On 6/23/23 18:29, Zack Newman wrote:
On 6/23/23 11:19, Stephan Neuhaus wrote:
# Rule 5
match out log on em0 from athn0:network to any nat-to (em0)

# Rule 6
pass out log on em0 from athn0:network to any

Rule 5 replaces the source IP address with the IP address assigned to
em0-as well as replaces the source port (for TCP and UDP) with an
ephemeral port. Rule 6 does _not_ pass traffic out of em0 from the IP
address assigned to em0 but instead passes traffic where the IP address
is from athn0:network, so of course it won't work.

Thanks for replying!

What you say may well be true, but if it is, it is in
conflict with the documentation and IMO the match/pass
combo is much less useful.

To make my first point, the pf FAQ says the following
about match/pass:

match
When a packet traverses the ruleset and matches a match rule, any optional parameters specified in that rule are remembered for future use (made "sticky").

pass
This rule allows the packet to be transmitted. If the packet was previously matched by a match rule where parameters were specified, they will be applied to this packet. [...]

This makes it very clear (to me at least) that the
nat-to in the match rule is "remembered for
future use" in the match, and is applied to the packet
only when it is finally subject to a pass rule.

The FAQ also has the following example:

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

This is what I meant when I said that I took my code
"almost verbatim" from the FAQ.

Also, "The Book of pf", 3rd ed., has a similar match/pass combo on p.53:

match out on $ext_if inet from $localnet nat-to ($ext_if)
pass quick inet proto { tcp, udp } from $localnet to port $udp_services

(See how the "from" address in the pass rule is
$localnet, which would match the packet's original
source address, and not $(ext_if)?)

To make my second point, If the packet would
immediately change its effective source address to
that of the outgoing interface, it would for example
become very hard in later rules to distinguish between
NATed packets and packets originating on the firewall, at least in pass out rules.

It would be a lot easier to just have a pass out rule and only filter
ingress traffic.

Agreed, but at this stage, I'm only trying to understand what's going on.


Is there anything you see in these rules, especially
in rules 5 and 6, that is not correct? I don't think
so, I've taken this almost verbatim from the pf FAQ
https://www.openbsd.org/faq/pf/nat.html.

You did not read that FAQ carefully enough, so I wouldn't say you
have followed it "almost verbatim". Under Configuring NAT, the example
shows

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]

Notice the pass out rule which states "from *ext_addr*" _not_ "from
src_addr".


Agreed! These very lines were the subject of a previous post of mine, and two people from t...@openbsd.org said that it was a typo and that the ext_addr in the pass rule should be changed to src_addr. See https://marc.info/?l=openbsd-tech&m=168714686620055&w=2 Note also that these lines are in conflict with the example that comes later in the FAQ, and which I have quoted above.

You are also not specifying the IP version which you likely should since
you probably don't want to rely on NAT for IPv6. For example

match out log on em0 inet from athn0:network nat-to (em0)
pass out

Fair point, thanks.

Cheers

Stephan

Reply via email to