Thursday, February 24, 2022

Re: PF bi-nat

On Thu, Feb 24, 2022 at 02:14:55PM +0000, Laura Smith wrote:

> Thanks David for your comprehesive reply. It looks like perhaps the match trick is the cleanest way.

BTW, IMO the descriptin and example in the man page of pf.conf is more
clear than the FAQ.

-Otto

>
>
> ------- Original Message -------
>
> On Thursday, February 24th, 2022 at 11:27, David Gwynne <david@gwynne.id.au> wrote:
>
> > On Wed, Feb 23, 2022 at 04:55:05PM +0000, Laura Smith wrote:
> >
> > > I've never had occasion to use bi-nat before and I'm struggling a little to wrap my head around the concept.
> > >
> > > The OpenBSD FAQ (https://www.openbsd.org/faq/pf/nat.html) gives the following example:
> > >
> > > "pass on tl0 from $web_serv_int to any binat-to $web_serv_ext"
> > >
> > > However I'm not clear on how this fits into the overall filtering strategy ? i.e. building logically on the example above, how do I say "only allow inbound bi-nat for ports 80 & 443".
> > >
> > > The FAQ makes an obscure statement "TCP and UDP ports are never modified with binat-to rules as they are with nat rules.", which I'm guessing is where the answer lies. But I'm not clear what this means in context ?
> > >
> > > Thanks !
> >
> > turns out binat is syntactic sugar, so it can be understood in terms of
> >
> > nat and rdr rules. let's say 192.0.2.1 is your external ip, 10.0.0.1
> >
> > is your internal ip, and em0 is your external interface:
> >
> > dlg@ix ~$ echo 'pass on em0 inet from 10.0.0.1 to any binat-to 192.0.2.1' | pfctl -vnf -
> >
> > pass out on em0 inet from 10.0.0.1 to any flags S/SA nat-to 192.0.2.1 static-port
> >
> > pass in on em0 inet from any to 192.0.2.1 flags S/SA rdr-to 10.0.0.1
> >
> > i read that as any connection to my external ip is forwarded to the
> >
> > backend, and any connection from my backend server is rewritten to
> >
> > appear as if it's coming from my external ip. this could be useful if
> >
> > you've got a small public ip address allocation (eg a /29) from an
> >
> > ISP and don't want to burn the network and broadcast addresses by
> >
> > putting them on an actual subnet. you would binat every public IP
> >
> > to a backend on a private IP instead. id personally use p2p tunnels
> >
> > from the router to each backend, but maybe MTU/MRU is precious too?
> >
> > anyway, in terms of policy, restricting this to ports 80 and 443
> >
> > looks a bit clumsy:
> >
> > dlg@ix ~$ echo 'pass on em0 inet from 10.0.0.1 to any port { 80 443 } binat-to 192.0.2.1' | pfctl -vnf -
> >
> > stdin:1: port only applies to tcp/udp
> >
> > stdin:1: skipping rule due to errors
> >
> > stdin:1: port only applies to tcp/udp
> >
> > stdin:1: skipping rule due to errors
> >
> > stdin:1: port only applies to tcp/udp
> >
> > stdin:1: skipping rule due to errors
> >
> > stdin:1: rule expands to no valid combination
> >
> > stdin:1: port only applies to tcp/udp
> >
> > stdin:1: skipping rule due to errors
> >
> > stdin:1: port only applies to tcp/udp
> >
> > stdin:1: skipping rule due to errors
> >
> > stdin:1: rule expands to no valid combination
> >
> > stdin:1: rule expands to no valid combination
> >
> > dlg@ix ~$ echo 'pass on em0 inet proto tcp from 10.0.0.1 to any port { 80 443 } binat-to 192.0.2.1' | pfctl -vnf -
> >
> > pass out on em0 inet proto tcp from 10.0.0.1 to any port = 80 flags S/SA nat-to 192.0.2.1 static-port
> >
> > pass in on em0 inet proto tcp from any port = 80 to 192.0.2.1 flags S/SA rdr-to 10.0.0.1
> >
> > pass in on em0 inet proto tcp from any port = 443 to 192.0.2.1 flags S/SA rdr-to 10.0.0.1
> >
> > pass out on em0 inet proto tcp from 10.0.0.1 to any port = 443 flags S/SA nat-to 192.0.2.1 static-port
> >
> > pass in on em0 inet proto tcp from any port = 443 to 192.0.2.1 flags S/SA rdr-to 10.0.0.1
> >
> > yeah. im not sure the pass out rules are that useful in practice.
> >
> > if you had a default allow policy, then binat could make sense. you'd
> >
> > have a pass binat rule followed by block rules to filter out the
> >
> > exceptions to your default policy.
> >
> > another option could be using match and tags:
> >
> > dlg@ix ~$ cat /tmp/rules
> >
> > match on em0 inet from 10.0.0.1 to any binat-to 192.0.2.1 tag backend
> >
> > pass out on em0 tagged backend
> >
> > pass in on em0 inet proto tcp to port { 80 443 } tagged backend
> >
> > dlg@ix ~$ pfctl -vnf /tmp/rules
> >
> > match out on em0 inet from 10.0.0.1 to any tag backend nat-to 192.0.2.1 static-port
> >
> > match in on em0 inet from any to 192.0.2.1 tag backend rdr-to 10.0.0.1
> >
> > pass in on em0 inet proto tcp from any to any port = 80 flags S/SA tagged backend
> >
> > pass in on em0 inet proto tcp from any to any port = 443 flags S/SA tagged backend
> >
> > pass out on em0 all flags S/SA tagged backend
> >
> > dlg
>

No comments:

Post a Comment