Tuesday, December 05, 2006

Packet Filter

Today I have been going over all of the documents on Packet Filter (pf). The following are the notes which I made while reading (The notes are not complete, just my reference):

Activation from boot:
Edit /etc/rc.conf.local adding:

Activation using pfctl(8):
The pfctl program allows us to activate pf using:
# pfctl -e
And deactivate pf using:
# pfctl -d

*Note that this just enables or disables PF, it doesn't actually load a ruleset. The ruleset must be loaded separately, either before or after PF is enabled.
At boot time pf reads /etc/pf.conf for it's configuration. The file has several parts:
  • Macros: User-defined variables that can hold IP addresses, interface names, etc.
  • Tables: A structure used to hold lists of IP addresses.
  • Options: Various options to control how PF works.
  • Scrub: Reprocessing packets to normalize and defragment them.
  • Queuing: Provides bandwidth control and packet prioritization.
  • Translation: Controls Network Address Translation and packet redirection.
  • Filter Rules: Allows the selective filtering or blocking of packets as they pass through any of the interfaces.
Lists allow one rule to contain multiple items, e.g. multiple IP addresses, port numbers etc. Lists are defined by specifying items within { } brackets. e.g:
block out on rl0 from (, } to any

When loading a ruleset and a list is encountered by the pfctl(8) program multiple rules are created. e.g. If pfctl found the above rule it would expand that to:
block out on rl0 from to any
block out on rl0 from to any

*Note that the commas between list items are optional.

Macros are user-defined variables. They can hold port numbers, IP addresses etc.
Macro names must start with a letter and may contain letters, digits, and underscores. e.g.:
int_if = "sis0"
pass in on $int_if from any to any
Macros can also contain lists.

Tables hold a groups of IP addresses. Tables are different from lists in that the lookups use less memory and processor and therefore are very fast.
Tables can be used in the following ways:
  • source and/or destination address in filter, scrub, NAT, and redirection rules.
  • translation address in NAT rules.
  • redirection address in redirection rules.
  • destination address in route-to, reply-to, and dup-to filter rule options.
To create a table in pf.conf the table directive is used. There are two attributes that can be specified for each table:
  • const - Once the table has been created the contents can not be changed. If this attribute is not specified; address can be added or removed using pfctl.
  • persist - Keep table in memory even if no rules are referring to it.
For Example:
table <MyNet> {, ! }
table <rfc1918> const {,, }
table <spammers> persist file "/etc/spammers"

block in on vr0 from { <rfc1918>, <spammers> } to any
pass in on vr0 from <MyNet> to any

The file /etc/spammers would contain a list of IP addresses and/or CIDR network blocks, one per line. Any line beginning with # is treated as a comment and ignored.
Tables can also be manipulated with pfctl, see: pfctl(8).

Packet Filter
A highly simplified syntax for filter rules is:
action [direction] [log] [quick] [on interface] [af] [proto protocol] \
[from src_addr [port src_port]] [to dst_addr [port dst_port]] \
[flags tcp_flags] [state]

Default Deny
In a default deny filter policy, the first filter rules are:
block in all
block out all

Now traffic has to passed by the firewall other wise it will be dropped.

If a packet matches a rule which is using the quick keyword, then no other processing is needed, and the specified action is taken.

Keeping State
Keeping state or stateful inspection allows pf to keep track of network connection. Information is stored about each connection in a state table, and pf then determines if a passing packet belongs to an established connection, if it does the packet is passed.
When a rule has the keep state option, the first packet matching the rule creates a "state" between the sender and receiver. Now, not only do packets going from the sender to receiver match the state entry and bypass ruleset evaluation, but so do the reply packets from receiver to sender. For example:
pass out on fxp0 proto tcp from any to any keep state
Stateful filtering has a number of options:
  • max number: The max number of state entries the rule can create.
  • source-track: Track number of states created per IP.
  • max-src-nodes number: limit the number of source IP addresses that can simultaneously create state.
  • max-src-states number: When the source-track option is used, max-src-states will limit the number of simultaneous state entries that can be created per source IP address.
If a connection has completed the 3-way handshake, then other restrictions can apply to stateful connections:
  • max-src-conn number: The maximum number of simultaneous TCP connections which a single host can make.
  • max-src-conn-ratenumber / interval: Limit the rate of new connections to a certain amount per time interval.
  • overload <table>: Put an offending host's IP address into the named table.
  • flush [global]: Kill any other states that match this rule and that were created by this source IP. When global is specified, kill all states matching this source IP, regardless of which rule created the state.
TCP Flags
  • F : FIN - Finish; end of session
  • S : SYN - Synchronize; indicates request to start session
  • R : RST - Reset; drop a connection
  • P : PUSH - Push; packet is sent immediately
  • A : ACK - Acknowledgement
  • U : URG - Urgent
  • E : ECE - Explicit Congestion Notification Echo
  • W : CWR - Congestion Window Reduced
In a rule flags are specified using the following syntax: flags check/mask
The mask tells pf to only inspect the specified flags.
The check specified which flag must be "on" in the header for a match

Proxy the handshake; pf will complete a client handshake, initiate a server handshake, then pass the packets between the two. e.g.:
pass in on $ext_if proto tcp from any to $web_server port www flags S/SA synproxy state
synproxy state also includes the same functionality as keep state and modulate state

Blocking Spoofed Packets
pf uses the antispoof keyword to protect against spoofing.:
antispoof [log] [quick] for interface [af]

Unicast Reverse Path Forwarding
An uRPF check compares the source IP of a packet with the routing table, to see if the outbound interface in the routing table is the same as the packet.
This check is performed using the urpf-failed keywords in filter rules:
block in quick from urpf-failed label uRPF

OS finger Printing
Using the os keyword in a rule, can detect the operating system of a remote host.

IP Options
To allow packets with IP options set which are block by default you need to use the allow-opts keyword.

NAT - Network Address Translation
A highly simplified syntax for a NAT rule is:
nat [pass [log]] on interface [af] from src_addr [port src_port] to dst_addr [port dst_port] -> ext_addr [pool_type] [static-port]

Example: (tl0 is external, dc0 internal):
nat on tl0 from dc0:network to any -> (tl0)
This rule says to perform NAT on the tl0 interface for any packets coming from the dc0 interfaces network and to replace the source IP with the current address of the tl0 interface.

Bidirectional Mapping (1:1 mapping)
A bidirectional mapping can be established by using the binat rule. A binat rule establishes a one to one mapping between an internal IP address and an external address.

Rule Exceptions
Exceptions can be made to translation rules by using the no keyword. e.g.:
no nat on tl0 from to any
nat on tl0 from to any ->

The entire network would have its packets translated to the external address except for
The no keyword can be used with nat, binat and rdr rules.

NAT Status
To view the active NAT translations pfctl(8) is used with the -s state option.

Redirection (Port Forwarding)
Redirection allows
incoming traffic to be sent to a machine behind the NAT gateway.e.g.:
rdr on tl0 proto tcp from any to any port 80 ->
This line redirects TCP port 80 (web server) traffic to a machine inside the network at So, even though is behind your gateway and inside your network, the outside world can access it.