Path MTU discovery

The last bit I will remind you about when it comes to troubleshooting is the 'path MTU discovery'. Internet protocols are designed to be device independent, and one consequence of device independence is that you can not always predict reliably what the optimal packet size is for a given connection. The main constraint on your packet size is called the Maximum Transmission Unit, or MTU, which sets the upper limit on the packet size for an interface. The ifconfig command will show you the MTU for your network interfaces.

The way modern TCP/IP implementations work, they expect to be able to determine the right packet size for a connection through a process which simply puts involves sending packets of varying sizes with the 'Do not fragment' flag set, expecting an ICMP return packet indicating "type 3, code 4", when the upper limit has been reached. Now you don't need to dive for the RFCs right away. Type 3 means "destination unreachable", while code 4 is short for "fragmentation needed, but the do not fragment flag is set". So if your connections to networks which may have other MTUs than your own seem sub-optimal, and you do not need to be that specific, you could try changing your list of ICMP types slightly to let the Destination unreachable packets through, too:

icmp_types = "{ echoreq, unreach }"

as we can see, this means we do not need to change the pass rule itself:

pass inet proto icmp all icmp-type $icmp_types

It's also possible to just allow the code 4 of type 3, instead of all codes.

pass inet proto icmp all icmp-type unreach code needfrag 

PF lets you filter on all variations of ICMP types and codes, and if you want to delve into what to pass and not of ICMP traffic, the list of possible types and codes are documented in the icmp(4) and icmp6(4) man pages. The background information is available in the RFCs[1] .

Notes

[1]

The main internet RFCs describing ICMP and some related techniques are RFC792, RFC950, RFC1191, RFC1256, RFC2521, rfc2765, while necessary updates for ICMP for IPv6 are found in RFC1885, RFC2463, RFC2466. These documents are available in a number of places on the net, such as the ietf.org and faqs.org web sites, and probably also via your package system.

It is quite possible that I will return to ICMP filtering in a future advanced section of the tutorial.