Changes in pf: Packet Filtering
Pages: 1, 2, 3, 4, 5, 6
Which protocol(s) will be filtered (proto)?
Another layer of filtering is filtering by protocol name or number.
This is done with an addition of the proto keyword
followed by the name(s) or number(s) of protocols that the packets are
formed in accordance with. The list of protocols can be found in
/etc/protocols.
For example, if you want to let in only TCP packets, use this rule:
pass in quick on $ext_if proto tcp
Tip: Almost all popular services use TCP. You
should block UDP packets sent to servers that only use TCP, because
such packets are almost never legitimate traffic. If you do not know
which protocol is used by which services, check
/etc/protocols. This file is current as of the time of
release of the OpenBSD system you are using. The latest and the
freshest listings are always in the IANA's online database.
What is the packet's source address (from, any,
all)?
Source address filtering is typically used to stop two kinds of packets: those originating from hosts with legal IP addresses that we do not want to accept traffic from, and those that carry spoofed source addresses. In the first case, you will want to block packets from legal IP addresses if they're giving you so much trouble that you'd rather not accept traffic from them. In the second case, you ought to block packets with spoofed source addresses for your own safety as they will never be legitimate traffic. The following rule blocks packets with spoofed source addresses sent from external hosts and arriving on the firewall's external interface:
$blockIPs = {10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, \
224.0.0.0/4, 240.0.0.0/5, 127.0.0.0/8, 0.0.0.0}
block in quick on $ext_if from $blockIPs
Conversely, we can specify addresses of hosts that we want to accept traffic from, as in:
block in quick on $ext_if from ! $allow_ad to any
Tip: Note the exclamation mark (!),
which negates the value that follows it, so the rule above reads
"block incoming packets (and don't match them against other filtering
rules) arriving on the external interface send from all IP addresses
except $allow_ad and destined for any host."
There are two shortcuts that you can use to specify wider ranges of
IP addresses. One is the any keyword, which when placed
after from or to, matches any source
(from any) or target (to any) address:
block in quick on $log_if from any to $log_ad
block in quick on $ext_if from $blockIPs to any
The second shortcut is the all keyword which replaces
from any to any. The following two rules are
synonymous:
block in on $ext_if from any to any
block in on $ext_if all
Tip: from and to go together, and
you cannot write a rule with just either of them.
Source address specification is a required part of
any packet filtering rule, even if you use an all-encompassing
any or all shortcuts.
What is the source port of the packet (port)?
For a finer degree of control, we can block or pass packets sent
from a specific port on the interface from which the matching packets
were sent. The port specification is listed after the source address
specification and is marked with the port keyword, as
in:
block in on $ext_if proto tcp from any port 80
The port 80 is equivalent to port = 80
Other possible operators are <, >,
<=, >=, !=,
<>, and ><. Their use is shown
in the following rules:
# block packets destined for port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port = 80
# block packets destined for all ports except port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port != 80
# block packets destined for ports lower than port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port < 80
# block packets destined for ports lower than and port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port <= 80
# block packets destined for ports higher than and equal to port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port > 80
# block packets destined for ports higher than and equal to port 80
block in on $ext_if proto tcp from any to $dmz_www_ad port >= 80
# block packets destined for ports higher than port 80 and lower than port 1024
block in on $ext_if proto tcp from any to $dmz_www_ad port 80 >< 1024
# block packets destined for ports lower than port 80 and higher than port 1024
block in on $ext_if proto tcp from any to $dmz_www_ad port 80 <> 1024
Specifying port numbers makes sense only for those protocols that
carry source port information (like TCP or UDP). That is why you need
to use the proto keyword when you use the
port keyword. Otherwise, pfctl(8)
will complain and refuse to load rules.
Destination IP address (to, any,
all)
Destination address filtering is typically used to pass only those packets that are destined to addresses where there are servers listening for connections, for example:
pass in on $ext_if from any to $dmz_www_ad
All syntax rules for source addresses discussed earlier are applicable to destination addresses.
Source target address specification is a required
part of any packet filtering rule, even if you use an all-encompassing
any or all shortcuts.
Destination port (port)
The destination port specification follows the destination address specification. All rules that apply to source ports, apply to destination ports. Of course, both are independent. You will probably use destination ports more often than source ports, as such rules are usually used to only let those packets through that are destined to ports where appropriate servers are listening, for example:
pass in on $ext_if proto tcp from any to $ext_www_ad port $ext_www_port
pass in on $ext_if proto tcp from any to $ext_smtp_ad port $ext_smtp_port
pass in on $ext_if proto tcp from any to $ext_ftp_ad port $ext_ftp_port