On 2023-06-24, Stephan Neuhaus <s...@artdecode.de> wrote:
> Hi Zack
>
> On 6/24/23 03:39, Zack Newman wrote:
>> There do appear to be contradictions in documentation as well as the pf
>> book. The Configuring NAT section is correct as you have seen with your
>> own rules.
>
> I'm not sure about the Configuring NAT section being
> correct. I still maintain that the documentation and
> observed behaviour are different.

The pf.conf(5) manual page is the best documentation for PF and that
is expected to be correct.

The pf faq could well be wrong, it's not really had a full
review/update/rewrite since before nat-to was introduced - a relatively
light conversion to the "new" syntax and mostly smaller changes -
no integration of new features in the existing text e.g. the very
useful tag/tagged is relegated to an added on "advanced features"
section).

> I now have the following small ruleset. The rules for
> ports 22 and 53 are just so that I can do my
> experiments over ssh. (Port 53 may not be necessary
> but the blocked packets mess up my logs.) The em0

You can always follow a general "block log" with a "block on port XX"
if you want to log most blocked psckets except for certain ones.

> interface has the IPv4 address 192.168.0.2.
>
> set skip on lo
>
> block log all
>
> pass in on em0 proto tcp to any port 22
> pass out on em0 proto tcp from any port 22
> pass on em0 proto udp from any port 53
> pass on em0 proto udp to any port 53

This allows someone on the internet to bypass your filter rules and
send UDP traffic to any port by simply setting the source port to 53.

Just have "to port 53", reply ("from port 53") packets will match
the state created by the packet that was passed by the "to port 53"
rule.

(You would have the same with TCP except for the direction on the
rule; still "pass out proto tcp from port 22" is probably not quite
what you want).

> I now think that either the documentation is wrong, or
> pf is wrong.  At any rate, there seems to be a rather
> serious disconnect between the two. The FAQ clearly
> says:
>
> When a packet is selected by a match rule, parameters (e.g. nat-to) in 
> that rule are remembered and are applied to the packet when a pass rule 
> matching the packet is reached.

Yes that's wrong. Address changes take effect at the time the match rule
is processed when traversing the ruleset; rules processed later "see"
the rewritten address. As pf.conf(5) says,


   Translation
     Translation options modify either the source or destination address
     and port of the packets associated with a stateful connection.  pf(4)
     modifies the specified address and/or port in the packet and
     recalculates IP, TCP, and UDP checksums as necessary.

     If specified on a match rule, subsequent rules will see packets as
     they look after any addresses and ports have been translated.  These
     rules will therefore have to filter based on the translated address
     and port number.


> I know that the documentation (at this time) ALSO
> says:
>
> match out on interface [af] \
>     from src_addr to dst_addr \
>     nat-to ext_addr [pool_type] [static-port]
> [...]
> pass out [log] on interface [af] [proto protocol] \
>     from ext_addr [port src_port] \
>     to dst_addr [port dst_port]
>
> where the pass rule has ext_addr instead of src_addr,
> but at least two people on t...@openbsd.org have
> confirmed that this is a bug and have already
> submitted a diff that replaces ext_addr with src_addr
> in the pass rule, see 
> https://marc.info/?l=openbsd-tech&m=168714686620055&w=2

I think that this bit _is_ correct as written, although it's not
particularly useful as it doesn't allow passing just the specific
translated packets.

I think it's the example rules which are wrong, i.e.

match out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.1
pass on tl0 from 192.168.1.0/24 to any

directly fixing this would be

match out on tl0 from 192.168.1.0/24 to any nat-to 198.51.100.1
pass on tl0 from 198.51.100.1 to any

however this would be a good place to instead show how to use
match...nat-to...tag and pass...tagged, maybe also received-on. Then a)
it's clear what traffic is passed and b) that fits better with the very
common use-case where the external (nat-rewritten) address is dynamic so
you need to use an interface name with parentheses in the nat-to rule.

But when you pull at that thread, the current structure of the pf faq
section starts to unravel, i.e. it doesn't make sense to separate tags
into "advanced", there's a fair bit of information which really isn't
useful at the faq level (flag matching? the bit about using "block
return" instead of a set of 6 different block rules that nobody learning
from the faq would have thought of writing? syn proxy, esoteric scrub
rules, being originally written from a point-of-view of "keep state"
being a special thing and tweaked from that to the current state, ...)
and it becomes a fairly big authoring job.

> Should I be taking this to another mailing list?
> Should I be submitting a bug report? Or am I just
> really really dense and am just too stupid to read the
> documentation correctly?

Don't know really... In the absence of someone with good knowledge of pf
and time+patience to craft an improved faq section, I'd mostly stick to
getting information from the manpage for now... (you can get a nicely
formatted version with "mandoc -T pdf /usr/share/man/man5/pf.conf.5 >
pf.pdf").

Reply via email to