diff options
author | darrenr <darrenr@FreeBSD.org> | 2001-10-20 04:17:07 +0000 |
---|---|---|
committer | darrenr <darrenr@FreeBSD.org> | 2001-10-20 04:17:07 +0000 |
commit | 7460780f26ddb1a56ce9edcfda0fc5bdf0654760 (patch) | |
tree | a215edcaca466164008dd39dec8b0d08291f40cb /share/examples | |
parent | 11dcd7407753aacaf46341311b4da0e4693142e8 (diff) | |
download | FreeBSD-src-7460780f26ddb1a56ce9edcfda0fc5bdf0654760.zip FreeBSD-src-7460780f26ddb1a56ce9edcfda0fc5bdf0654760.tar.gz |
Add the IPFilter how-to and other related documents to the base install
so that users gets ipfilter examples without a source install.
PR: 26763
Submitted by: Cyrille Lefevre <clefevre@poboxes.com>
Diffstat (limited to 'share/examples')
-rw-r--r-- | share/examples/ipfilter/Makefile | 33 | ||||
-rw-r--r-- | share/examples/ipfilter/README | 15 | ||||
-rw-r--r-- | share/examples/ipfilter/example.14 | 62 | ||||
-rw-r--r-- | share/examples/ipfilter/examples.txt | 515 | ||||
-rw-r--r-- | share/examples/ipfilter/firewall.1 | 36 | ||||
-rw-r--r-- | share/examples/ipfilter/firewall.2 | 70 | ||||
-rw-r--r-- | share/examples/ipfilter/ipf-howto.txt | 3168 | ||||
-rw-r--r-- | share/examples/ipfilter/ipf.conf.permissive | 30 | ||||
-rw-r--r-- | share/examples/ipfilter/ipf.conf.restrictive | 77 | ||||
-rw-r--r-- | share/examples/ipfilter/ipf.conf.sample | 19 | ||||
-rw-r--r-- | share/examples/ipfilter/ipnat.conf.sample | 3 | ||||
-rw-r--r-- | share/examples/ipfilter/rules.txt | 182 |
12 files changed, 4210 insertions, 0 deletions
diff --git a/share/examples/ipfilter/Makefile b/share/examples/ipfilter/Makefile new file mode 100644 index 0000000..f2f27b8 --- /dev/null +++ b/share/examples/ipfilter/Makefile @@ -0,0 +1,33 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../contrib/ipfilter/rules + +BINDIR= /usr/share/examples + +FILES= README + +# dist sample files +FILES+= BASIC.NAT BASIC_1.FW BASIC_2.FW \ + example.1 example.2 example.3 example.4 example.5 \ + example.6 example.7 example.8 example.9 example.10 \ + example.11 example.12 example.13 example.sr firewall \ + ftp-proxy ftppxy nat-setup nat.eg server tcpstate + +# ftp://ftp.OpenBSD.org/pub/OpenBSD/src/share/ipf/ sample files. +FILES+= example.14 firewall.1 firewall.2 \ + ipf.conf.permissive ipf.conf.restrictive \ + ipf.conf.sample ipnat.conf.sample + +# http://www.obfuscation.org/ipf/ how-to +FILES+= ipf-howto.txt + +# http://coombs.anu.edu.au/~avalon/ sample files +FILES+= examples.txt rules.txt + +all: + +install: ${FILES} + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${SHAREMODE} \ + ${.ALLSRC} ${DESTDIR}${BINDIR}/ipfilter + +.include <bsd.prog.mk> diff --git a/share/examples/ipfilter/README b/share/examples/ipfilter/README new file mode 100644 index 0000000..aefd2cd --- /dev/null +++ b/share/examples/ipfilter/README @@ -0,0 +1,15 @@ +# $FreeBSD$ + +This directory contains various files related to ipfilter. + +For information on building ipf based firewalls, read the ipf-howto.txt. + +a more up to date version of this file may be found at: + + http://www.obfuscation.org/ipf/ + +Additional help may be found at the ipf home page: + + http://coombs.anu.edu.au/~avalon/ + +examples.txt and rules.txt come from this site. diff --git a/share/examples/ipfilter/example.14 b/share/examples/ipfilter/example.14 new file mode 100644 index 0000000..f1f2be4 --- /dev/null +++ b/share/examples/ipfilter/example.14 @@ -0,0 +1,62 @@ +# $FreeBSD$ +# +# log all inbound packet on le0 which has IP options present +# +log in on le0 from any to any with ipopts +# +# block any inbound packets on le0 which are fragmented and "too short" to +# do any meaningful comparison on. This actually only applies to TCP +# packets which can be missing the flags/ports (depending on which part +# of the fragment you see). +# +block in log quick on le0 from any to any with short frag +# +# log all inbound TCP packets with the SYN flag (only) set +# (NOTE: if it were an inbound TCP packet with the SYN flag set and it +# had IP options present, this rule and the above would cause it +# to be logged twice). +# +log in on le0 proto tcp from any to any flags S/SA +# +# block and log any inbound ICMP unreachables +# +block in log on le0 proto icmp from any to any icmp-type unreach +# +# block and log any inbound UDP packets on le0 which are going to port 2049 +# (the NFS port). +# +block in log on le0 proto udp from any to any port = 2049 +# +# quickly allow any packets to/from a particular pair of hosts +# +pass in quick from any to 10.1.3.2/32 +pass in quick from any to 10.1.0.13/32 +pass in quick from 10.1.3.2/32 to any +pass in quick from 10.1.0.13/32 to any +# +# block (and stop matching) any packet with IP options present. +# +block in quick on le0 from any to any with ipopts +# +# allow any packet through +# +pass in from any to any +# +# block any inbound UDP packets destined for these subnets. +# +block in on le0 proto udp from any to 10.1.3.0/24 +block in on le0 proto udp from any to 10.1.1.0/24 +block in on le0 proto udp from any to 10.1.2.0/24 +# +# block any inbound TCP packets with only the SYN flag set that are +# destined for these subnets. +# +block in on le0 proto tcp from any to 10.1.3.0/24 flags S/SA +block in on le0 proto tcp from any to 10.1.2.0/24 flags S/SA +block in on le0 proto tcp from any to 10.1.1.0/24 flags S/SA +# +# block any inbound ICMP packets destined for these subnets. +# +block in on le0 proto icmp from any to 10.1.3.0/24 +block in on le0 proto icmp from any to 10.1.1.0/24 +block in on le0 proto icmp from any to 10.1.2.0/24 diff --git a/share/examples/ipfilter/examples.txt b/share/examples/ipfilter/examples.txt new file mode 100644 index 0000000..8444908 --- /dev/null +++ b/share/examples/ipfilter/examples.txt @@ -0,0 +1,515 @@ +IP Filter Examples + + [Image] Permissions + [Image] Interface + [Image] Netmasks and hosts + [Image] IP Protocols + [Image] IP Options + [Image] IP Fragments + [Image] TCP/UDP Ports + [Image] ICMP type/code + [Image] TCP Flags (established) + [Image] Responding to a BAD packet + [Image] IP Security Classes + [Image] Packet state filtering + [Image] Network Address Translation (NAT) + [Image] Transparent Proxy Support + [Image] Transparent routing + [Image] Logging packets to network devices + [Image] Rule groups + Authenticating packets + Pre-authenticating packets + + ------------------------------------------------------------------------ + +Permission Specifying. + +To specify where to pass through or to block a packet, either block or pass +is used. In and out are used to describe the direction in which the packet +is travelling through a network interface. Eg: + +# setup default to block all packets. +block in all +block out all +# pass packets from host firewall to any destination +pass in from firewall to any + + ------------------------------------------------------------------------ + +Select network Interfaces + +To select which interface a packet is currently associated with, either its +destination as a result of route processing or where it has been received +from, the on keyword is used. Whilst not compulsory, it is recommended that +each rule include it for clarity. Eg: + +# drop all inbound packets from localhost coming from ethernet +block in on le0 from localhost to any + + ------------------------------------------------------------------------ + +Netmasks and hosts + +As not all networks are formed with classical network boundaries, it is +necessary to provide a mechanism to support VLSM (Variable Length Subnet +Masks). This package provides several ways to do this. Eg: + +# +block in on le0 from mynet/26 to any +# +block in on le0 from mynet/255.255.255.192 to any +# +block in on le0 from mynet mask 255.255.255.192 to any +# +block in on le0 from mynet mask 0xffffffc0 to any + +Are all valid and legal syntax with this package. However, when regenerating +rules (ie using ipfstat), this package will prefer to use the shortest valid +notation (top down). + +The default netmask, when none is given is 255.255.255.255 or "/32". + +To invert the match on a hostname or network, include an ! before the name +or number with no space between them. + ------------------------------------------------------------------------ + +Protocol + +To filter on an individual protocol, it is possible to specify the protocol +in a filter rule. Eg: + +# block all incoming ICMP packets +block in on le0 proto icmp all + +The name of the protocol can be any valid name from /etc/protocols or a +number. + +# allow all IP packets in which are protocol 4 +pass in on le0 proto 4 all + +There is one exception to this rule, being "tcp/udp". If given in a ruleset, +it will match either of the two protocols. This is useful when setting up +port restrictions. Eg: + +# prevent any packets destined for NFS from coming in +block in on le0 proto tcp/udp from any to any port = 2049 + + ------------------------------------------------------------------------ + +Filtering IP fragments + +IP fragments are bad news, in general. Recent study has shown that IP +fragments can pose a large threat to IP packet filtering, IF there are rules +used which rely on data which may be distributed across fragments. To this +package, the threat is that the TCP flags field of the TCP packet may be in +the 2nd or 3rd fragment or possibly be believed to be in the first when +actually in the 2nd or 3rd. + +To filter out these nasties, it is possible to select fragmented packets out +as follows: + +# +# get rid of all IP fragments +# +block in all with frag + +The problem arises that fragments can actually be a non-malicious. The +really malicious ones can be grouped under the term "short fragments" and +can be filtered out as follows: + +# +# get rid of all short IP fragments (too small for valid comparison) +# +block in proto tcp all with short + + ------------------------------------------------------------------------ + +IP Options + +IP options have a bad name for being a general security threat. They can be +of some use, however, to programs such as traceroute but many find this +usefulness not worth the risk. + +Filtering on IP options can be achieved two ways. The first is by naming +them collectively and is done as follows: + +# +# drop and log any IP packets with options set in them. +# +block in log all with ipopts +# + +The second way is to actually list the names of the options you wish to +filter. + +# +# drop any source routing options +# +block in quick all with opt lsrr +block in quick all with opt ssrr + +[Image] NOTE that options are matched explicitly, so if I had lsrr,ssrr it +would only match packets with both options set. + +It is also possible to select packets which DON'T have various options +present in the packet header. For example, to allow telnet connections +without any IP options present, the following would be done: + +# +# Allow anyone to telnet in so long as they don't use IP options. +# +pass in proto tcp from any to any port = 23 with no ipopts +# +# Allow packets with strict source routing and no loose source routing +# +pass in from any to any with opt ssrr not opt lsrr + + ------------------------------------------------------------------------ + +Filtering by ports + +Filtering by port number only works with the TCP and UDP IP protocols. When +specifying port numbers, either the number or the service name from +/etc/services may be used. If the proto field is used in a filter rule, it +will be used in conjunction with the port name in determining the port +number. + +The possible operands available for use with port numbers are: + +Operand Alias Parameters Result +< lt port# true if port is less than given value +> gt port# true if port is greater than given value += eq port# true if port is equal to than given value +!= ne port# true if port is not equal to than given value +<= le port# true if port is less than or equal to given value +=> ge port# true if port is greater than or equal to given value + +Eg: + +# +# allow any TCP packets from the same subnet as foo is on through to host +# 10.1.1.2 if they are destined for port 6667. +# +pass in proto tcp from fubar/24 to 10.1.1.2/32 port = 6667 +# +# allow in UDP packets which are NOT from port 53 and are destined for +# localhost +# +pass in proto udp from fubar port != 53 to localhost + +Two range comparisons are also possible: + +Expression Syntax: +port1# <> port2# true if port is less than port1 or greater than port2 +port1# >< port2# true if port is greater than port1 and less than port2 + +[Image] NOTE that in neither case, when the port number is equal to one of +those given, does it match. Eg: + +# +# block anything trying to get to X terminal ports, X:0 to X:9 +# +block in proto tcp from any to any port 5999 >< 6010 +# +# allow any connections to be made, except to BSD print/r-services +# this will also protect syslog. +# +block in proto tcp/udp all +pass in proto tcp/udp from any to any port 512 <> 515 + +Note that the last one above could just as easily be done in the reverse +fashion: allowing everything through and blocking only a small range. Note +that the port numbers are different, however, due to the difference in the +way they are compared. + +# +# allow any connections to be made, except to BSD print/r-services +# this will also protect syslog. +# +pass in proto tcp/udp all +block in proto tcp/udp from any to any port 511 >< 516 + + ------------------------------------------------------------------------ + +TCP Flags (established) + +Filtering on TCP flags is useful, but fraught with danger. I'd recommend +that before using TCP flags in your IP filtering, you become at least a +little bit acquainted with what the role of each of them is and when they're +used. This package will compare the flags present in each TCP packet, if +asked, and match if those present in the TCP packet are the same as in the +IP filter rule. + +Some IP filtering/firewall packages allow you to filter out TCP packets +which belong to an "established" connection. This is, simply put, filtering +on packets which have the ACK bit set. The ACK bit is only set in packets +transmitted during the lifecycle of a TCP connection. It is necessary for +this flag to be present from either end for data to be transferred. If you +were using a rule which as worded something like: + +allow proto tcp 10.1.0.0 255.255.0.0 port = 23 10.2.0.0 255.255.0.0 established + +It could be rewritten as: + +pass in proto tcp 10.1.0.0/16 port = 23 10.2.0.0/16 flags A/A +pass out proto tcp 10.1.0.0/16 port = 23 10.2.0.0/16 flags A/A + +A more useful flag to filter on, for TCP connections, I find, is the SYN +flag. This is only set during the initial stages of connection negotiation, +and for the very first packet of a new TCP connection, it is the only flag +set. At all other times, an ACK or maybe even an URG/PUSH flag may be set. +So, if I want to stop connections being made to my internal network +(10.1.0.0) from the outside network, I might do something like: + +# +# block incoming connection requests to my internal network from the big bad +# internet. +# +block in on le0 proto tcp from any to 10.1.0.0/16 flags S/SA + +If you wanted to block the replies to this (the SYN-ACK's), then you might +do: + +block out on le0 proto tcp from 10.1.0.0 to any flags SA/SA + +where SA represents the SYN-ACK flags both being set. + +The flags after the / represent the TCP flag mask, indicating which bits of +the TCP flags you are interested in checking. When using the SYN bit in a +check, you SHOULD specify a mask to ensure that your filter CANNOT be +defeated by a packet with SYN and URG flags, for example, set (to Unix, this +is the same as a plain SYN). + ------------------------------------------------------------------------ + +ICMP Type/Code + +ICMP can be a source of a lot of trouble for Internet Connected networks. +Blocking out all ICMP packets can be useful, but it will disable some +otherwise useful programs, such as "ping". Filtering on ICMP type allows for +pings (for example) to work. Eg: + +# block all ICMP packets. +# +block in proto icmp all +# +# allow in ICMP echos and echo-replies. +# +pass in on le1 proto icmp from any to any icmp-type echo +pass in on le1 proto icmp from any to any icmp-type echorep + +To specify an ICMP code, the numeric value must be used. So, if we wanted to +block all port-unreachables, we would do: + +# +# block all ICMP destination unreachable packets which are port-unreachables +# +block in on le1 proto icmp from any to any icmp-type unreach code 3 + + ------------------------------------------------------------------------ + +Responding to a BAD packet + +To provide feedback to people trying to send packets through your filter +which you wish to disallow, you can send back either an ICMP error +(Destination Unreachable) or, if they're sending a TCP packet, a TCP RST +(Reset). + +What's the difference ? TCP/IP stacks take longer to pass the ICMP errors +back, through to the application, as they can often be due to temporary +problems (network was unplugged for a second) and it is `incorrect' to shut +down a connection for this reason. Others go to the other extreme and will +shut down all connections between the two hosts for which the ICMP error is +received. The TCP RST, however, is for only *one* connection (cannot be used +for more than one) and will cause the connection to immediately shut down. +So, for example, if you're blocking port 113, and setup a rule to return a +TCP RST rather than nothing or an ICMP packet, you won't experience any +delay if the other end was attempting to make a connection to an identd +service. + +Some examples are as follows: + +# +# block all incoming TCP connections but send back a TCP-RST for ones to +# the ident port +# +block in proto tcp from any to any flags S/SA +block return-rst in quick proto tcp from any to any port = 113 flags S/SA +# +# block all inbound UDP packets and send back an ICMP error. +# +block return-icmp in proto udp from any to any + +When returning ICMP packets, it is also possible to specify the type of ICMP +error return. This was requested so that traceroute traces could be forced +to end elegantly. To do this, the requested ICMP Unreachable code is placed +in brackets following the "return-icmp" directive: + +# +# block all inbound UDP packets and send back an ICMP error. +# +block return-icmp (3) in proto udp from any to any port > 30000 +block return-icmp (port-unr) in proto udp from any to any port > 30000 + +Those two examples are equivalent, and return a ICMP port unreachable error +packet to in response to any UDP packet received destined for a port greater +than 30,000. + ------------------------------------------------------------------------ + +Filtering IP Security Classes + +For users who have packets which contain IP security bits, filtering on the +defined classes and authority levels is supported. Currently, filtering on +16bit authority flags is not supported. + +As with ipopts and other IP options, it is possible to say that the packet +only matches if a certain class isn't present. + +Some examples of filtering on IP security options: + +# +# drop all packets without IP security options +# +block in all with no opt sec +# +# only allow packets in and out on le0 which are top secret +# +block out on le1 all +pass out on le1 all with opt sec-class topsecret +block in on le1 all +pass in on le1 all with opt sec-class topsecret + + ------------------------------------------------------------------------ + +Packet state filtering + +Packet state filtering can be used for any TCP flow to short-cut later +filtering. The "short-cuts" are kept in a table, with no alterations to the +packet filter list made. Subsequent packets, if a matching packet is found +in the table, are not passed through the list. For TCP flows, the filter +will follow the ack/sequence numbers of packets and only allow packets +through which fall inside the correct window. + +# +# Keep state for all outgoing telnet connections +# and disallow all other TCP traffic. +# +pass out on le1 proto tcp from any to any port = telnet keep state +block out on le1 all + +For UDP packets, packet exchanges are effectively stateless. However, if a +packet is first sent out from a given port, a reply is usually expected in +answer, in the `reverse' direction. + +# +# allow UDP replies back from name servers +# +pass out on le1 proto udp from any to any port = domain keep state + +Held UDP state is timed out, as is TCP state for entries added which do not +have the SYN flag set. If an entry is created with the SYN flag set, any +subsequent matching packet which doesn't have this flag set (ie a SYN-ACK) +will cause it to be "timeless" (actually, the timeout defaults to 5 days), +until either a FIN or RST is seen. + + ------------------------------------------------------------------------ + +Network Address Translation (NAT) + +Network address translation is used to remap IP #'s from one address range +to another range of network addresses. For TCP and UDP, this also can +include the port numbers. The IP#'s/port #'s are changed when a packet is +going out through an interface and IP Filter matches it against a NAT rules. + +Packets coming back in the same interface are remapped, as a matter of +course, to their original address information. + +# map all tcp connections from 10.1.0.0/16 to 240.1.0.1, changing the source +# port number to something between 10,000 and 20,000 inclusive. For all other +# IP packets, allocate an IP # between 240.1.0.0 and 240.1.0.255, temporarily +# for each new user. In this example, ed1 is the external interface. +# Use ipnat, not ipf to load these rules. +# +map ed1 10.1.0.0/16 -> 240.1.0.1/32 portmap tcp 10000:20000 +map ed1 10.1.0.0/16 -> 240.1.0.0/24 + + ------------------------------------------------------------------------ + +Transparent Proxy Suppoer + +Transparent proxies are supported through redirection, which works in a +similar way to NAT, except that rules are triggered by input packets. To +effect redirection rules, ipnat must be used (same as for NAT) rather than +ipf. + +# Redirection is triggered for input packets. +# For example, to redirect FTP connections through this box (in this case ed0 +# is the interface on the "inside" where default routes point), to the local +# ftp port, forcing them to connect through a proxy, you would use: +# +rdr ed0 0.0.0.0/0 port ftp -> 127.0.0.1 port ftp + + ------------------------------------------------------------------------ + +Transparent routing + +Transparent routing can be performed in two ways using IP Filter. The first +is to use the keyword "fastroute" in a rule, using the normal route lookup +to occur or using a fixed route with "to". Both effect transparent routing +by not causing any decrement in the TTL to occur as it passes through the +kernel. + +# Route all UDP packets through transparently. +# +pass in quick fastroute proto udp all +# +# Route all ICMP packets to network 10 (on le0) out through le1, to "router" +# +pass in quick on le0 to le1:router proto icmp all + + ------------------------------------------------------------------------ + +Logging packets to the network + +Logging packets to the network devices is supported for both packets being +passed through the filter and those being blocked. For packets being passed +on, the "dup-to" keyword must be used, but for packets being blocked, either +"to" (more efficient) or "dup-to" can be used. + +To log packets to the interface without requiring ARP to work, create a +static arp cache for a meaningless IP# (say 10.0.0.1) and log packets to +this IP#. + +# Log all short TCP packets to qe3, with "packetlog" as the intended +# destination for the packet. +# +block in quick to qe3:packetlog proto tcp all with short +# +# Log all connection attempts for TCP +# +pass in quick on ppp0 dup-to le1:packetlog proto tcp all flags S/SA + + ------------------------------------------------------------------------ + +Rule groups + +To aide in making rule processing more efficient, it is possible to setup +rule `groups'. By default, all rules are in group 0 and all other groups +have it as their ultimate parent. To start a new group, a rule includes a +`head' statement, such as this: + +# Process all incoming ppp packets on ppp0 with group 100, with the default for +# this interface to block all incoming. +# +block in quick on ppp0 all head 100 + +If we then wanted to allow people to connect to our WWW server, via ppp0, we +could then just add a rule about WWW. NOTE: only packets which match the +above rule are processed by any group 100 rules. + +# Allow connections to the WWW server via ppp0. +# +pass in quick proto tcp from any to any port = WWW keep state group 100 + + ------------------------------------------------------------------------ +Return to the IP Filter home page +$FreeBSD$ diff --git a/share/examples/ipfilter/firewall.1 b/share/examples/ipfilter/firewall.1 new file mode 100644 index 0000000..eaf8624 --- /dev/null +++ b/share/examples/ipfilter/firewall.1 @@ -0,0 +1,36 @@ +# $FreeBSD$ +# +# This is an example of a very light firewall used to guard against +# some of the most easily exploited common security holes. +# +# The example assumes it is running on a gateway with interface ppp0 +# attached to the outside world, and interface ed0 attached to +# network 192.168.4.0 which needs to be protected. +# +# +# Pass any packets not explicitly mentioned by subsequent rules +# +pass out from any to any +pass in from any to any +# +# Block any inherently bad packets coming in from the outside world. +# These include ICMP redirect packets and IP fragments so short the +# filtering rules won't be able to examine the whole UDP/TCP header. +# +block in log quick on ppp0 proto icmp from any to any icmp-type redir +block in log quick on ppp0 proto tcp/udp all with short +# +# Block any IP spoofing atempts. (Packets "from" our network +# shouldn't be coming in from outside). +# +block in log quick on ppp0 from 192.168.4.0/24 to any +block in log quick on ppp0 from localhost to any +block in log quick on ppp0 from 0.0.0.0/32 to any +block in log quick on ppp0 from 255.255.255.255/32 to any +# +# Block any incoming traffic to NFS ports, to the RPC portmapper, and +# to X servers. +# +block in log on ppp0 proto tcp/udp from any to any port = sunrpc +block in log on ppp0 proto tcp/udp from any to any port = 2049 +block in log on ppp0 proto tcp from any to any port = 6000 diff --git a/share/examples/ipfilter/firewall.2 b/share/examples/ipfilter/firewall.2 new file mode 100644 index 0000000..23d610d --- /dev/null +++ b/share/examples/ipfilter/firewall.2 @@ -0,0 +1,70 @@ +# $FreeBSD$ +# +# This is an example of a fairly heavy firewall used to keep everyone +# out of a particular network while still allowing people within that +# network to get outside. +# +# The example assumes it is running on a gateway with interface ppp0 +# attached to the outside world, and interface ed0 attached to +# network 192.168.4.0 which needs to be protected. +# +# +# Pass any packets not explicitly mentioned by subsequent rules +# +pass out from any to any +pass in from any to any +# +# Block any inherently bad packets coming in from the outside world. +# These include ICMP redirect packets, IP fragments so short the +# filtering rules won't be able to examine the whole UDP/TCP header, +# and anything with IP options. +# +block in log quick on ppp0 proto icmp from any to any icmp-type redir +block in log quick on ppp0 proto tcp/udp all with short +block in log quick on ppp0 from any to any with ipopts +# +# Block any IP spoofing atempts. (Packets "from" our network +# shouldn't be coming in from outside). +# +block in log quick on ppp0 from 192.168.4.0/24 to any +block in log quick on ppp0 from localhost to any +block in log quick on ppp0 from 0.0.0.0/32 to any +block in log quick on ppp0 from 255.255.255.255/32 to any +# +# Block all incoming UDP traffic except talk and DNS traffic. NFS +# and portmap are special-cased and logged. +# +block in on ppp0 proto udp from any to any +block in log on ppp0 proto udp from any to any port = sunrpc +block in log on ppp0 proto udp from any to any port = 2049 +pass in on ppp0 proto udp from any to any port = domain +pass in on ppp0 proto udp from any to any port = talk +pass in on ppp0 proto udp from any to any port = ntalk +# +# Block all incoming TCP traffic connections to known services, +# returning a connection reset so things like ident don't take +# forever timing out. Don't log ident (auth port) as it's so common. +# +block return-rst in log on ppp0 proto tcp from any to any flags S/SA +block return-rst in on ppp0 proto tcp from any to any port = auth flags S/SA +# +# Allow incoming TCP connections to ports between 1024 and 5000, as +# these don't have daemons listening but are used by outgoing +# services like ftp and talk. For slightly more obscurity (though +# not much more security), the second commented out rule can chosen +# instead. +# +pass in on ppp0 proto tcp from any to any port 1024 >< 5000 +#pass in on ppp0 proto tcp from any port = ftp-data to any port 1024 >< 5000 +# +# Now allow various incoming TCP connections to particular hosts, TCP +# to the main nameserver so secondaries can do zone transfers, SMTP +# to the mail host, www to the web server (which really should be +# outside the firewall if you care about security), and ssh to a +# hypothetical machine caled 'gatekeeper' that can be used to gain +# access to the protected network from the outside world. +# +pass in on ppp0 proto tcp from any to ns1 port = domain +pass in on ppp0 proto tcp from any to mail port = smtp +pass in on ppp0 proto tcp from any to www port = www +pass in on ppp0 proto tcp from any to gatekeeper port = ssh diff --git a/share/examples/ipfilter/ipf-howto.txt b/share/examples/ipfilter/ipf-howto.txt new file mode 100644 index 0000000..baef95c --- /dev/null +++ b/share/examples/ipfilter/ipf-howto.txt @@ -0,0 +1,3168 @@ + + + + + + + IP Filter Based Firewalls HOWTO + + Brendan Conoboy <synk@swcp.com> + Erik Fichtner <emf@obfuscation.org> + $FreeBSD$ + + Fri Apr 20 09:31:14 EDT 2001 + + + + + + + Abstract: This document is intended to introduce a new + user to the IP Filter firewalling package and, at the + same time, teach the user some basic fundamentals of + good firewall design. + + + + + + + + + + + + +1. Introduction + + IP Filter is a great little firewall package. It does +just about everything other free firewalls (ipfwadm, +ipchains, ipfw) do, but it's also portable and does neat +stuff the others don't. This document is intended to make +some cohesive sense of the sparse documentation presently +available for ipfilter. Some prior familiarity with packet +filtering will be useful, however too much familiarity may +make this document a waste of your time. For greater under- +standing of firewalls, the authors recommend reading Build- +ing Internet Firewalls, Chapman & Zwicky, O'Reilly and Asso- +ciates; and TCP/IP Illustrated, Volume 1, Stevens, Addison- +Wesley. + + + + + +1.1. Disclaimer + + The authors of this document are not responsible for +any damages incurred due to actions taken based on this doc- +ument. This document is meant as an introduction to building +a firewall based on IP-Filter. If you do not feel + + + + + + + + + + -2- + + +comfortable taking responsibility for your own actions, you +should stop reading this document and hire a qualified secu- +rity professional to install your firewall for you. + + +1.2. Copyright + + Unless otherwise stated, HOWTO documents are copy- +righted by their respective authors. HOWTO documents may be +reproduced and distributed in whole or in part, in any +medium physical or electronic, as long as this copyright +notice is retained on all copies. Commercial redistribution +is allowed and encouraged; however, the authors would like +to be notified of any such distributions. + + All translations, derivative works, or aggregate works +incorporating any HOWTO documents must be covered under this +copyright notice. That is, you may not produce a derivative +work from a HOWTO and impose additional restrictions on its +distribution. Exceptions to these rules may be granted under +certain conditions; please contact the HOWTO coordinator. + + In short, we wish to promote dissemination of this +information through as many channels as possible. However, +we do wish to retain copyright on the HOWTO documents, and +would like to be notified of any plans to redistribute the +HOWTOs. + + +1.3. Where to obtain the important pieces + + The official IPF homepage is at: +<http://coombs.anu.edu.au/~avalon/ip-filter.html> + + The most up-to-date version of this document can be +found at: <http://www.obfuscation.org/ipf/> + + + + +2. Basic Firewalling + + This section is designed to familiarize you with ipfil- +ter's syntax, and firewall theory in general. The features +discussed here are features you'll find in any good firewall +package. This section will give you a good foundation to +make reading and understanding the advanced section very +easy. It must be emphasized that this section alone is not +enough to build a good firewall, and that the advanced sec- +tion really is required reading for anybody who wants to +build an effective security system. + + + + + + + + + + + + + -3- + + +2.1. Config File Dynamics, Order and Precedence + + IPF (IP Filter) has a config file (as opposed to say, +running some command again and again for each new rule). +The config file drips with Unix: There's one rule per line, +the "#" mark denotes a comment, and you can have a rule and +a comment on the same line. Extraneous whitespace is +allowed, and is encouraged to keep the rules readable. + + +2.2. Basic Rule Processing + + The rules are processed from top to bottom, each one +appended after another. This quite simply means that if the +entirety of your config file is: + + block in all + pass in all + +The computer sees it as: + + block in all + pass in all + +Which is to say that when a packet comes in, the first thing +IPF applies is: + + block in all + +Should IPF deem it necessary to move on to the next rule, it +would then apply the second rule: + + pass in all + + At this point, you might want to ask yourself "would +IPF move on to the second rule?" If you're familiar with +ipfwadm or ipfw, you probably won't ask yourself this. +Shortly after, you will become bewildered at the weird way +packets are always getting denied or passed when they +shouldn't. Many packet filters stop comparing packets to +rulesets the moment the first match is made; IPF is not one +of them. + + Unlike the other packet filters, IPF keeps a flag on +whether or not it's going to pass the packet. Unless you +interrupt the flow, IPF will go through the entire ruleset, +making its decision on whether or not to pass or drop the +packet based on the last matching rule. The scene: IP Fil- +ter's on duty. It's been been scheduled a slice of CPU +time. It has a checkpoint clipboard that reads: + + block in all + pass in all + + + + + + + + + + + -4- + + +A packet comes in the interface and it's time to go to work. +It takes a look at the packet, it takes a look at the first +rule: + + block in all + +"So far I think I will block this packet" says IPF. It +takes a look at the second rule: + + pass in all + +"So far I think I will pass this packet" says IPF. It takes +a look at a third rule. There is no third rule, so it goes +with what its last motivation was, to pass the packet +onward. + +It's a good time to point out that even if the ruleset had +been + + block in all + block in all + block in all + block in all + pass in all + +that the packet would still have gone through. There is no +cumulative effect. The last matching rule always takes +precedence. + +2.3. Controlling Rule Processing + + If you have experience with other packet filters, you +may find this layout to be confusing, and you may be specu- +lating that there are problems with portability with other +filters and speed of rule matching. Imagine if you had 100 +rules and most of the applicable ones were the first 10. +There would be a terrible overhead for every packet coming +in to go through 100 rules every time. Fortunately, there +is a simple keyword you can add to any rule that makes it +take action at that match. That keyword is quick. + +Here's a modified copy of the original ruleset using the +quick keyword: + + block in quick all + pass in all + +In this case, IPF looks at the first rule: + + block in quick all + +The packet matches and the search is over. The packet is +expunged without a peep. There are no notices, no logs, no +memorial service. Cake will not be served. So what about + + + + + + + + + + -5- + + +the next rule? + + pass in all + + This rule is never encountered. It could just as eas- +ily not be in the config file at all. The sweeping match of +all and the terminal keyword quick from the previous rule +make certain that no rules are followed afterward. + + Having half a config file laid to waste is rarely a +desirable state. On the other hand, IPF is here to block +packets and as configured, it's doing a very good job. +Nonetheless, IPF is also here to let some packets through, +so a change to the ruleset to make this possible is called +for. + +2.4. Basic filtering by IP address + + IPF will match packets on many criteria. The one that +we most commonly think of is the IP address. There are some +blocks of address space from which we should never get traf- +fic. One such block is from the unroutable networks, +192.168.0.0/16 (/16 is the CIDR notation for a netmask. You +may be more familiar with the dotted decimal format, +255.255.0.0. IPF accepts both). If you wanted to block +192.168.0.0/16, this is one way to do it: + + block in quick from 192.168.0.0/16 to any + pass in all + +Now we have a less stringent ruleset that actually does +something for us. Let's imagine a packet comes in from +1.2.3.4. The first rule is applied: + + block in quick from 192.168.0.0/16 to any + +The packet is from 1.2.3.4, not 192.168.*.*, so there is no +match. The second rule is applied: + + pass in all + +The packet from 1.2.3.4 is definitely a part of all, so the +packet is sent to whatever it's destination happened to be. + + On the other hand, suppose we have a packet that comes +in from 192.168.1.2. The first rule is applied: + + block in quick from 192.168.0.0/16 to any + +There's a match, the packet is dropped, and that's the end. +Again, it doesn't move to the second rule because the first +rule matches and contains the quick keyword. + + + + + + + + + + + + -6- + + + At this point you can build a fairly extensive set of +definitive addresses which are passed or blocked. Since +we've already started blocking private address space from +entering our firewall, let's take care of the rest of it: + + block in quick from 192.168.0.0/16 to any + block in quick from 172.16.0.0/12 to any + block in quick from 10.0.0.0/8 to any + pass in all + +The first three address blocks are some of the private IP +space. + +2.5. Controlling Your Interfaces + + It seems very frequent that companies have internal +networks before they want a link to the outside world. In +fact, it's probably reasonable to say that's the main reason +people consider firewalls in the first place. The machine +that bridges the outside world to the inside world and vice +versa is the router. What separates the router from any +other machine is simple: It has more than one interface. + + Every packet you receive comes from a network inter- +face; every packet you transmit goes out a network inter- +face. Say your machine has 3 interfaces, lo0 (loopback), +xl0 (3com ethernet), and tun0 (FreeBSD's generic tunnel +interface that PPP uses), but you don't want packets coming +in on the tun0 interface? + + block in quick on tun0 all + pass in all + +In this case, the on keyword means that that data is coming +in on the named interface. If a packet comes in on tun0, +the first rule will block it. If a packet comes in on lo0 +or in on xl0, the first rule will not match, the second rule +will, the packet will be passed. + +2.6. Using IP Address and Interface Together + + It's an odd state of affairs when one decides it best +to have the tun0 interface up, but not allow any data to be +received from it. The more criteria the firewall matches +against, the tighter (or looser) the firewall can become. +Maybe you want data from tun0, but not from 192.168.0.0/16? +This is the start of a powerful firewall. + + block in quick on tun0 from 192.168.0.0/16 to any +----------- + See rfc1918 at +<http://www.faqs.org/rfcs/rfc1918.html> and +<http://www.ietf.org/internet-drafts/draft-man- +ning-dsua-06.txt> + + + + + + + + + + -7- + + + pass in all + +Compare this to our previous rule: + + block in quick from 192.168.0.0/16 to any + pass in all + +The old way, all traffic from 192.168.0.0/16, regardless of +interface, was completely blocked. The new way, using on +tun0 means that it's only blocked if it comes in on the tun0 +interface. If a packet arrived on the xl0 interface from +192.168.0.0/16, it would be passed. + + At this point you can build a fairly extensive set of +definitive addresses which are passed or blocked. Since +we've already started blocking private address space from +entering tun0, let's take care of the rest of it: + + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + pass in all + +You've already seen the first three blocks, but not the +rest. The fourth is a largely wasted class-A network used +for loopback. Much software communicates with itself on +127.0.0.1 so blocking it from an external source is a good +idea. The fifth, 0.0.0.0/8, should never be seen on the +internet. Most IP stacks treat "0.0.0.0/32" as the default +gateway, and the rest of the 0.*.*.* network gets handled +strangely by various systems as a byproduct of how routing +decisions are made. You should treat 0.0.0.0/8 just like +127.0.0.0/8. 169.254.0.0/16 has been assigned by the IANA +for use in auto-configuration when systems have not yet been +able to obtain an IP address via DHCP or the like. Most +notably, Microsoft Windows will use addresses in this range +if they are set to DHCP and cannot find a DHCP server. +192.0.2.0/24 has also been reserved for use as an example IP +netblock for documentation authors. We specifically do not +use this range as it would cause confusion when we tell you +to block it, and thus all our examples come from +20.20.20.0/24. 204.152.64.0/23 is an odd netblock reserved +by Sun Microsystems for private cluster interconnects, and +blocking this is up to your own judgement. Lastly, +224.0.0.0/3 wipes out the "Class D and E" networks which is +used mostly for multicast traffic, although further defini- +tion of "Class E" space can be found in RFC 1166. + + + + + + + + + + + -8- + + + There's a very important principle in packet filtering +which has only been alluded to with the private network +blocking and that is this: When you know there's certain +types of data that only comes from certain places, you setup +the system to only allow that kind of data from those +places. In the case of the unroutable addresses, you know +that nothing from 10.0.0.0/8 should be arriving on tun0 +because you have no way to reply to it. It's an illegiti- +mate packet. The same goes for the other unroutables as +well as 127.0.0.0/8. + + Many pieces of software do all their authentication +based upon the packet's originating IP address. When you +have an internal network, say 20.20.20.0/24, you know that +the only traffic for that internal network is going to come +off the local ethernet. Should a packet from 20.20.20.0/24 +arrive over a PPP dialup, it's perfectly reasonable to drop +it on the floor, or put it in a dark room for interrogation. +It should by no means be allowed to get to its final desti- +nation. You can accomplish this particularly easily with +what you already know of IPF. The new ruleset would be: + + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in quick on tun0 from 20.20.20.0/24 to any + pass in all + +2.7. Bi-Directional Filtering; The "out" Keyword + + Up until now, we've been passing or blocking inbound +traffic. To clarify, inbound traffic is all traffic that +enters the firewall on any interface. Conversely, outbound +traffic is all traffic that leaves on any interface (whether +locally generated or simply passing through). This means +that all packets coming in are not only filtered as they +enter the firewall, they're also filtered as they exit. +Thusfar there's been an implied pass out all that may or may +not be desirable. Just as you may pass and block incoming +traffic, you may do the same with outgoing traffic. + + Now that we know there's a way to filter outbound pack- +ets just like inbound, it's up to us to find a conceivable +use for such a thing. One possible use of this idea is to +keep spoofed packets from exiting your own network. Instead +of passing any traffic out the router, you could instead +limit permitted traffic to packets originating at + + + + + + + + + + + -9- + + +20.20.20.0/24. You might do it like this: + + pass out quick on tun0 from 20.20.20.0/24 to any + block out quick on tun0 from any to any + +If a packet comes from 20.20.20.1/32, it gets sent out by +the first rule. If a packet comes from 1.2.3.4/32 it gets +blocked by the second. + + You can also make similar rules for the unroutable +addresses. If some machine tries to route a packet through +IPF with a destination in 192.168.0.0/16, why not drop it? +The worst that can happen is that you'll spare yourself some +bandwidth: + + block out quick on tun0 from any to 192.168.0.0/16 + block out quick on tun0 from any to 172.16.0.0/12 + block out quick on tun0 from any to 10.0.0.0/8 + block out quick on tun0 from any to 0.0.0.0/8 + block out quick on tun0 from any to 127.0.0.0/8 + block out quick on tun0 from any to 169.254.0.0/16 + block out quick on tun0 from any to 192.0.2.0/24 + block out quick on tun0 from any to 204.152.64.0/23 + block out quick on tun0 from any to 224.0.0.0/3 + block out quick on tun0 from !20.20.20.0/24 to any + +In the narrowest viewpoint, this doesn't enhance your secu- +rity. It enhances everybody else's security, and that's a +nice thing to do. As another viewpoint, one might suppose +that because nobody can send spoofed packets from your site, +that your site has less value as a relay for crackers, and +as such is less of a target. + + You'll likely find a number of uses for blocking out- +bound packets. One thing to always keep in mind is that in +and out directions are in reference to your firewall, never +any other machine. + +2.8. Logging What Happens; The "log" Keyword + + Up to this point, all blocked and passed packets have +been silently blocked and silently passed. Usually you want +to know if you're being attacked rather than wonder if that +firewall is really buying you any added benefits. While I +wouldn't want to log every passed packet, and in some cases +every blocked packet, I would want to know about the blocked +packets from 20.20.20.0/24. To do this, we add the log key- +word: + + block in quick on tun0 from 192.168.0.0/16 to any +----------- + This can, of course, be changed by using -DIPFIL- +TER_DEFAULT_BLOCK when compiling ipfilter on your +system. + + + + + + + + + + -10- + + + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + pass in all + +So far, our firewall is pretty good at blocking packets com- +ing to it from suspect places, but there's still more to be +done. For one thing, we're accepting packets destined any- +where. One thing we ought to do is make sure packets to +20.20.20.0/32 and 20.20.20.255/32 get dropped on the floor. +To do otherwise opens the internal network for a smurf +attack. These two lines would prevent our hypothetical net- +work from being used as a smurf relay: + + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + +This brings our total ruleset to look something like this: + + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + pass in all + +2.9. Complete Bi-Directional Filtering By Interface + + So far we have only presented fragments of a complete +ruleset. When you're actually creating your ruleset, you +should setup rules for every direction and every interface. +The default state of ipfilter is to pass packets. It is as +though there were an invisible rule at the beginning which +states pass in all and pass out all. Rather than rely on +some default behaviour, make everything as specific as pos- +sible, interface by interface, until every base is covered. + + First we'll start with the lo0 interface, which wants +to run wild and free. Since these are programs talking to +others on the local system, go ahead and keep it unre- +stricted: + + + + + + + + + + -11- + + + pass out quick on lo0 + pass in quick on lo0 + +Next, there's the xl0 interface. Later on we'll begin plac- +ing restrictions on the xl0 interface, but to start with, +we'll act as though everything on our local network is +trustworthy and give it much the same treatment as lo0: + + pass out quick on xl0 + pass in quick on xl0 + +Finally, there's the tun0 interface, which we've been half- +filtering with up until now: + + block out quick on tun0 from any to 192.168.0.0/16 + block out quick on tun0 from any to 172.16.0.0/12 + block out quick on tun0 from any to 127.0.0.0/8 + block out quick on tun0 from any to 10.0.0.0/8 + block out quick on tun0 from any to 0.0.0.0/8 + block out quick on tun0 from any to 169.254.0.0/16 + block out quick on tun0 from any to 192.0.2.0/24 + block out quick on tun0 from any to 204.152.64.0/23 + block out quick on tun0 from any to 224.0.0.0/3 + pass out quick on tun0 from 20.20.20.0/24 to any + block out quick on tun0 from any to any + + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + pass in all + +This is a pretty significant amount of filtering already, +protecting 20.20.20.0/24 from being spoofed or being used +for spoofing. Future examples will continue to show one- +sideness, but keep in mind that it's for brevity's sake, and +when setting up your own ruleset, adding rules for every +direction and every interface is necessary. + + +2.10. Controlling Specific Protocols; The "proto" Keyword + + Denial of Service attacks are as rampant as buffer +overflow exploits. Many denial of service attacks rely on +glitches in the OS's TCP/IP stack. Frequently, this has +come in the form of ICMP packets. Why not block them + + + + + + + + + + -12- + + +entirely? + + block in log quick on tun0 proto icmp from any to any + +Now any ICMP traffic coming in from tun0 will be logged and +discarded. + +2.11. Filtering ICMP with the "icmp-type" Keyword; Merging +Rulesets + + Of course, dropping all ICMP isn't really an ideal sit- +uation. Why not drop all ICMP? Well, because it's useful +to have partially enabled. So maybe you want to keep some +types of ICMP traffic and drop other kinds. If you want +ping and traceroute to work, you need to let in ICMP types 0 +and 11. Strictly speaking, this might not be a good idea, +but if you need to weigh security against convenience, IPF +lets you do it. + + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11 + +Remember that ruleset order is important. Since we're doing +everything quick we must have our passes before our blocks, +so we really want the last three rules in this order: + + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11 + block in log quick on tun0 proto icmp from any to any + +Adding these 3 rules to the anti-spoofing rules is a bit +tricky. One error might be to put the new ICMP rules at the +beginning: + + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11 + block in log quick on tun0 proto icmp from any to any + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + pass in all + +The problem with this is that an ICMP type 0 packet from +192.168.0.0/16 will get passed by the first rule, and never +blocked by the fourth rule. Also, since we quickly pass an + + + + + + + + + + -13- + + +ICMP ECHO_REPLY (type 0) to 20.20.20.0/24, we've just opened +ourselves back up to a nasty smurf attack and nullified +those last two block rules. Oops. To avoid this, we place +the ICMP rules after the anti-spoofing rules: + + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11 + block in log quick on tun0 proto icmp from any to any + pass in all + +Because we block spoofed traffic before the ICMP rules are +processed, a spoofed packet never makes it to the ICMP rule- +set. It's very important to keep such situations in mind +when merging rules. + +2.12. TCP and UDP Ports; The "port" Keyword + + Now that we've started blocking packets based on proto- +col, we can start blocking packets based on specific aspects +of each protocol. The most frequently used of these aspects +is the port number. Services such as rsh, rlogin, and tel- +net are all very convenient to have, but also hideously +insecure against network sniffing and spoofing. One great +compromise is to only allow the services to run internally, +then block them externally. This is easy to do because +rlogin, rsh, and telnet use specific TCP ports (513, 514, +and 23 respectively). As such, creating rules to block them +is easy: + + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 513 + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 514 + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 23 + +Make sure all 3 are before the pass in all and they'll be +closed off from the outside (leaving out spoofing for +brevity's sake): + + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0 + pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11 + block in log quick on tun0 proto icmp from any to any + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 513 + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 514 + + + + + + + + + + -14- + + + block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 23 + pass in all + +You might also want to block 514/udp (syslog), 111/tcp & +111/udp (portmap), 515/tcp (lpd), 2049/tcp and 2049/udp +(NFS), 6000/tcp (X11) and so on and so forth. You can get a +complete listing of the ports being listened to by using +netstat -a (or lsof -i, if you have it installed). + + Blocking UDP instead of TCP only requires replacing +proto tcp with proto udp. The rule for syslog would be: + + block in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 514 + +IPF also has a shorthand way to write rules that apply to +both proto tcp and proto udp at the same time, such as +portmap or NFS. The rule for portmap would be: + + block in log quick on tun0 proto tcp/udp from any to 20.20.20.0/24 port = 111 + + + + +3. Advanced Firewalling Introduction + + This section is designed as an immediate followup to +the basic section. Contained below are both concepts for +advanced firewall design, and advanced features contained +only within ipfilter. Once you are comfortable with this +section, you should be able to build a very strong firewall. + +3.1. Rampant Paranoia; or The Default-Deny Stance + + There's a big problem with blocking services by the +port: sometimes they move. RPC based programs are terrible +about this, lockd, statd, even nfsd listens places other +than 2049. It's awfully hard to predict, and even worse to +automate adjusting all the time. What if you miss a ser- +vice? Instead of dealing with all that hassle, let's start +over with a clean slate. The current ruleset looks like +this: + + + + + Yes, we really are starting over. The first rule we're +going to use is this: + + block in all + +No network traffic gets through. None. Not a peep. You're +rather secure with this setup. Not terribly useful, but +quite secure. The great thing is that it doesn't take much +more to make your box rather secure, yet useful too. Let's + + + + + + + + + + -15- + + +say the machine this is running on is a web server, nothing +more, nothing less. It doesn't even do DNS lookups. It +just wants to take connections on 80/tcp and that's it. We +can do that. We can do that with a second rule, and you +already know how: + + block in on tun0 all + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80 + +This machine will pass in port 80 traffic for 20.20.20.1, +and deny everything else. For basic firewalling, this is +all one needs. + +3.2. Implicit Allow; The "keep state" Rule + + The job of your firewall is to prevent unwanted traffic +getting to point B from point A. We have general rules +which say "as long as this packet is to port 23, it's okay." +We have general rules which say "as long as this packet has +its FIN flag set, it's okay." Our firewalls don't know the +beginning, middle, or end of any TCP/UDP/ICMP session. They +merely have vague rules that are applied to all packets. +We're left to hope that the packet with its FIN flag set +isn't really a FIN scan, mapping our services. We hope that +the packet to port 23 isn't an attempted hijack of our tel- +net session. What if there was a way to identify and autho- +rize individual TCP/UDP/ICMP sessions and distinguish them +from port scanners and DoS attacks? There is a way, it's +called keeping state. + + We want convenience and security in one. Lots of peo- +ple do, that's why Ciscos have an "established" clause that +lets established tcp sessions go through. Ipfw has estab- +lished. Ipfwadm has setup/established. They all have this +feature, but the name is very misleading. When we first saw +it, we thought it meant our packet filter was keeping track +of what was going on, that it knew if a connection was +really established or not. The fact is, they're all taking +the packet's word for it from a part of the packet anybody +can lie about. They read the TCP packet's flags section and +there's the reason UDP/ICMP don't work with it, they have no +such thing. Anybody who can create a packet with bogus +flags can get by a firewall with this setup. + + Where does IPF come in to play here, you ask? Well, +unlike the other firewalls, IPF really can keep track of +whether or not a connection is established. And it'll do it +with TCP, UDP and ICMP, not just TCP. Ipf calls it keeping +state. The keyword for the ruleset is keep state. + + Up until now, we've told you that packets come in, then +the ruleset gets checked; packets go out, then the ruleset +gets checked. Actually, what happens is packets come in, +the state table gets checked, then *maybe* the inbound + + + + + + + + + + -16- + + +ruleset gets checked; packets go out, the state table gets +checked, then *maybe* the outbound ruleset gets checked. +The state table is a list of TCP/UDP/ICMP sessions that are +unquestionadely passed through the firewall, circumventing +the entire ruleset. Sound like a serious security hole? +Hang on, it's the best thing that ever happened to your +firewall. + + All TCP/IP sessions have a start, a middle, and an end +(even though they're sometimes all in the same packet). You +can't have an end without a middle and you can't have a mid- +dle without a start. This means that all you really need to +filter on is the beginning of a TCP/UDP/ICMP session. If +the beginning of the session is allowed by your firewall +rules, you really want the middle and end to be allowed too +(lest your IP stack should overflow and your machines become +useless). Keeping state allows you to ignore the middle and +end and simply focus on blocking/passing new sessions. If +the new session is passed, all its subsequent packets will +be allowed through. If it's blocked, none of its subsequent +packets will be allowed through. Here's an example for run- +ning an ssh server (and nothing but an ssh server): + + block out quick on tun0 all + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 22 keep state + +The first thing you might notice is that there's no "pass +out" provision. In fact, there's only an all-inclusive +"block out" rule. Despite this, the ruleset is complete. +This is because by keeping state, the entire ruleset is cir- +cumvented. Once the first SYN packet hits the ssh server, +state is created and the remainder of the ssh session is +allowed to take place without interference from the fire- +wall. Here's another example: + + block in quick on tun0 all + pass out quick on tun0 proto tcp from 20.20.20.1/32 to any keep state + +In this case, the server is running no services. Infact, +it's not a server, it's a client. And this client doesn't +want unauthorized packets entering its IP stack at all. +However, the client wants full access to the internet and +the reply packets that such privledge entails. This simple +ruleset creates state entries for every new outgoing TCP +session. Again, since a state entry is created, these new +TCP sessions are free to talk back and forth as they please +without the hinderance or inspection of the firewall rule- +set. We mentioned that this also works for UDP and ICMP: + + block in quick on tun0 all + pass out quick on tun0 proto tcp from 20.20.20.1/32 to any keep state + pass out quick on tun0 proto udp from 20.20.20.1/32 to any keep state + pass out quick on tun0 proto icmp from 20.20.20.1/32 to any keep state + + + + + + + + + + + -17- + + +Yes Virginia, we can ping. Now we're keeping state on TCP, +UDP, ICMP. Now we can make outgoing connections as though +there's no firewall at all, yet would-be attackers can't get +back in. This is very handy because there's no need to +track down what ports we're listening to, only the ports we +want people to be able to get to. + + State is pretty handy, but it's also a bit tricky. You +can shoot yourself in the foot in strange and mysterious +ways. Consider the following ruleset: + + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 + pass out quick on tun0 proto tcp from any to any keep state + block in quick all + block out quick all + +At first glance, this seems to be a good setup. We allow +incoming sessions to port 23, and outgoing sessions any- +where. Naturally packets going to port 23 will have reply +packets, but the ruleset is setup in such a way that the +pass out rule will generate a state entry and everything +will work perfectly. At least, you'd think so. + + The unfortunate truth is that after 60 seconds of idle +time the state entry will be closed (as opposed to the nor- +mal 5 days). This is because the state tracker never saw +the original SYN packet destined to port 23, it only saw the +SYN ACK. IPF is very good about following TCP sessions from +start to finish, but it's not very good about coming into +the middle of a connection, so rewrite the rule to look like +this: + + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 keep state + pass out quick on tun0 proto tcp from any to any keep state + block in quick all + block out quick all + +The additional of this rule will enter the very first packet +into the state table and everything will work as expected. +Once the 3-way handshake has been witness by the state +engine, it is marked in 4/4 mode, which means it's setup for +long-term data exchange until such time as the connection is +torn down (wherein the mode changes again. You can see the +current modes of your state table with ipfstat -s. + +3.3. Stateful UDP + + UDP is stateless so naturally it's a bit harder to do a +reliable job of keeping state on it. Nonetheless, ipf does +a pretty good job. When machine A sends a UDP packet to +machine B with source port X and destination port Y, ipf +will allow a reply from machine B to machine A with source +port Y and destination port X. This is a short term state +entry, a mere 60 seconds. + + + + + + + + + + -18- + + + Here's an example of what happens if we use nslookup to +get the IP address of www.3com.com: + + $ nslookup www.3com.com + + A DNS packet is generated: + + 17:54:25.499852 20.20.20.1.2111 > 198.41.0.5.53: 51979+ + +The packet is from 20.20.20.1, port 2111, destined for +198.41.0.5, port 53. A 60 second state entry is created. +If a packet comes back from 198.41.0.5 port 53 destined for +20.20.20.1 port 2111 within that period of time, the reply +packet will be let through. As you can see, milliseconds +later: + + 17:54:25.501209 198.41.0.5.53 > 20.20.20.1.2111: 51979 q: www.3com.com + +The reply packet matches the state criteria and is let +through. At that same moment that packet is let through, +the state gateway is closed and no new incoming packets will +be allowed in, even if they claim to be from the same place. + +3.4. Stateful ICMP + + IPFilter handles ICMP states in the manner that one +would expect from understanding how ICMP is used with TCP +and UDP, and with your understanding of how keep state +works. There are two general types of ICMP messages; +requests and replies. When you write a rule such as: + + pass out on tun0 proto icmp from any to any icmp-type 8 keep state + +to allow outbound echo requests (a typical ping), the resul- +tant icmp-type 0 packet that comes back will be allowed in. +This state entry has a default timeout of an incomplete 0/0 +state of 60 seconds. Thus, if you are keeping state on any +outbound icmp message that will elicit an icmp message in +reply, you need a proto icmp [...] keep state rule. + + However, the majority of ICMP messages are status mes- +sages generated by some failure in UDP (and sometimes TCP), +and in 3.4.x and greater IPFilters, any ICMP error status +message (say icmp-type 3 code 3 port unreachable, or icmp- +type 11 time exceeded) that matches an active state table +entry that could have generated that message, the ICMP +packet is let in. For example, in older IPFilters, if you +wanted traceroute to work, you needed to use: + + pass out on tun0 proto udp from any to any port 33434><33690 keep state + pass in on tun0 proto icmp from any to any icmp-type timex + +whereas now you can do the right thing and just keep state +on udp with: + + + + + + + + + + -19- + + + pass out on tun0 proto udp from any to any port 33434><33690 keep state + +To provide some protection against a third-party sneaking +ICMP messages through your firewall when an active connec- +tion is known to be in your state table, the incoming ICMP +packet is checked not only for matching source and destina- +tion addresses (and ports, when applicable) but a tiny part +of the payload of the packet that the ICMP message is claim- +ing it was generated by. + +3.5. FIN Scan Detection; "flags" Keyword, "keep frags" Key- +word + +Let's go back to the 4 rule set from the previous section: + + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 keep state + pass out quick on tun0 proto tcp from any to any keep state + block in quick all + block out quick all + +This is almost, but not quite, satisfactory. The problem is +that it's not just SYN packets that're allowed to go to port +23, any old packet can get through. We can change this by +using the flags option: + + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 flags S keep state + pass out quick on tun0 proto tcp from any to any flags S keep state + block in quick all + block out quick all + +Now only TCP packets, destined for 20.20.20.1, at port 23, +with a lone SYN flag will be allowed in and entered into the +state table. A lone SYN flag is only present as the very +first packet in a TCP session (called the TCP handshake) and +that's really what we wanted all along. There's at least +two advantages to this: No arbitrary packets can come in +and make a mess of your state table. Also, FIN and XMAS +scans will fail since they set flags other than the SYN +flag. Now all incoming packets must either be handshakes or +have state already. If anything else comes in, it's proba- +bly a port scan or a forged packet. There's one exception +to that, which is when a packet comes in that's fragmented +from its journey. IPF has provisions for this as well, the +----------- + Some examples use flags S/SA instead of flags S. +flags S actually equates to flags S/AUPRFS and +matches against only the SYN packet out of all six +possible flags, while flags S/SA will allow pack- +ets that may or may not have the URG, PSH, FIN, or +RST flags set. Some protocols demand the URG or +PSH flags, and S/SAFR would be a better choice for +these, however we feel that it is less secure to +blindly use S/SA when it isn't required. But it's +your firewall. + + + + + + + + + + -20- + + +keep frags keyword. With it, IPF will notice and keep track +of packets that are fragmented, allowing the expected frag- +ments to to go through. Let's rewrite the 3 rules to log +forgeries and allow fragments: + + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23 flags S keep state keep frags + pass out quick on tun0 proto tcp from any to any keep state flags S keep frags + block in log quick all + block out log quick all + +This works because every packet that should be allowed +through makes it into the state table before the blocking +rules are reached. The only scan this won't detect is a SYN +scan itself. If you're truely worried about that, you might +even want to log all initial SYN packets. + +3.6. Responding To a Blocked Packet + + So far, all of our blocked packets have been dumped on +the floor, logged or not, we've never sent anything back to +the originating host. Sometimes this isn't the most desir- +able of responses because in doing so, we actually tell the +attacker that a packet filter is present. It seems a far +better thing to misguide the attacker into believing that, +while there's no packet filter running, there's likewise no +services to break into. This is where fancier blocking +comes into play. + + When a service isn't running on a Unix system, it nor- +mally lets the remote host know with some sort of return +packet. In TCP, this is done with an RST (Reset) packet. +When blocking a TCP packet, IPF can actually return an RST +to the origin by using the return-rst keyword. + +Where once we did: + + block in log on tun0 proto tcp from any to 20.20.20.0/24 port = 23 + pass in all + +We might now do: + + block return-rst in log proto tcp from any to 20.20.20.0/24 port = 23 + block in log quick on tun0 + pass in all + +We need two block statements since return-rst only works +with TCP, and we still want to block protocols such as UDP, +ICMP, and others. Now that this is done, the remote side +will get "connection refused" instead of "connection timed +out". + + It's also possible to send an error message when some- +body sends a packet to a UDP port on your system. Whereas +once you might have used: + + + + + + + + + + -21- + + + block in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 111 + +You could instead use the return-icmp keyword to send a +reply: + + block return-icmp(port-unr) in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 111 + +According to TCP/IP Illustrated, port-unreachable is the +correct ICMP type to return when no service is listening on +the port in question. You can use any ICMP type you like, +but port-unreachable is probably your best bet. It's also +the default ICMP type for return-icmp. + + However, when using return-icmp, you'll notice that +it's not very stealthy, and it returns the ICMP packet with +the IP address of the firewall, not the original destination +of the packet. This was fixed in ipfilter 3.3, and a new +keyword; return-icmp-as-dest, has been added. The new for- +mat is: + + block return-icmp-as-dest(port-unr) in log on tun0 proto udp from any to 20.20.20.0/24 port = 111 + +3.7. Fancy Logging Techniques + + It is important to note that the presence of the log +keyword only ensures that the packet will be available to +the ipfilter logging device; /dev/ipl. In order to actu- +ally see this log information, one must be running the ipmon +utility (or some other utility that reads from /dev/ipl). +The typical usage of log is coupled with ipmon -s to log the +information to syslog. As of ipfilter 3.3, one can now even +control the logging behavior of syslog by using log level +keywords, as in rules such as this: + + block in log level auth.info quick on tun0 from 20.20.20.0/24 to any + block in log level auth.alert quick on tun0 proto tcp from any to 20.20.20.0/24 port = 21 + +In addition to this, you can tailor what information is +being logged. For example, you may not be interested that +someone attempted to probe your telnet port 500 times, but +you are interested that they probed you once. You can use +the log first keyword to only log the first example of a +packet. Of course, the notion of "first-ness" only applies +to packets in a specific session, and for the typical +blocked packet, you will be hard pressed to encounter situa- +tions where this does what you expect. However, if used in +conjunction with pass and keep state, this can be a valuable +keyword for keeping tabs on traffic. + + Another useful thing you can do with the logs is to +keep track of interesting pieces of the packet in addition +to the header information normally being logged. Ipfilter +will give you the first 128 bytes of the packet if you use +the log body keyword. You should limit the use of body + + + + + + + + + + -22- + + +logging, as it makes your logs very verbose, but for certain +applications, it is often handy to be able to go back and +take a look at the packet, or to send this data to another +application that can examine it further. + +3.8. Putting It All Together + + So now we have a pretty tight firewall, but it can +still be tighter. Some of the original ruleset we wiped +clean is actually very useful. I'd suggest bringing back +all the anti-spoofing stuff. This leaves us with: + + block in on tun0 + block in quick on tun0 from 192.168.0.0/16 to any + block in quick on tun0 from 172.16.0.0/12 to any + block in quick on tun0 from 10.0.0.0/8 to any + block in quick on tun0 from 127.0.0.0/8 to any + block in quick on tun0 from 0.0.0.0/8 to any + block in quick on tun0 from 169.254.0.0/16 to any + block in quick on tun0 from 192.0.2.0/24 to any + block in quick on tun0 from 204.152.64.0/23 to any + block in quick on tun0 from 224.0.0.0/3 to any + block in log quick on tun0 from 20.20.20.0/24 to any + block in log quick on tun0 from any to 20.20.20.0/32 + block in log quick on tun0 from any to 20.20.20.255/32 + pass out quick on tun0 proto tcp/udp from 20.20.20.1/32 to any keep state + pass out quick on tun0 proto icmp from 20.20.20.1/32 to any keep state + pass in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80 flags S keep state + +3.9. Improving Performance With Rule Groups + + Let's extend our use of our firewall by creating a much +more complicated, and we hope more applicable to the real +world, example configuration For this example, we're going +to change the interface names, and network numbers. Let's +assume that we have three interfaces in our firewall with +interfaces xl0, xl1, and xl2. + +xl0 is connected to our external network 20.20.20.0/26 +xl1 is connected to our "DMZ" network 20.20.20.64/26 +xl2 is connected to our protected network 20.20.20.128/25 + +We'll define the entire ruleset in one swoop, since we fig- +ure that you can read these rules by now: + + block in quick on xl0 from 192.168.0.0/16 to any + block in quick on xl0 from 172.16.0.0/12 to any + block in quick on xl0 from 10.0.0.0/8 to any + block in quick on xl0 from 127.0.0.0/8 to any + block in quick on xl0 from 0.0.0.0/8 to any + block in quick on xl0 from 169.254.0.0/16 to any + block in quick on xl0 from 192.0.2.0/24 to any + block in quick on xl0 from 204.152.64.0/23 to any + block in quick on xl0 from 224.0.0.0/3 to any + + + + + + + + + + -23- + + + block in log quick on xl0 from 20.20.20.0/24 to any + block in log quick on xl0 from any to 20.20.20.0/32 + block in log quick on xl0 from any to 20.20.20.63/32 + block in log quick on xl0 from any to 20.20.20.64/32 + block in log quick on xl0 from any to 20.20.20.127/32 + block in log quick on xl0 from any to 20.20.20.128/32 + block in log quick on xl0 from any to 20.20.20.255/32 + pass out on xl0 all + + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21 flags S keep state + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20 flags S keep state + pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53 flags S keep state + pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53 keep state + pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53 flags S keep state + pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53 keep state + block out on xl1 all + pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state + + block out on xl2 all + pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state + +From this arbitarary example, we can already see that our +ruleset is becoming unwieldy. To make matters worse, as we +add more specific rules to our DMZ network, we add addi- +tional tests that must be parsed for every packet, which +affects the performance of the xl0 <-> xl2 connections. If +you set up a firewall with a ruleset like this, and you have +lots of bandwidth and a moderate amount of cpu, everyone +that has a workstation on the xl2 network is going to come +looking for your head to place on a platter. So, to keep +your head <-> torso network intact, you can speed things +along by creating rule groups. Rule groups allow you to +write your ruleset in a tree fashion, instead of as a linear +list, so that if your packet has nothing to do with the set +of tests (say, all those xl1 rules) those rules will never +be consulted. It's somewhat like having multiple firewalls +all on the same machine. + +Here's a simple example to get us started: + + block out quick on xl1 all head 10 + pass out quick proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state group 10 + block out on xl2 all + +In this simplistic example, we can see a small hint of the +power of the rule group. If the packet is not destined for +xl1, the head of rule group 10 will not match, and we will +go on with our tests. If the packet does match for xl1, the +quick keyword will short-circuit all further processing at +the root level (rule group 0), and focus the testing on +rules which belong to group 10; namely, the SYN check for +80/tcp. In this way, we can re-write the above rules so +that we can maximize performance of our firewall. + + + + + + + + + + -24- + + + block in quick on xl0 all head 1 + block in quick on xl0 from 192.168.0.0/16 to any group 1 + block in quick on xl0 from 172.16.0.0/12 to any group 1 + block in quick on xl0 from 10.0.0.0/8 to any group 1 + block in quick on xl0 from 127.0.0.0/8 to any group 1 + block in quick on xl0 from 0.0.0.0/8 to any group 1 + block in quick on xl0 from 169.254.0.0/16 to any group 1 + block in quick on xl0 from 192.0.2.0/24 to any group 1 + block in quick on xl0 from 204.152.64.0/23 to any group 1 + block in quick on xl0 from 224.0.0.0/3 to any group 1 + block in log quick on xl0 from 20.20.20.0/24 to any group 1 + block in log quick on xl0 from any to 20.20.20.0/32 group 1 + block in log quick on xl0 from any to 20.20.20.63/32 group 1 + block in log quick on xl0 from any to 20.20.20.64/32 group 1 + block in log quick on xl0 from any to 20.20.20.127/32 group 1 + block in log quick on xl0 from any to 20.20.20.128/32 group 1 + block in log quick on xl0 from any to 20.20.20.255/32 group 1 + pass in on xl0 all group 1 + + pass out on xl0 all + + block out quick on xl1 all head 10 + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80 flags S keep state group 10 + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21 flags S keep state group 10 + pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20 flags S keep state group 10 + pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53 flags S keep state group 10 + pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53 keep state group 10 + pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53 flags S keep state + pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53 keep state group 10 + + pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state + + block out on xl2 all + + pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state + +Now you can see the rule groups in action. For a host on +the xl2 network, we can completely bypass all the checks in +group 10 when we're not communicating with hosts on that +network. + + Depending on your situation, it may be prudent to group +your rules by protocol, or various machines, or netblocks, +or whatever makes it flow smoothly. + +3.10. "Fastroute"; The Keyword of Stealthiness + + Even though we're forwarding some packets, and blocking +other packets, we're typically behaving like a well behaved +router should by decrementing the TTL on the packet and +acknowledging to the entire world that yes, there is a hop +here. But we can hide our presence from inquisitive appli- +cations like unix traceroute which uses UDP packets with +various TTL values to map the hops between two sites. If we + + + + + + + + + + -25- + + +want incoming traceroutes to work, but we do not want to +announce the presence of our firewall as a hop, we can do so +with a rule like this: + + block in quick on xl0 fastroute proto udp from any to any port 33434 >< 33465 + +The presence of the fastroute keyword will signal ipfilter +to not pass the packet into the Unix IP stack for routing +which results in a TTL decrement. The packet will be placed +gently on the output interface by ipfilter itself and no +such decrement will happen. Ipfilter will of course use the +system's routing table to figure out what the appropriate +output interface really is, but it will take care of the +actual task of routing itself. + + There's a reason we used block quick in our example, +too. If we had used pass, and if we had IP Forwarding +enabled in our kernel, we would end up having two paths for +a packet to come out of, and we would probably panic our +kernel. + + It should be noted, however, that most Unix kernels +(and certainly the ones underlying the systems that ipfilter +usually runs on) have far more efficient routing code than +what exists in ipfilter, and this keyword should not be +thought of as a way to improve the operating speed of your +firewall, and should only be used in places where stealth is +an issue. + + + + +4. NAT and Proxies + + Outside of the corporate environment, one of the +biggest enticements of firewall technology to the end user +is the ability to connect several computers through a common +external interface, often without the approval, knowledge, +or even consent of their service provider. To those famil- +iar with Linux, this concept is called IP Masquerading, but +to the rest of the world it is known by the more obscure +name of Network Address Translation, or NAT for short. + +4.1. Mapping Many Addresses Into One Address + + The basic use of NAT accomplishes much the same thing +that Linux's IP Masquerading function does, and it does it +----------- + To be pedantic, what IPFilter provides is really +called NPAT, for Network and Port Address Transla- +tion, which means we can change any of the source +and destination IP Addresses and their source and +destination ports. True NAT only allows one to +change the addresses. + + + + + + + + + + -26- + + +with one simple rule: + + map tun0 192.168.1.0/24 -> 20.20.20.1/32 + +Very simple. Whenever a packet goes out the tun0 interface +with a source address matching the CIDR network mask of +192.168.1.0/24 this packet will be rewritten within the IP +stack such that its source address is 20.20.20.1, and it +will be sent on to its original destination. The system +also keeps a list of what translated connections are in +progress so that it can perform the reverse and remap the +response (which will be directed to 20.20.20.1) to the +internal host that really generated the packet. + + There is a drawback to the rule we have just written, +though. In a large number of cases, we do not happen to +know what the IP address of our outside link is (if we're +using tun0 or ppp0 and a typical ISP) so it makes setting up +our NAT tables a chore. Luckily, NAT is smart enough to +accept an address of 0/32 as a signal that it needs to go +look at what the address of that interface really is and we +can rewrite our rule as follows: + + map tun0 192.168.1.0/24 -> 0/32 + +Now we can load our ipnat rules with impunity and connect to +the outside world without having to edit anything. You do +have to run ipf -y to refresh the address if you get discon- +nected and redial or if your DHCP lease changes, though. + + Some of you may be wondering what happens to the source +port when the mapping happens. With our current rule, the +packet's source port is unchanged from the original source +port. There can be instances where we do not desire this +behavior; maybe we have another firewall further upstream we +have to pass through, or perhaps many hosts are trying to +use the same source port, causing a collision where the rule +doesn't match and the packet is passed untranslated. ipnat +helps us here with the portmap keyword: + + map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000 + +Our rule now shoehorns all the translated connections (which +can be tcp, udp, or tcp/udp) into the port range of 20000 to +30000. + + + +----------- + This is a typical internal address space, since +it's non-routable on the Real Internet it is often +used for internal networks. You should still +block these packets coming in from the outside +world as discussed earlier. + + + + + + + + + + -27- + + +4.2. Mapping Many Addresses Into a Pool of Addresses + + Another use common use of NAT is to take a small stati- +cally allocated block of addresses and map many computers +into this smaller address space. This is easy to accom- +plish using what you already know about the map and portmap +keywords by writing a rule like so: + + map tun0 192.168.0.0/16 -> 20.20.20.0/24 portmap tcp/udp 20000:60000 + +Also, there may be instances where a remote application +requires that multiple connections all come from the same IP +address. We can help with these situations by telling NAT +to statically map sessions from a host into the pool of +addresses and work some magic to choose a port. This uses a +the keyword map-block as follows: + + map-block tun0 192.168.1.0/24 -> 20.20.20.0/24 + +4.3. One to One Mappings + + Occasionally it is desirable to have a system with one +IP address behind the firewall to appear to have a com- +pletely different IP address. One example of how this would +work would be a lab of computers which are then attached to +various networks that are to be put under some kind of test. +In this example, you would not want to have to reconfigure +the entire lab when you could place a NAT system in front +and change the addresses in one simple place. We can do +that with the bimap keyword, for bidirectional mapping. +Bimap has some additional protections on it to ensure a +known state for the connection, whereas the map keyword is +designed to allocate an address and a source port and +rewrite the packet and go on with life. + + bimap tun0 192.168.1.1/32 -> 20.20.20.1/32 + +will accomplish the mapping for one host. + +4.4. Spoofing Services + + Spoofing services? What does that have to do with any- +thing? Plenty. Let's pretend that we have a web server +running on 20.20.20.5, and since we've gotten increasingly +suspicious of our network security, we desire to not run +this server on port 80 since that requires a brief lifespan +as the root user. But how do we run it on a less +privledged port of 8000 in this world of "anything dot com"? +How will anyone find our server? We can use the redirection +facilities of NAT to solve this problem by instructing it to +remap any connections destined for 20.20.20.5:80 to really +point to 20.20.20.5:8000. This uses the rdr keyword: + + rdr tun0 20.20.20.5/32 port 80 -> 192.168.0.5 port 8000 + + + + + + + + + + -28- + + +We can also specify the protocol here, if we wanted to redi- +rect a UDP service, instead of a TCP service (which is the +default). For example, if we had a honeypot on our firewall +to impersonate the popular Back Orifice for Windows, we +could shovel our entire network into this one place with a +simple rule: + + rdr tun0 20.20.20.0/24 port 31337 -> 127.0.0.1 port 31337 udp + +An extremely important point must be made about rdr: You +cannot easily use this feature as a "reflector". E.g: + + rdr tun0 20.20.20.5/32 port 80 -> 20.20.20.6 port 80 tcp + +will not work in the situation where .5 and .6 are on the +same LAN segment. The rdr function is applied to packets +that enter the firewall on the specified interface. When a +packet comes in that matches a rdr rule, its destination +address is then rewritten, it is pushed into ipf for filter- +ing, and should it successfully run the gauntlet of filter +rules, it is then sent to the unix routing code. Since this +packet is still inbound on the same interface that it will +need to leave the system on to reach a host, the system gets +confused. Reflectors don't work. Neither does specifying +the address of the interface the packet just came in on. +Always remember that rdr destinations must exit out of the +firewall host on a different interface. + +4.5. Transparent Proxy Support; Redirection Made Useful + + Since you're installing a firewall, you may have +decided that it is prudent to use a proxy for many of your +outgoing connections so that you can further tighten your +filter rules protecting your internal network, or you may +have run into a situation that the NAT mapping process does +not currently handle properly. This can also be accom- +plished with a redirection statement: + + rdr xl0 0.0.0.0/0 port 21 -> 127.0.0.1 port 21 + +This statement says that any packet coming in on the xl0 +interface destined for any address (0.0.0.0/0) on the ftp +port should be rewritten to connect it with a proxy that is +running on the NAT system on port 21. + +----------- + Yes. There is a way to do this. It's so convo- +luted that I refuse to use it, though. Smart peo- +ple who require this functionality will transpar- +ently redirect into something like TIS plug-gw on +127.0.0.1. Stupid people will set up a dummy loop +interface pair and double rewrite. + This includes 127.0.0.1, by the way. That's on +lo0. Neat, huh? + + + + + + + + + + -29- + + + This specific example of FTP proxying does lead to some +complications when used with web browsers or other auto- +matic-login type clients that are unaware of the require- +ments of communicating with the proxy. There are patches +for TIS Firewall Toolkit'sftp-gw to mate it with the nat +process so that it can determine where you were trying to go +and automatically send you there. Many proxy packages now +work in a transparent proxy environment (Squid for example, +located at http://squid.nlanr.net, works fine.) + + This application of the rdr keyword is often more use- +ful when you wish to force users to authenticate themselves +with the proxy. (For example, you desire your engineers to +be able to surf the web, but you would rather not have your +call-center staff doing so.) + +4.6. Magic Hidden Within NAT; Application Proxies + + Since ipnat provides a method to rewrite packets as +they traverse the firewall, it becomes a convenient place to +build in some application level proxies to make up for well +known deficiencies of that application and typical fire- +walls. For example; FTP. We can make our firewall pay +attention to the packets going across it and when it notices +that it's dealing with an Active FTP session, it can write +itself some temporary rules, much like what happens with +keep state, so that the FTP data connection works. To do +this, we use a rule like so: + + map tun0 192.168.1.0/24 -> 20.20.20.1/32 proxy port ftp ftp/tcp + +You must always remember to place this proxy rule before any +portmap rules, otherwise when portmap comes along and +matches the packet and rewrites it before the proxy gets a +chance to work on it. Remember that ipnat rules are first- +match. + + There also exist proxies for "rcmd" (which we suspect +is berkeley r-* commands which should be forbidden anyway, +thus we haven't looked at what this proxy does) and "raudio" +for Real Audio PNM streams. Likewise, both of these rules +should be put before any portmap rules, if you're doing NAT. + + + +5. Loading and Manipulating Filter Rules; The ipf Utility + + IP Filter rules are loaded by using the ipf utility. +The filter rules can be stored in any file on the system, +but typically these rules are stored in /etc/ipf.rules, +/usr/local/etc/ipf.rules, or /etc/opt/ipf/ipf.rules. + + IP Filter has two sets of rules, the active set and the +inactive set. By default, all operations are performed on + + + + + + + + + + -30- + + +the active set. You can manipulate the inactive set by +adding -I to the ipf command line. The two sets can be +toggled by using the -s command line option. This is very +useful for testing new rule sets without wiping out the old +rule set. + + Rules can also be removed from the list instead of +added by using the -r command line option, but it is gener- +ally a safer idea to flush the rule set that you're working +on with -F and completely reload it when making changes. + + In summary, the easiest way to load a rule set is ipf +-Fa -f /etc/ipf.rules. For more complicated manipulations +of the rule set, please see the ipf(1) man page. + +6. Loading and Manipulating NAT Rules; The ipnat Utility + + NAT rules are loaded by using the ipnat utility. The +NAT rules can be stored in any file on the system, but typi- +cally these rules are stored in /etc/ipnat.rules, +/usr/local/etc/ipnat.rules, or /etc/opt/ipf/ipnat.rules. + + Rules can also be removed from the list instead of +added by using the -r command line option, but it is gener- +ally a safer idea to flush the rule set that you're working +on with -C and completely reload it when making changes. +Any active mappings are not affected by -C, and can be +removed with -F. + + NAT rules and active mappings can be examined with the +-l command line option. + + In summary, the easiest way to load a NAT rule set is +ipnat -CF -f /etc/ipnat.rules. + +7. Monitoring and Debugging + + There will come a time when you are interested in what +your firewall is actually doing, and ipfilter would be +incomplete if it didn't have a full suite of status monitor- +ing tools. + +7.1. The ipfstat utility + + In its simplest form, ipfstat displays a table of +interesting data about how your firewall is performing, such +as how many packets have been passed or blocked, if they +were logged or not, how many state entries have been made, +and so on. Here's an example of something you might see +from running the tool: + + # ipfstat + input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0 + output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0 + + + + + + + + + + -31- + + + input packets logged: blocked 99286 passed 0 + output packets logged: blocked 0 passed 0 + packets logged: input 0 output 0 + log failures: input 3898 output 0 + fragment state(in): kept 0 lost 0 + fragment state(out): kept 0 lost 0 + packet state(in): kept 169364 lost 0 + packet state(out): kept 431395 lost 0 + ICMP replies: 0 TCP RSTs sent: 0 + Result cache hits(in): 1215208 (out): 1098963 + IN Pullups succeeded: 2 failed: 0 + OUT Pullups succeeded: 0 failed: 0 + Fastroute successes: 0 failures: 0 + TCP cksum fails(in): 0 (out): 0 + Packet log flags set: (0) + none + +ipfstat is also capable of showing you your current rule +list. Using the -i or the -o flag will show the currently +loaded rules for in or out, respectively. Adding a -h to +this will provide more useful information at the same time +by showing you a "hit count" on each rule. For example: + + # ipfstat -ho + 2451423 pass out on xl0 from any to any + 354727 block out on ppp0 from any to any + 430918 pass out quick on ppp0 proto tcp/udp from 20.20.20.0/24 to any keep state keep frags + +From this, we can see that perhaps there's something abnor- +mal going on, since we've got a lot of blocked packets out- +bound, even with a very permissive pass out rule. Something +here may warrant further investigation, or it may be func- +tioning perfectly by design. ipfstat can't tell you if your +rules are right or wrong, it can only tell you what is hap- +pening because of your rules. + +To further debug your rules, you may want to use the -n +flag, which will show the rule number next to each rule. + + # ipfstat -on + @1 pass out on xl0 from any to any + @2 block out on ppp0 from any to any + @3 pass out quick on ppp0 proto tcp/udp from 20.20.20.0/24 to any keep state keep frags + +The final piece of really interesting information that ipfs- +tat can provide us is a dump of the state table. This is +done with the -s flag: + + # ipfstat -s + 281458 TCP + 319349 UDP + 0 ICMP + 19780145 hits + 5723648 misses + + + + + + + + + + -32- + + + 0 maximum + 0 no memory + 1 active + 319349 expired + 281419 closed + 100.100.100.1 -> 20.20.20.1 ttl 864000 pass 20490 pr 6 state 4/4 + pkts 196 bytes 17394 987 -> 22 585538471:2213225493 16592:16500 + pass in log quick keep state + pkt_flags & b = 2, pkt_options & ffffffff = 0 + pkt_security & ffff = 0, pkt_auth & ffff = 0 + +Here we see that we have one state entry for a TCP connec- +tion. The output will vary slightly from version to ver- +sion, but the basic information is the same. We can see in +this connection that we have a fully established connection +(represented by the 4/4 state. Other states are incomplete +and will be documented fully later.) We can see that the +state entry has a time to live of 240 hours, which is an +absurdly long time, but is the default for an established +TCP connection. This TTL counter is decremented every sec- +ond that the state entry is not used, and will finally +result in the connection being purged if it has been left +idle. The TTL is also reset to 864000 whenever the state +IS used, ensuring that the entry will not time out while it +is being actively used. We can also see that we have passed +196 packets consisting of about 17kB worth of data over this +connection. We can see the ports for both endpoints, in +this case 987 and 22; which means that this state entry rep- +resents a connection from 100.100.100.1 port 987 to +20.20.20.1 port 22. The really big numbers in the second +line are the TCP sequence numbers for this connection, which +helps to ensure that someone isn't easily able to inject a +forged packet into your session. The TCP window is also +shown. The third line is a synopsis of the implicit rule +that was generated by the keep state code, showing that this +connection is an inbound connection. + +7.2. The ipmon utility + + ipfstat is great for collecting snapshots of what's +going on on the system, but it's often handy to have some +kind of log to look at and watch events as they happen in +time. ipmon is this tool. ipmon is capable of watching +the packet log (as created with the log keyword in your +rules), the state log, or the nat log, or any combination of +the three. This tool can either be run in the foreground, +or as a daemon which logs to syslog or a file. If we wanted +to watch the state table in action, ipmon -o S would show +this: + + # ipmon -o S + 01/08/1999 15:58:57.836053 STATE:NEW 100.100.100.1,53 -> 20.20.20.15,53 PR udp + 01/08/1999 15:58:58.030815 STATE:NEW 20.20.20.15,123 -> 128.167.1.69,123 PR udp + 01/08/1999 15:59:18.032174 STATE:NEW 20.20.20.15,123 -> 128.173.14.71,123 PR udp + + + + + + + + + + -33- + + + 01/08/1999 15:59:24.570107 STATE:EXPIRE 100.100.100.1,53 -> 20.20.20.15,53 PR udp Pkts 4 Bytes 356 + 01/08/1999 16:03:51.754867 STATE:NEW 20.20.20.13,1019 -> 100.100.100.10,22 PR tcp + 01/08/1999 16:04:03.070127 STATE:EXPIRE 20.20.20.13,1019 -> 100.100.100.10,22 PR tcp Pkts 63 Bytes 4604 + +Here we see a state entry for an external dns request off +our nameserver, two xntp pings to well-known time servers, +and a very short lived outbound ssh connection. + + ipmon is also capable of showing us what packets have +been logged. For example, when using state, you'll often +run into packets like this: + + # ipmon -o I + 15:57:33.803147 ppp0 @0:2 b 100.100.100.103,443 -> 20.20.20.10,4923 PR tcp len 20 1488 -A + +What does this mean? The first field is obvious, it's a +timestamp. The second field is also pretty obvious, it's +the interface that this event happened on. The third field +@0:2 is something most people miss. This is the rule that +caused the event to happen. Remember ipfstat -in? If you +wanted to know where this came from, you could look there +for rule 2 in rule group 0. The fourth field, the little +"b" says that this packet was blocked, and you'll generally +ignore this unless you're logging passed packets as well, +which would be a little "p" instead. The fifth and sixth +fields are pretty self-explanatory, they say where this +packet came from and where it was going. The seventh ("PR") +and eighth fields tell you the protocol and the ninth field +tells you the size of the packet. The last part, the "-A" +in this case, tells you the flags that were on the packet; +This one was an ACK packet. Why did I mention state ear- +lier? Due to the often laggy nature of the Internet, some- +times packets will be regenerated. Sometimes, you'll get +two copies of the same packet, and your state rule which +keeps track of sequence numbers will have already seen this +packet, so it will assume that the packet is part of a dif- +ferent connection. Eventually this packet will run into a +real rule and have to be dealt with. You'll often see the +last packet of a session being closed get logged because the +keep state code has already torn down the connection before +the last packet has had a chance to make it to your fire- +wall. This is normal, do not be alarmed. Another example +packet that might be logged: + + 12:46:12.470951 xl0 @0:1 S 20.20.20.254 -> 255.255.255.255 PR icmp len 20 9216 icmp 9/0 + +----------- + For a technical presentation of the IP Filter +stateful inspection engine, please see the white +paper Real Stateful TCP Packet Filtering in IP +Filter, by Guido van Rooij. This paper may be +found at +<http://www.iae.nl/users/guido/papers/tcp_filter- +ing.ps.gz> + + + + + + + + + + -34- + + +This is a ICMP router discovery broadcast. We can tell by +the ICMP type 9/0. + +Finally, ipmon also lets us look at the NAT table in action. + + # ipmon -o N + 01/08/1999 05:30:02.466114 @2 NAT:RDR 20.20.20.253,113 <- -> 20.20.20.253,113 [100.100.100.13,45816] + 01/08/1999 05:30:31.990037 @2 NAT:EXPIRE 20.20.20.253,113 <- -> 20.20.20.253,113 [100.100.100.13,45816] Pkts 10 Bytes 455 + +This would be a redirection to an identd that lies to pro- +vide ident service for the hosts behind our NAT, since they +are typically unable to provide this service for themselves +with ordinary natting. + + + + +8. Specific Applications of IP Filter - Things that don't +fit, but should be mentioned anyway. + +8.1. Keep State With Servers and Flags. + + Keeping state is a good thing, but it's quite easy to +make a mistake in the direction that you want to keep state +in. Generally, you want to have a keep state keyword on +the first rule that interacts with a packet for the connec- +tion. One common mistake that is made when mixing state +tracking with filtering on flags is this: + + block in all + pass in quick proto tcp from any to 20.20.20.20/32 port = 23 flags S + pass out all keep state + +That certainly appears to allow a connection to be created +to the telnet server on 20.20.20.20, and the replies to go +back. If you try using this rule, you'll see that it does +work--Momentarily. Since we're filtering for the SYN flag, +the state entry never fully gets completed, and the default +time to live for an incomplete state is 60 seconds. + +We can solve this by rewriting the rules in one of two ways: + +1) + + block in all + pass in quick proto tcp from any to 20.20.20.20/32 port = 23 keep state + block out all + +or: + +2) + + block in all + pass in quick proto tcp from any to 20.20.20.20/32 port = 23 flags S keep state + + + + + + + + + + -35- + + + pass out all keep state + +Either of these sets of rules will result in a fully estab- +lished state entry for a connection to your server. + +8.2. Coping With FTP + + FTP is one of those protocols that you just have to sit +back and ask "What the heck were they thinking?" FTP has +many problems that the firewall administrator needs to deal +with. What's worse, the problems the administrator must +face are different between making ftp clients work and mak- +ing ftp servers work. + + Within the FTP protocol, there are two forms of data +transfer, called active and passive. Active transfers are +those where the server connects to an open port on the +client to send data. Conversely, passive transfers are +those where the client connects to the server to receive +data. + +8.2.1. Running an FTP Server + + In running an FTP server, handling Active FTP sessions +is easy to setup. At the same time, handling Passive FTP +sessions is a big problem. First we'll cover how to handle +Active FTP, then move on to Passive. Generally, we can han- +dle Active FTP sessions like we would an incoming HTTP or +SMTP connection; just open the ftp port and let keep state +do the rest: + + pass in quick proto tcp from any to 20.20.20.20/32 port = 21 flags S keep state + pass out proto tcp all keep state + +These rules will allow Active FTP sessions, the most common +type, to your ftp server on 20.20.20.20. + + The next challenge becomes handling Passive FTP connec- +tions. Web browsers default to this mode, so it's becoming +quite popular and as such it should be supported. The prob- +lem with passive connections are that for every passive con- +nection, the server starts listening on a new port (usually +above 1023). This is essentially like creating a new +unknown service on the server. Assuming we have a good +firewall with a default-deny policy, that new service will +be blocked, and thus Active FTP sessions are broken. Don't +despair! There's hope yet to be had. + + A person's first inclination to solving this problem +might be to just open up all ports above 1023. In truth, +this will work: + + pass in quick proto tcp from any to 20.20.20.20/32 port > 1023 flags S keep state + pass out proto tcp all keep state + + + + + + + + + + -36- + + +This is somewhat unsatisfactory, though. By letting every- +thing above 1023 in, we actually open ourselves up for a +number of potential problems. While 1-1023 is the desig- +nated area for server services to run, numerous programs +decided to use numbers higher than 1023, such as nfsd and X. + + The good news is that your FTP server gets to decide +which ports get assigned to passive sessions. This means +that instead of opening all ports above 1023, you can allo- +cate ports 15001-19999 as ftp ports and only open that range +of your firewall up. In wu-ftpd, this is done with the pas- +sive ports option in ftpaccess. Please see the man page on +ftpaccess for details in wu-ftpd configuration. On the +ipfilter side, all we need do is setup corresponding rules: + + pass in quick proto tcp from any to 20.20.20.20/32 port 15000 >< 20000 flags S keep state + pass out proto tcp all keep state + +If even this solution doesn't satisfy you, you can always +hack IPF support into your FTP server, or FTP server support +into IPF. + +8.2.2. Running an FTP Client + + While FTP server support is still less than perfect in +IPF, FTP client support has been working well since 3.3.3. +As with FTP servers, there are two types of ftp client +transfers: passive and active. + + The simplest type of client transfer from the fire- +wall's standpoint is the passive transfer. Assuming you're +keeping state on all outbound tcp sessions, passive trans- +fers will work already. If you're not doing this already, +please consider the following: + + pass out proto tcp all keep state + +The second type of client transfer, active, is a bit more +troublesome, but nonetheless a solved problem. Active +transfers cause the server to open up a second connection +back to the client for data to flow through. This is nor- +mally a problem when there's a firewall in the middle, stop- +ping outside connections from coming back in. To solve +this, ipfilter includes an ipnat proxy which temporarily +opens up a hole in the firewall just for the FTP server to +get back to the client. Even if you're not using ipnat to +do nat, the proxy is still effective. The following rules +is the bare minimum to add to the ipnat configuration file +(ep0 should be the interface name of the outbound network +connection): + + map ep0 0/0 -> 0/32 proxy port 21 ftp/tcp + + + + + + + + + + + + -37- + + +For more details on ipfilter's internal proxies, see section +3.6 + +8.3. Assorted Kernel Variables + + There are some useful kernel tunes that either need to +be set for ipf to function, or are just generally handy to +know about for building firewalls. The first major one you +must set is to enable IP Forwarding, otherwise ipf will do +very little, as the underlying ip stack won't actually route +packets. + +IP Forwarding: + +openbsd: + net.inet.ip.forwarding=1 + + +freebsd: + net.inet.ip.forwarding=1 + + +netbsd: + net.inet.ip.forwarding=1 + + +solaris: + ndd -set /dev/ip ip_forwarding 1 + +Ephemeral Port Adjustment: + +openbsd: + net.inet.ip.portfirst = 25000 + + +freebsd: + net.inet.ip.portrange.first = 25000 net.inet.ip.por- + trange.last = 49151 + + +netbsd: + net.inet.ip.anonportmin = 25000 net.inet.ip.anonportmax + = 49151 + + +solaris: + ndd -set /dev/tcp tcp_smallest_anon_port 25000 + ndd -set /dev/tcp tcp_largest_anon_port 65535 + +Other Useful Values: + +openbsd: + net.inet.ip.sourceroute = 0 + net.inet.ip.directed-broadcast = 0 + + + + + + + + + + -38- + + +freebsd: + net.inet.ip.sourceroute=0 + net.ip.accept_sourceroute=0 + + +netbsd: + net.inet.ip.allowsrcrt=0 + net.inet.ip.forwsrcrt=0 + net.inet.ip.directed-broadcast=0 + net.inet.ip.redirect=0 + + +solaris: + ndd -set /dev/ip ip_forward_directed_broadcasts 0 + ndd -set /dev/ip ip_forward_src_routed 0 + ndd -set /dev/ip ip_respond_to_echo_broadcast 0 + +In addition, freebsd has some ipf specific sysctl variables. + + net.inet.ipf.fr_flags: 0 + net.inet.ipf.fr_pass: 514 + net.inet.ipf.fr_active: 0 + net.inet.ipf.fr_tcpidletimeout: 864000 + net.inet.ipf.fr_tcpclosewait: 60 + net.inet.ipf.fr_tcplastack: 20 + net.inet.ipf.fr_tcptimeout: 120 + net.inet.ipf.fr_tcpclosed: 1 + net.inet.ipf.fr_udptimeout: 120 + net.inet.ipf.fr_icmptimeout: 120 + net.inet.ipf.fr_defnatage: 1200 + net.inet.ipf.fr_ipfrttl: 120 + net.inet.ipf.ipl_unreach: 13 + net.inet.ipf.ipl_inited: 1 + net.inet.ipf.fr_authsize: 32 + net.inet.ipf.fr_authused: 0 + net.inet.ipf.fr_defaultauthage: 600 + + + + +9. Fun with ipf! + + This section doesn't necessarily teach you anything new +about ipf, but it may raise an issue or two that you haven't +yet thought up on your own, or tickle your brain in a way +that you invent something interesting that we haven't +thought of. + +9.1. Localhost Filtering + + A long time ago at a university far, far away, Wietse +Venema created the tcp-wrapper package, and ever since, it's +been used to add a layer of protection to network services +all over the world. This is good. But, tcp-wrappers have + + + + + + + + + + -39- + + +flaws. For starters, they only protect TCP services, as the +name suggests. Also, unless you run your service from +inetd, or you have specifically compiled it with libwrap and +the appropriate hooks, your service isn't protected. This +leaves gigantic holes in your host security. We can plug +these up by using ipf on the local host. For example, my +laptop often gets plugged into or dialed into networks that +I don't specifically trust, and so, I use the following rule +set: + + pass in quick on lo0 all + pass out quick on lo0 all + + block in log all + block out all + + pass in quick proto tcp from any to any port = 113 flags S keep state + pass in quick proto tcp from any to any port = 22 flags S keep state + pass in quick proto tcp from any port = 20 to any port 39999 >< 45000 flags S keep state + + pass out quick proto icmp from any to any keep state + pass out quick proto tcp/udp from any to any keep state keep frags + +It's been like that for quite a while, and I haven't suf- +fered any pain or anguish as a result of having ipf loaded +up all the time. If I wanted to tighten it up more, I could +switch to using the NAT ftp proxy and I could add in some +rules to prevent spoofing. But even as it stands now, this +box is far more restrictive about what it presents to the +local network and beyond than the typical host does. This +is a good thing if you happen to run a machine that allows a +lot of users on it, and you want to make sure one of them +doesn't happen to start up a service they wern't supposed +to. It won't stop a malicious hacker with root access from +adjusting your ipf rules and starting a service anyway, but +it will keep the "honest" folks honest, and your weird ser- +vices safe, cozy and warm even on a malicious LAN. A big +win, in my opinion. Using local host filtering in addition +to a somewhat less-restrictive "main firewall" machine can +solve many performance issues as well as political night- +mares like "Why doesn't ICQ work?" and "Why can't I put a +web server on my own workstation! It's MY WORKSTATION!!" +Another very big win. Who says you can't have security and +convienence at the same time? + +9.2. What Firewall? Transparent filtering. + + One major concern in setting up a firewall is the +integrity of the firewall itself. Can somebody break into +your firewall, thereby subverting its ruleset? This is a +common problem administrators must face, particularly when +they're using firewall solutions on top of their Unix/NT +machines. Some use it as an arguement for blackbox hardware +solutions, under the flawed notion that inherent obscurity + + + + + + + + + + -40- + + +of their closed system increases their security. We have a +better way. + + Many network admins are familiar with the common ether- +net bridge. This is a device that connects two separate +ethernet segments to make them one. An ethernet bridge is +typically used to connect separate buildings, switch network +speeds, and extend maximum wire lengths. Hubs and switches +are common bridges, sometimes they're just 2 ported devices +called repeaters. Recent versions of Linux, OpenBSD, +NetBSD, and FreeBSD include code to convert $1000 PCs into +$10 bridges, too! What all bridges tend to have in common +is that though they sit in the middle of a connection +between two machines, the two machines don't know the bridge +is there. Enter ipfilter and OpenBSD. + + Ethernet bridging takes place at Layer2 on the ISO +stack. IP takes place on Layer3. IP Filter in primarily +concerned with Layer3, but dabbles in Layer2 by working with +interfaces. By mixing IP filter with OpenBSD's bridge +device, we can create a firewall that is both invisible and +unreachable. The system needs no IP address, it doesn't +even need to reveal its ethernet address. The only telltale +sign that the filter might be there is that latency is some- +what higher than a piece of cat5 would normally make it, and +that packets don't seem to make it to their final destina- +tion. + + The setup for this sort of ruleset is surprisingly sim- +ple, too. In OpenBSD, the first bridge device is named +bridge0. Say we have two ethernet cards in our machine as +well, xl0 and xl1. To turn this machine into a bridge, all +one need do is enter the following three commands: + + brconfig bridge0 add xl0 add xl1 up + ifconfig xl0 up + ifconfig xl1 up + +At ths point, all traffic ariving on xl0 is sent out xl1 and +all traffic on xl1 is sent out xl0. You'll note that nei- +ther interface has been assigned an IP address, nor do we +need assign one. All things considered, it's likely best we +not add one at all. + + Rulesets behave essentially the as the always have. +Though there is a bridge0 interface, we don't filter based +on it. Rules continue to be based upon the particular +interface we're using, making it important which network +cable is plugged into which network card in the back of the +machine. Let's start with some basic filtering to illis- +trate what's happened. Assume the network used to look like +this: + + + + + + + + + + + + -41- + + + 20.20.20.1 <---------------------------------> 20.20.20.0/24 network hub + +That is, we have a router at 20.20.20.1 connected to the +20.20.20.0/24 network. All packets from the 20.20.20.0/24 +network go through 20.20.20.1 to get to the outside world +and vice versa. Now we add the Ipf Bridge: + + 20.20.20.1 <-------/xl0 IpfBridge xl1/-------> 20.20.20.0/24 network hub + +We also have the following ruleset loaded on the IpfBridge +host: + + pass in quick all + pass out quick all + +With this ruleset loaded, the network is functionally iden- +tical. As far as the 20.20.20.1 router is concerned, and as +far as the 20.20.20.0/24 hosts are concerned, the two net- +work diagrams are identical. Now let's change the ruleset +some: + + block in quick on xl0 proto icmp + pass in quick all + pass out quick all + +Still, 20.20.20.1 and 20.20.20.0/24 think the network is +identical, but if 20.20.20.1 attempts to ping 20.20.20.2, it +will never get a reply. What's more, 20.20.20.2 won't even +get the packet in the first place. IPfilter will intercept +the packet before it even gets to the other end of the vir- +tual wire. We can put a bridged filter anywhere. Using +this method we can shrink the network trust circle down an +individual host level (given enough ethernet cards:-) + + Blocking icmp from the world seems kind of silly, espe- +cially if you're a sysadmin and like pinging the world, to +traceroute, or to resize your MTU. Let's construct a better +ruleset and take advantage of the original key feature of +ipf: stateful inspection. + + pass in quick on xl1 proto tcp keep state + pass in quick on xl1 proto udp keep state + pass in quick on xl1 proto icmp keep state + block in quick on xl0 + +In this situation, the 20.20.20.0/24 network (perhaps more +aptly called the xl1 network) can now reach the outside +world, but the outside world can't reach it, and it can't +figure out why, either. The router is accessible, the hosts +are active, but the outside world just can't get in. Even +if the router itself were compromised, the firewall would +still be active and successful. + + + + + + + + + + + + -42- + + + So far, we've been filtering by interface and protocol +only. Even though bridging is concerned layer2, we can +still discriminate based on IP address. Normally we have a +few services running, so our ruleset may look like this: + + pass in quick on xl1 proto tcp keep state + pass in quick on xl1 proto udp keep state + pass in quick on xl1 proto icmp keep state + block in quick on xl1 # nuh-uh, we're only passing tcp/udp/icmp sir. + pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state + pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80 flags S keep state + block in quick on xl0 + +Now we have a network where 20.20.20.2 is a zone serving +name server, 20.20.20.3 is an incoming mail server, and +20.20.20.7 is a web server. + + Bridged IP Filter is not yet perfect, we must confess. + + First, You'll note that all the rules are setup using +the in direction instead of a combination of in and out. +This is because the out direction is presently unimplemented +with bridging in OpenBSD. This was originally done to pre- +vent vast performance drops using multiple interfaces. Work +has been done in speeding it up, but it remains unimple- +mented. If you really want this feature, you might try your +hand at working on the code or asking the OpenBSD people how +you can help. + + Second, using IP Filter with bridging makes the use of +IPF's NAT features inadvisable, if not downright dangerous. +The first problem is that it would give away that there's a +filtering bridge. The second problem would be that the +bridge has no IP address to masquerade with, which will most +assuredly lead to confusion and perhaps a kernel panic to +boot. You can, of course, put an IP address on the outbound +interface to make NAT work, but part of the glee of bridging +is thus diminished. + +9.2.1. Using Transparent Filtering to Fix Network Design +Mistakes + + Many organizations started using IP well before they +thought a firewall or a subnet would be a good idea. Now +they have class-C sized networks or larger that include all +their servers, their workstations, their routers, coffee +makers, everything. The horror! Renumbering with proper +subnets, trust levels, filters, and so are in both time con- +suming and expensive. The expense in hardware and man hours +alone is enough to make most organizations unwilling to +really solve the problem, not to mention the downtime +involved. The typical problem network looks like this: + + + + + + + + + + -43- + + + 20.20.20.1 router 20.20.20.6 unix server + 20.20.20.2 unix server 20.20.20.7 nt workstation + 20.20.20.3 unix server 20.20.20.8 nt server + 20.20.20.4 win98 workstation 20.20.20.9 unix workstation + 20.20.20.5 intelligent switch 20.20.20.10 win95 workstation + +Only it's about 20 times larger and messier and frequently +undocumented. Ideally, you'd have all the trusting servers +in one subnet, all the work- stations in another, and the +network switches in a third. Then the router would filter +packets between the subnets, giving the workstations limited +access to the servers, nothing access to the switches, and +only the sysadmin's workstation access to the coffee pot. +I've never seen a class-C sized network with such coherence. +IP Filter can help. + + To start with, we're going to separate the router, the +workstations, and the servers. To do this we're going to +need 2 hubs (or switches) which we probably already have, +and an IPF machine with 3 ethernet cards. We're going to +put all the servers on one hub and all the workstations on +the other. Normally we'd then connect the hubs to each +other, then to the router. Instead, we're going to plug the +router into IPF's xl0 interface, the servers into IPF's xl1 +interface, and the workstations into IPF's xl2 interface. +Our network diagram looks something like this: + + | 20.20.20.2 unix server + router (20.20.20.1) ____________| 20.20.20.3 unix server + | / | 20.20.20.6 unix server + | /xl1 | 20.20.20.7 nt server + ------------/xl0 IPF Bridge < + xl2 | 20.20.20.4 win98 workstation + ____________| 20.20.20.8 nt workstation + | 20.20.20.9 unix workstation + | 20.20.20.10 win95 workstation + +Where once there was nothing but interconnecting wires, now +there's a filtering bridge that not a single host needs to +be modified to take advantage of. Presumably we've already +enabled bridging so the network is behaving perfectly nor- +mally. Further, we're starting off with a ruleset much like +our last ruleset: + + pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state + pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80 flags S keep state + block in quick on xl0 + pass in quick on xl1 proto tcp keep state + pass in quick on xl1 proto udp keep state + pass in quick on xl1 proto icmp keep state + block in quick on xl1 # nuh-uh, we're only passing tcp/udp/icmp sir. + pass in quick on xl2 proto tcp keep state + + + + + + + + + + -44- + + + pass in quick on xl2 proto udp keep state + pass in quick on xl2 proto icmp keep state + block in quick on xl2 # nuh-uh, we're only passing tcp/udp/icmp sir. + +Once again, traffic coming from the router is restricted to +DNS, SMTP, and HTTP. At the moment, the servers and the +workstations can exchange traffic freely. Depending on what +kind of organization you are, there might be something about +this network dynamic you don't like. Perhaps you don't want +your workstations getting access to your servers at all? +Take the xl2 ruleset of: + + pass in quick on xl2 proto tcp keep state + pass in quick on xl2 proto udp keep state + pass in quick on xl2 proto icmp keep state + block in quick on xl2 # nuh-uh, we're only passing tcp/udp/icmp sir. + +And change it to: + + block in quick on xl2 from any to 20.20.20.0/24 + pass in quick on xl2 proto tcp keep state + pass in quick on xl2 proto udp keep state + pass in quick on xl2 proto icmp keep state + block in quick on xl2 # nuh-uh, we're only passing tcp/udp/icmp sir. + +Perhaps you want them to just get to the servers to get and +send their mail with IMAP? Easily done: + + pass in quick on xl2 proto tcp from any to 20.20.20.3/32 port=25 + pass in quick on xl2 proto tcp from any to 20.20.20.3/32 port=143 + block in quick on xl2 from any to 20.20.20.0/24 + pass in quick on xl2 proto tcp keep state + pass in quick on xl2 proto udp keep state + pass in quick on xl2 proto icmp keep state + block in quick on xl2 # nuh-uh, we're only passing tcp/udp/icmp sir. + +Now your workstations and servers are protected from the +outside world, and the servers are protected from your work- +stations. + + Perhaps the opposite is true, maybe you want your work- +stations to be able to get to the servers, but not the out- +side world. After all, the next generation of exploits is +breaking the clients, not the servers. In this case, you'd +change the xl2 rules to look more like this: + + pass in quick on xl2 from any to 20.20.20.0/24 + block in quick on xl2 + +Now the servers have free reign, but the clients can only +connect to the servers. We might want to batten down the +hatches on the servers, too: + + pass in quick on xl1 from any to 20.20.20.0/24 + + + + + + + + + + -45- + + + block in quick on xl1 + +With the combination of these two, the clients and servers +can talk to each other, but neither can access the outside +world (though the outside world can get to the few services +from earlier). The whole ruleset would look something like +this: + + pass in quick on xl0 proto udp from any to 20.20.20.2/32 port=53 keep state + pass in quick on xl0 proto tcp from any to 20.20.20.2/32 port=53 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.3/32 port=25 flags S keep state + pass in quick on xl0 proto tcp from any to 20.20.20.7/32 port=80 flags S keep state + block in quick on xl0 + pass in quick on xl1 from any to 20.20.20.0/24 + block in quick on xl1 + pass in quick on xl2 from any to 20.20.20.0/24 + block in quick on xl2 + +So remember, when your network is a mess of twisty IP +addresses and machine classes, transparent filtered bridges +can solve a problem that would otherwise be lived with and +perhaps someday exploited. + +9.3. Drop-Safe Logging With dup-to and to. + + Until now, we've been using the filter to drop packets. +Instead of dropping them, let's consider passing them on to +another system that can do something useful with this infor- +mation beyond the logging we can perform with ipmon. Our +firewall system, be it a bridge or a router, can have as +many interfaces as we can cram into the system. We can use +this information to create a "drop-safe" for our packets. A +good example of a use for this would be to implement an +intrusion detection network. For starters, it might be +desirable to hide the presence of our intrusion detection +systems from our real network so that we can keep them from +being detected. + + Before we get started, there are some operational char- +acteristics that we need to make note of. If we are only +going to deal with blocked packets, we can use either the to +keyword or the fastroute keyword. (We'll cover the differ- +ences between these two later) If we're going to pass the +packets like we normally would, we need to make a copy of +the packet for our drop-safe log with the dup-to keyword. + +9.3.1. The dup-to Method + + If, for example, we wanted to send a copy of everything +going out the xl3 interface off to our drop-safe network on +ed0, we would use this rule in our filter list: + + pass out on xl3 dup-to ed0 from any to any + + + + + + + + + + + -46- + + +You might also have a need to send the packet directly to a +specific IP address on your drop-safe network instead of +just making a copy of the packet out there and hoping for +the best. To do this, we modify our rule slightly: + + pass out on xl3 dup-to ed0:192.168.254.2 from any to any + +But be warned that this method will alter the copied +packet's destination address, and may thus destroy the use- +fulness of the log. For this reason, we recommend only +using the known address method of logging when you can be +certain that the address that you're logging to corresponds +in some way to what you're logging for (e.g.: don't use +"192.168.254.2" for logging for both your web server and +your mail server, since you'll have a hard time later trying +to figure out which system was the target of a specific set +of packets.) + + This technique can be used quite effectively if you +treat an IP Address on your drop-safe network in much the +same way that you would treat a Multicast Group on the real +internet. (e.g.: "192.168.254.2" could be the channel for +your http traffic analysis system, "23.23.23.23" could be +your channel for telnet sessions, and so on.) You don't +even need to actually have this address set as an address or +alias on any of your analysis systems. Normally, your +ipfilter machine would need to ARP for the new destination +address (using dup-to ed0:192.168.254.2 style, of course) +but we can avoid that issue by creating a static arp entry +for this "channel" on our ipfilter system. + + In general, though, dup-to ed0 is all that is required +to get a new copy of the packet over to our drop-safe net- +work for logging and examination. + +9.3.2. The to Method + + The dup-to method does have an immediate drawback, +though. Since it has to make a copy of the packet and +optionally modify it for its new destination, it's going to +take a while to complete all this work and be ready to deal +with the next packet coming in to the ipfilter system. + + If we don't care about passing the packet to its normal +destination and we were going to block it anyway, we can +just use the to keyword to push this packet past the normal +routing table and force it to go out a different interface +than it would normally go out. + + block in quick on xl0 to ed0 proto tcp from any to any port < 1024 + +we use block quick for to interface routing, because like +fastroute, the to interface code will generate two packet +paths through ipfilter when used with pass, and likely cause + + + + + + + + + + -47- + + +your system to panic. + + + +10. Bogus Network Filtering, the ultimate in current anti- +spoofing technology. + + We've spent a little bit of time tracking down the cur- +rent vast tracts of IP address space that have been reserved +by the IANA for various reasons, or are otherwise not cur- +rently in use at the time this document was written. Since +none of these address ranges should be in use currently, +there should be no legitimate reason to ever see them as a +source address, or to send them traffic as a destination +address, right? Right! + + So without further ado, the complete list of bogus net- +works: + + # + # s/OUTSIDE/outside-interface (eg: fxp0) + # s/MYNET/network-cidr-address (eg: 1.2.3.0/24) + # + block in on OUTSIDE all + block in quick on OUTSIDE from 0.0.0.0/7 to any + block in quick on OUTSIDE from 2.0.0.0/8 to any + block in quick on OUTSIDE from 5.0.0.0/8 to any + block in quick on OUTSIDE from 10.0.0.0/8 to any + block in quick on OUTSIDE from 23.0.0.0/8 to any + block in quick on OUTSIDE from 27.0.0.0/8 to any + block in quick on OUTSIDE from 31.0.0.0/8 to any + block in quick on OUTSIDE from 67.0.0.0/8 to any + block in quick on OUTSIDE from 68.0.0.0/6 to any + block in quick on OUTSIDE from 72.0.0.0/5 to any + block in quick on OUTSIDE from 80.0.0.0/4 to any + block in quick on OUTSIDE from 96.0.0.0/3 to any + block in quick on OUTSIDE from 127.0.0.0/8 to any + block in quick on OUTSIDE from 128.0.0.0/16 to any + block in quick on OUTSIDE from 128.66.0.0/16 to any + block in quick on OUTSIDE from 169.254.0.0/16 to any + block in quick on OUTSIDE from 172.16.0.0/12 to any + block in quick on OUTSIDE from 191.255.0.0/16 to any + block in quick on OUTSIDE from 192.0.0.0/16 to any + block in quick on OUTSIDE from 192.168.0.0/16 to any + block in quick on OUTSIDE from 197.0.0.0/8 to any + block in quick on OUTSIDE from 201.0.0.0/8 to any + block in quick on OUTSIDE from 204.152.64.0/23 to any + block in quick on OUTSIDE from 224.0.0.0/3 to any + block in quick on OUTSIDE from MYNET to any + # Your pass rules come here... + + block out on OUTSIDE all + block out quick on OUTSIDE from !MYNET to any + block out quick on OUTSIDE from MYNET to 0.0.0.0/7 + + + + + + + + + + -48- + + + block out quick on OUTSIDE from MYNET to 2.0.0.0/8 + block out quick on OUTSIDE from MYNET to 5.0.0.0/8 + block out quick on OUTSIDE from MYNET to 10.0.0.0/8 + block out quick on OUTSIDE from MYNET to 23.0.0.0/8 + block out quick on OUTSIDE from MYNET to 27.0.0.0/8 + block out quick on OUTSIDE from MYNET to 31.0.0.0/8 + block out quick on OUTSIDE from MYNET to 67.0.0.0/8 + block out quick on OUTSIDE from MYNET to 68.0.0.0/6 + block out quick on OUTSIDE from MYNET to 72.0.0.0/5 + block out quick on OUTSIDE from MYNET to 80.0.0.0/4 + block out quick on OUTSIDE from MYNET to 96.0.0.0/3 + block out quick on OUTSIDE from MYNET to 127.0.0.0/8 + block out quick on OUTSIDE from MYNET to 128.0.0.0/16 + block out quick on OUTSIDE from MYNET to 128.66.0.0/16 + block out quick on OUTSIDE from MYNET to 169.254.0.0/16 + block out quick on OUTSIDE from MYNET to 172.16.0.0/12 + block out quick on OUTSIDE from MYNET to 191.255.0.0/16 + block out quick on OUTSIDE from MYNET to 192.0.0.0/16 + block out quick on OUTSIDE from MYNET to 192.168.0.0/16 + block out quick on OUTSIDE from MYNET to 197.0.0.0/8 + block out quick on OUTSIDE from MYNET to 201.0.0.0/8 + block out quick on OUTSIDE from MYNET to 204.152.64.0/23 + block out quick on OUTSIDE from MYNET to 224.0.0.0/3 + # Your pass rules come here... + +If you're going to use these, we suggest that you become +familiar with whois.arin.net and keep an occasional eye on +these, as the IANA isn't going to notify you when they allo- +cate one of these to a new corporation or something. You +have been warned. + + We'd also like to thank Frank DiGennaro <fsd@server- +vault.com> for greatly contributing to this filter list. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/examples/ipfilter/ipf.conf.permissive b/share/examples/ipfilter/ipf.conf.permissive new file mode 100644 index 0000000..714d7d9 --- /dev/null +++ b/share/examples/ipfilter/ipf.conf.permissive @@ -0,0 +1,30 @@ +# $FreeBSD$ +# augmented rules generated by mkfilters +block in log quick from any with ipopts +block in log quick proto tcp from any to any with short +block in log quick all with opt lsrr +block in log quick all with opt ssrr +#------------------------------------------------------- +# loopback pakets left unmolested +pass in quick on lo0 all +pass out quick on lo0 all +#------------------------------------------------------- +pass out on ed1 all head 150 +block out from 127.0.0.0/8 to any group 150 +block out from any to 127.0.0.0/8 group 150 +block out from any to 192.168.1.110/32 group 150 +#------------------------------------------------------- +pass in on ed1 all head 100 +block in from 127.0.0.0/8 to any group 100 +block in from 192.168.1.110/32 to any group 100 +block in from 192.168.0.1/24 to any group 100 +#------------------------------------------------------- +pass out on fxp0 all head 250 +block out from 127.0.0.0/8 to any group 250 +block out from any to 127.0.0.0/8 group 250 +block out from any to 192.168.0.1/32 group 250 +#------------------------------------------------------- +pass in on fxp0 all head 200 +block in from 127.0.0.0/8 to any group 200 +block in from 192.168.0.1/32 to any group 200 +block in from 192.168.1.110/24 to any group 200 diff --git a/share/examples/ipfilter/ipf.conf.restrictive b/share/examples/ipfilter/ipf.conf.restrictive new file mode 100644 index 0000000..ad3de82 --- /dev/null +++ b/share/examples/ipfilter/ipf.conf.restrictive @@ -0,0 +1,77 @@ +# $FreeBSD$ +#-------------------------------------------------------------------------- +# ed1 - external interface +# fxp0 - internal interface +#-------------------------------------------------------------------------- +# First, nasty packets which we don't want near us at all +# packets which are too short to be real except echo replies on lo0 +pass in log quick on lo0 proto icmp from 127.0.0.1/8 to 127.0.0.1/8 with short +block in log quick all with short +block in log quick all with opt lsrr +block in log quick all with opt ssrr +#-------------------------------------------------------------------------- +# loopback packets left unmolested +pass in log quick on lo0 all +pass out log quick on lo0 all +#-------------------------------------------------------------------------- +# Group setup: +# 100 incoming ed1 +# 150 outgoing ed1 +# 200 incoming fxp0 +# 250 outgoing fxp0 +#-------------------------------------------------------------------------- +block in log body on ed1 all head 100 +block out log body on ed1 all head 150 +#-------------------------------------------------------------------------- +block in log on fxp0 all head 200 +block out log on fxp0 all head 250 +#-------------------------------------------------------------------------- +# incoming ed1 traffic - group 100 +# 1) prevent localhost spoofing +block in log quick from 127.0.0.1/32 to 192.168.0.0/24 group 100 +block in log quick from 127.0.0.1/32 to 192.168.1.0/24 group 100 +block in log quick from any to 127.0.0.1/8 group 100 +#-------------------------------------------------------------------------- +# 2) deny pakets which should not be seen on th internet (paranoid) +block in log quick from 10.0.0.0/8 to any group 100 +block in log quick from any to 10.0.0.0/8 group 100 +block in log quick from 172.16.0.0/16 to any group 100 +block in log quick from any to 172.16.0.0/16 group 100 +block in log quick from 192.168.0.0/16 to any group 100 +block in log from any to 192.168.0.0/16 group 100 +# 3) implement policy +# allow incoming ftp-data +pass in log quick proto tcp/udp from any to 192.168.1.1/24 keep state group 100 +# if nothing applies, block and return icmp-replies (unreachable and rst) +block return-icmp(net-unr) in proto udp from any to any group 100 +block return-rst in log proto tcp from any to any group 100 +#-------------------------------------------------------------------------- +# outgoing ed1 traffic - group 150 +# Setup outgoing DNS +pass out log quick proto tcp/udp from any to 212.40.0.10 port = 53 keep state group 150 +pass out log quick proto tcp/udp from any to 212.40.5.50 port = 53 keep state group 150 +# allow outgoing http-service +pass out log quick proto tcp from any to any port = 80 flags S/SA keep state keep frags group 150 +# allow outgoing smtp traffic +pass out log quick proto tcp from 192.168.1.1/24 to any port = 25 flags S/SA keep state group 150 +# allow outgoing pop3 traffic +pass out log quick proto tcp from 192.168.1.1/24 to any port = 110 flags S/SA keep state group 150 +# allow outgoing ftp traffic +pass out log quick proto tcp/udp from 192.168.1.1/24 to any port = ftp keep state group 150 +pass out log quick proto icmp from any to any keep state keep frags group 150 +#-------------------------------------------------------------------------- +# incoming traffic on fxp0 - group 200 +#-------------------------------------------------------------------------- +# 1) prevent localhost spoofing +block in log quick from 127.0.0.0/8 to any group 200 +block in log quick from 192.168.0.1/32 to any group 200 +block in log quick from 192.168.1.110/24 to any group 200 +pass in log quick from any to any group 200 +#-------------------------------------------------------------------------- +# outgoing traffic on fxp0 - group 250 +#-------------------------------------------------------------------------- +block out log quick from 127.0.0.0/8 to any group 250 +block out quick from any to 127.0.0.0/8 group 250 +block out log quick from any to 192.168.0.1/32 group 250 +pass out log quick from any to nay group 250 +#-------------------------------------------------------------------------- diff --git a/share/examples/ipfilter/ipf.conf.sample b/share/examples/ipfilter/ipf.conf.sample new file mode 100644 index 0000000..c5d47bc --- /dev/null +++ b/share/examples/ipfilter/ipf.conf.sample @@ -0,0 +1,19 @@ +# $FreeBSD$ +block in log quick from any with ipopts +block in log quick proto tcp from any to any with short +pass out on ed1 all head 150 +block out from 127.0.0.0/8 to any group 150 +block out from any to 127.0.0.0/8 group 150 +block out from any to 192.168.1.110/32 group 150 +pass in on ed1 all head 100 +block in from 127.0.0.0/8 to any group 100 +block in from 192.168.1.110/32 to any group 100 +block in from 192.168.0.1/0xffffff00 to any group 100 +pass out on fxp0 all head 250 +block out from 127.0.0.0/8 to any group 250 +block out from any to 127.0.0.0/8 group 250 +block out from any to 192.168.0.1/32 group 250 +pass in on fxp0 all head 200 +block in from 127.0.0.0/8 to any group 200 +block in from 192.168.0.1 to any group 200 +block in from 192.168.1.110/0xffffff00 to any group 200 diff --git a/share/examples/ipfilter/ipnat.conf.sample b/share/examples/ipfilter/ipnat.conf.sample new file mode 100644 index 0000000..67956bc --- /dev/null +++ b/share/examples/ipfilter/ipnat.conf.sample @@ -0,0 +1,3 @@ +# $FreeBSD$ +map ed1 192.168.0.0/24 -> 192.168.1.110/32 portmap tcp/udp 40000:65000 +map ed1 192.168.0.0/24 -> 192.168.1.110/32 diff --git a/share/examples/ipfilter/rules.txt b/share/examples/ipfilter/rules.txt new file mode 100644 index 0000000..26a51d0 --- /dev/null +++ b/share/examples/ipfilter/rules.txt @@ -0,0 +1,182 @@ +# $FreeBSD$ +# +# block all incoming TCP packets on le0 from host "foo" to any destination. +# +block in on le0 proto tcp from foo/32 to any + + ------------------------------------------------------------------------ + +# +# block all outgoing TCP packets on le0 from any host to port 23 of host bar. +# +block out on le0 proto tcp from any to bar/32 port != 23 + + ------------------------------------------------------------------------ + +# +# block all inbound packets. +# +block in from any to any +# +# pass through packets to and from localhost. +# +pass in from 127.0.0.1/32 to 127.0.0.1/32 +# +# allow a variety of individual hosts to send any type of IP packet to any +# other host. +# +pass in from 10.1.3.1 to any +pass in from 10.1.3.2 to any +pass in from 10.1.3.3 to any +pass in from 10.1.3.4 to any +pass in from 10.1.3.5 to any +pass in from 10.1.0.13/32 to any +pass in from 10.1.1.1/32 to any +pass in from 10.1.2.1/32 to any +# +# +# block all outbound packets. +# +block out from any to any +# +# allow any packets destined for localhost out. +# +pass out from any to 127.0.0.1/32 +# +# allow any host to send any IP packet out to a limited number of hosts. +# +pass out from any to 10.1.3.1/32 +pass out from any to 10.1.3.2/32 +pass out from any to 10.1.3.3/32 +pass out from any to 10.1.3.4/32 +pass out from any to 10.1.3.5/32 +pass out from any to 10.1.0.13/32 +pass out from any to 10.1.1.1/32 +pass out from any to 10.1.2.1/32 + + ------------------------------------------------------------------------ + +# +# block all ICMP packets. +# +block in proto icmp from any to any + + ------------------------------------------------------------------------ + +# +# test ruleset +# +# allow packets coming from foo to bar through. +# +pass from foo to bar +# +# allow any TCP packets from the same subnet as foo is on through to host +# 10.1.1.2 if they are destined for port 6667. +# +pass proto tcp from fubar/24 to 10.1.1.2/32 port = 6667 +# +# allow in UDP packets which are NOT from port 53 and are destined for +# localhost +# +pass proto udp from fubar port != 53 to localhost +# +# block all ICMP unreachables. +# +block from any to any icmp unreach +# +# allow packets through which have a non-standard IP header length (ie there +# are IP options such as source-routing present). +# +pass from any to any with ipopts + + ------------------------------------------------------------------------ + +# +# block all TCP packets with only the SYN flag set (this is the first +# packet sent to establish a connection). +# +block in proto tcp from any to any flags S/SA + + ------------------------------------------------------------------------ + +# +# log all inbound packet on le0 which has IP options present +# +log in on le0 from any to any with ipopts +# +# block any inbound packets on le0 which are fragmented and "too short" to +# do any meaningful comparison on. This actually only applies to TCP +# packets which can be missing the flags/ports (depending on which part +# of the fragment you see). +# +block in log quick on le0 from any to any with short frag +# +# log all inbound TCP packets with the SYN flag (only) set +# (NOTE: if it were an inbound TCP packet with the SYN flag set and it +# had IP options present, this rule and the above would cause it +# to be logged twice). +# +log in on le0 proto tcp from any to any flags S/SA +# +# block and log any inbound ICMP unreachables +# +block in log on le0 proto icmp from any to any icmp-type unreach +# +# block and log any inbound UDP packets on le0 which are going to port 2049 +# (the NFS port). +# +block in log on le0 proto udp from any to any port = 2049 +# +# quickly allow any packets to/from a particular pair of hosts +# +pass in quick from any to 10.1.3.2/32 +pass in quick from any to 10.1.0.13/32 +pass in quick from 10.1.3.2/32 to any +pass in quick from 10.1.0.13/32 to any +# +# block (and stop matching) any packet with IP options present. +# +block in quick on le0 from any to any with ipopts +# +# allow any packet through +# +pass in from any to any +# +# block any inbound UDP packets destined for these subnets. +# +block in on le0 proto udp from any to 10.1.3.0/24 +block in on le0 proto udp from any to 10.1.1.0/24 +block in on le0 proto udp from any to 10.1.2.0/24 +# +# block any inbound TCP packets with only the SYN flag set that are +# destined for these subnets. +# +block in on le0 proto tcp from any to 10.1.3.0/24 flags S/SA +block in on le0 proto tcp from any to 10.1.2.0/24 flags S/SA +block in on le0 proto tcp from any to 10.1.1.0/24 flags S/SA +# +# block any inbound ICMP packets destined for these subnets. +# +block in on le0 proto icmp from any to 10.1.3.0/24 +block in on le0 proto icmp from any to 10.1.1.0/24 +block in on le0 proto icmp from any to 10.1.2.0/24 +# +# Log all short TCP packets to qe3, with "packetlog" as the intended +# destination for the packet. +# +block in to qe3:packetlog proto tcp all with short +# +# Log all connection attempts for TCP +# +pass in dup-to le0:packetlog proto tcp all flags S/SA +# +# Route all UDP packets through transparently. +# +pass in fastroute proto udp all +# +# Route all ICMP packets to network 10 out through le1, to "router" +# +pass in to le1:router proto icmp all + + ------------------------------------------------------------------------ +Return to the IP Filter home page |