Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Jan 2015 10:33:20 +0800
From:      Julian Elischer <julian@freebsd.org>
To:        lev@FreeBSD.org, freebsd-net@freebsd.org
Subject:   Re: ipfw, nat and stateful firewall: why "keep-state" on "skipto" works at all and how do this properly?
Message-ID:  <54CAED70.1080501@freebsd.org>
In-Reply-To: <54CAD234.3020407@FreeBSD.org>
References:  <54CAD234.3020407@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On 1/30/15 8:37 AM, Lev Serebryakov wrote:
> -----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
ok so the dynamic rule is created on the outgoing packet, and 
associated with
   skipto 12900
which sets up a NAT session.

on a later incoming packet, the rule 11500 is hit first so the packets 
are NAT'd back,
and then their state is compared to that stored in the outgoing path, 
and if they match, they go to 12900
where they are not checked again becasue they are not 'out' packets.
so it falls through to 12999 and is allowed in. (in its changed form).
packets that are not in a known session fall through teh check-state 
and are dropped.

it all looks ok to me. kinda cute actually.

>   It was migrated from old copy'n'pasted "divert" variant (created
> before "nat" action was created!).
>
>   Looks like, it does not what I want at all! It works only by
> accident, as "check-state" becomes "skipto 12900" and it is works only
> because 12999 is "allow ip from any to any" and not some other filtration!
>
>   Is here better way to have nat and stateful ruleset?
It would be really cool if state could hold the NAT'd form of the
packets as well. but what you have above is really kinda cute,
and seems to work as far as I can read.
what "other filtration" do you want?


I always do what is done here and separate inwards and outwards
packets for the external interface into two different sets of rules
(and another set for other interfaces).

I find it helps to draw a packet flow with two chains,  in and out..
with samples of what the packets look like for each flow at each point.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?54CAED70.1080501>