Solved Sharing know-how: SSH connection locks when loading ipfw_nat Kernel module (ipfw/NAT/SSH)

roccobaroccoSC

Aspiring Daemon

Reaction score: 210
Messages: 722

Hi, I am posting this just to share my knowledge about a problem that I was not able to find a good documentation for.
I use IPFW with NAT on a FreeBSD 12.2-RELEASE host and use it as a gateway to a number of jails on the host. I set up a custom firewall script and load a number of IPFW rules with NAT, which work very well, except for one case:
The very first time (before the machine was configured for NAT), I install the custom script and enable IPFW with the commands listed below.
Code:
# Generate custom script IPFW_RULES here...

sysrc gateway_enable="YES"
sysrc firewall_enable="YES"
sysrc firewall_nat_enable="YES"
sysrc firewall_logging="YES"
sysrc firewall_script="${IPFW_RULES}"
sysrc natd_enable="NO"

sysrc kld_list+="ipfw_nat"
kldstat -qm ipfw_nat || kldload ipfw_nat  # SSH connection freezes here!

service ipfw restart
ipfw resetlog

Right after kldload ipfw_nat my SSH connection freezes and another SSH connection to the machine is not possible. I have to log in via a local console and execute the script, then everything works just fine.
I can even execute the script again via SSH and it works perfectly. Only when the kernel module ipfw_nat.ko is not loaded and I load it, the connection breaks.

I wanted to fix it and be able to initialize my firewall settings on a pristine host without interrupting the SSH session.

I did some research and found the following forum thread from 2008: https://forums.freebsd.org/threads/routing-all-traffic-through-a-vpn-tunnel.476/#post-2384
P.S.: After kldload ipfw.ko by default all packets will be dropped, so you can lock out machine if you working through ssh
They did not elaborate on how this can be worked around though. :(

Also, in the ipfw(8) man page I read this:
If you are logged in over a network, loading the kld(4) version of
ipfw is probably not as straightforward as you would think. I recom-
mend the following command line:

kldload /modules/ipfw.ko && \
ipfw add 32000 allow ip from any to any

Along the same lines, doing an

ipfw flush

in similar surroundings is also a bad idea.
Solution
I assumed the same applies to loading ipfw_nat.ko as in my case, so I just tried changing my script to relax the firewall temporarily when loading ipfw_nat (as suggested by the man page):
Code:
# Generate custom script IPFW_RULES here...

sysrc gateway_enable="YES"
sysrc firewall_enable="YES"
sysrc firewall_nat_enable="YES"
sysrc firewall_logging="YES"
sysrc firewall_script="${IPFW_RULES}"
sysrc natd_enable="NO"

sysrc kld_list+="ipfw_nat"
kldstat -qm ipfw_nat || kldload ipfw_nat  && ipfw add    100 allow ip from any    to any

service ipfw restart
ipfw resetlog

This worked and the SSH connection does not break anymore.

Securitywise it's probably worth to note that the firewall is down for a couple of milliseconds before reloading the rules but as it is initially off, it does not make any practical difference.
Please comment on this! Is this solution correct? Is there an easier way?

Thanks.
 
Top