Discussion:
pf: antispoof with dynamic IP address?
Mogens Jensen
2021-05-21 05:32:32 UTC
Permalink
The antispoof directive will expand to two block rules with IP address
of the interface, so I would think that with a dynamic IP, the interface
should be surrounded in parentheses like this:

antispoof for (wi0)

But this seems to be wrong, as I have not read any guide or FAQ that
does this, e.g. the "Building a router" guide found at
https://www.openbsd.org/faq/pf/example1.html#pf

In the gateway configuration, egress group is surrounded with
parentheses in multiple places, but not with antispoof:

antispoof quick for { egress $wired $wifi }

Why should this not be

antispoof quick for { (egress) $wired $wifi }

or

antispoof quick for { (egress:0) $wired $wifi }

Another thing I was wondering about while reading the manpage for
pf.conf:

===
The simplest mechanism to block everything by default and only pass
packets that match explicit rules is specify a first filter rule of:

block all
===

Is it not even simpler to just specify the filter rule as block without
all, they seem to expand identical?

Thanks.

Mogens Jensen
Peter N. M. Hansteen
2021-05-21 08:22:21 UTC
Permalink
Post by Mogens Jensen
The antispoof directive will expand to two block rules with IP address
of the interface, so I would think that with a dynamic IP, the interface
antispoof for (wi0)
quoting pf.conf(5):

" The antispoof directive expands to a set of filter rules which will block
all traffic with a source IP from the network(s) directly connected to
the specified interface(s) from entering the system through any other
interface."

This means essentially that the sample rules would fail to be effective
only if the interface you antispoof for has switched networks. I think
that is a relatively rare event for running firewalls and not doing a ruleset
reload.
Post by Mogens Jensen
===
The simplest mechanism to block everything by default and only pass
block all
===
Is it not even simpler to just specify the filter rule as block without
all, they seem to expand identical?
You're right, they expand to the exact same thing:

[Fri May 21 10:19:50] ***@zelda:~$ cat blockonly
block
[Fri May 21 10:19:57] ***@zelda:~$ cat blockall
block all
[Fri May 21 10:20:01] ***@zelda:~$ doas pfctl -vnf blockall
block drop all
[Fri May 21 10:20:11] ***@zelda:~$ doas pfctl -vnf blockonly
block drop all

(also see eg http://home.nuug.no/~peter/pf/newest/simplest-secure.html)

Cheers,
Peter
--
Peter N. M. Hansteen, member of the first RFC 1149 implementation team
http://bsdly.blogspot.com/ http://www.bsdly.net/ http://www.nuug.no/
"Remember to set the evil bit on all malicious network traffic"
delilah spamd[29949]: 85.152.224.147: disconnected after 42673 seconds.
Mogens Jensen
2021-05-22 15:02:55 UTC
Permalink
" The antispoof directive expands to a set of filter rules which will block
all traffic with a source IP from the network(s) directly connected to
the specified interface(s) from entering the system through any other
interface."
This means essentially that the sample rules would fail to be effective
only if the interface you antispoof for has switched networks. I think
that is a relatively rare event for running firewalls and not doing a ruleset
reload.
I'm still struggling with understanding why it works, please bear with
me.

Let's say I'm assigned dynamic IP address 192.0.2.5/24 from my ISP on
external interface em0.

antispoof em0 inet

Expands to:

block drop in on ! em0 inet from 192.0.2.0/24 to any
block drop in inet from 192.0.2.5 to any

At some point when the IP lease is renewed, the ISP has assigned an
address from another block e.g. 203.0.113.21/24. I would now think that
the block rules created by antispoof are obsolete as they are not
updated with the new address, but why should it still work without
interface name in parentheses?

Thanks.

Mogens Jensen
Peter Nicolai Mathias Hansteen
2021-05-22 15:16:54 UTC
Permalink
Post by Mogens Jensen
Let's say I'm assigned dynamic IP address 192.0.2.5/24 from my ISP on
external interface em0.
antispoof em0 inet
block drop in on ! em0 inet from 192.0.2.0/24 to any
block drop in inet from 192.0.2.5 to any
At some point when the IP lease is renewed, the ISP has assigned an
address from another block e.g. 203.0.113.21/24. I would now think that
the block rules created by antispoof are obsolete as they are not
updated with the new address, but why should it still work without
interface name in parentheses?
I frankly haven’t tested what you describe in real life, but I think you have understood correctly. If your ISP throws you into a different network on lease renewal, things would go sideways without the parentheses.

The two expand slightly differently, btw:

[Sat May 22 17:14:23] ***@zelda:~$ cat antispoof
antispoof for ure0
[Sat May 22 17:14:27] ***@zelda:~$ doas pfctl -vnf antispoof
block drop in on ! ure0 inet from 10.10.10.0/24 to any
block drop in inet from 10.10.10.10 to any
[Sat May 22 17:14:30] ***@zelda:~$ cat antispoof_paren
antispoof for (ure0)
[Sat May 22 17:14:39] ***@zelda:~$ doas pfctl -vnf antispoof_paren
block drop in on ! ure0 from (ure0:network) to any
block drop in from (ure0) to any

(Just now on a -current machine)

All the best,
Peter N. M. Hansteen

—
Peter N. M. Hansteen, member of the first RFC 1149 implementation team
http://bsdly.blogspot.com/ http://www.bsdly.net/ http://www.nuug.no/
"Remember to set the evil bit on all malicious network traffic"
delilah spamd[29949]: 85.152.224.147: disconnected after 42673 seconds.
Stuart Henderson
2021-05-23 10:22:37 UTC
Permalink
Post by Mogens Jensen
" The antispoof directive expands to a set of filter rules which will block
all traffic with a source IP from the network(s) directly connected to
the specified interface(s) from entering the system through any other
interface."
This means essentially that the sample rules would fail to be effective
only if the interface you antispoof for has switched networks. I think
that is a relatively rare event for running firewalls and not doing a ruleset
reload.
I'm still struggling with understanding why it works, please bear with
me.
Let's say I'm assigned dynamic IP address 192.0.2.5/24 from my ISP on
external interface em0.
antispoof em0 inet
block drop in on ! em0 inet from 192.0.2.0/24 to any
block drop in inet from 192.0.2.5 to any
At some point when the IP lease is renewed, the ISP has assigned an
address from another block e.g. 203.0.113.21/24. I would now think that
the block rules created by antispoof are obsolete as they are not
updated with the new address, but why should it still work without
interface name in parentheses?
Thanks.
Mogens Jensen
"egress" is not really useful with antispoof anyway.

antispoof generates a set of rules to block packets with local network
addresses coming in on an unexpected interface (either the wrong
internal interface, or an external interface).

It does not generate rules to stop someone on an internal network
sending packets from another invalid address. For example even
listing all network interfaces in antispoof rules, someone on an
internal network can still send traffic with a source address
of (e.g.) 8.8.8.8.

To prevent that you'll need "block by default / allow specific source"
rules like "pass in on em0 from em0:network" (etc, for each interface),
or "block in from urpf-failed" (which does a dynamic route lookup;
simpler config but slightly higher per-connection overhead).

Loading...