ipfw, nat and stateful firewall: why "keep-state" on "skipto" works at all and how do this properly?

wishmaster artemrts at ukr.net
Fri Jan 30 09:42:38 UTC 2015



Hi, 

below my experience.
 
 --- Original message ---
 From: "Lev Serebryakov" <lev at freebsd.org>
 Date: 30 January 2015, 02:37:54
  


> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA512
> 
> 
> I have problems to understand how combination of nat and stateful
> ruleset for ipfw should work. There is no good guides, and most guides
> uses old "divert" which is different from in-kernel nat, as far as I
> understand.
> 
> Problem is, if we want to allow only incoming packets which are
> belong to already established connections, we need to create state in
> "allow" out rule for outbound packet BEFORE nat rule and then pass it
> to nat, which looks impossible, as "allow" stop processing. Or we
> could pass it to nat and then "allow keep-state", but then there will
> be same problem for inbound packets: "check-state" should go before
> "nat" rule, but packet should be passed to nat after that!
> 
> Now I have old ruleset which I don't quite understand. It works, but
> WHY? Now I have such rules for outbound packets:
> 
> 12700 skipto 12900 ip from any to any keep-state
> 12800 deny ip from any to any
> 12900 nat 1 ip from any to any out
> 12999 allow ip from any to any
> 
> And rules for inbound ones are:
> 
> 11000 deny ip from any to not me
> 11500 nat 1 ip from any to any
> 11510 check-state
> 11600 allow tcp from any to me ssh,http setup keep-state
> 11999 deny ip from any to any

At first, i think you should move keep-state from skipto to explicit allow rule.

Some explaining where check-state is useful for me. Packets, coming from LAN allow by rule 3205 and create keep-state rule; on ext_if nat and allow rule without keep-state (15000,15010) as it is already exists. On incoming on ext_if nat and keep-state rules and packets goes to the kernel. Any other packets from outside will be blocked.
Traffic from server itself allows by 15150 rule with keep-state and will be checked on incoming interface by rule 5020.

So in my case it is no need to have explicit allow rule after 'nat' rule on incoming direction on external interface. This is behavior like pf.

For my case with 4 ISP link I use something like this example, but more complex, though.

### IN int_if nfe0
$cmd 3000 check-state log

$cmd 3205 allow log ip4 from any to not me not 25 $ks     # allow to wild world to not 25 port only
$cmd 3210 allow log ip4 from any to me 22,21,20,80,81,3306,2112,5060,49000-65535 $ks
$cmd 3212 allow log ip4 from any 68 to me 67
$cmd 3215 allow log icmp from any to me icmptypes 0,3,4,8,11

$cmd 3499 deny log all from any to any

### OUT ext_if sk0
$cmd 15000 nat 1 log ip4 from not me to not me recv "*"  # for LAN only
$cmd 15010 allow log ip4 from me to not me recv "*"       # for LAN only

$cmd 15150 allow log ip4 from me to any $ks               # for server's traffic only

$cmd 15999 deny log all from any to any

### IN ext_if sk0
$cmd 5000 nat 1 log ip4 from any to me

$cmd 5020 check-state log

$cmd 5100 allow log tcp from any to me 22 setup limit src-addr 3  # to server itself
$cmd 5200 allow log tcp from any to "table(12)" 80,81,443,5555 setup limit src-addr 20  # to jails
$cmd 5310 allow log icmp from any to any icmptypes 0,3,4,8,11

$cmd 5999 deny log all from any to any


Cheers,
Vitaly



More information about the freebsd-net mailing list