![]() |
July 2002 | BSD Newsletter | Get BSD | Contact Us | Search BSD | FAQ | New to BSD? |
|
In today's world of broadband Internet technologies such as cable and DSL, IP addresses are often assigned in limited quantity by an ISP. Many of us would like a robust firewall to protect our network, but would rather not waste precious IP addresses. In this article we are going to build a robust, stateful packet filter that uses no IP addresses. Thankfully, OpenBSD provides built-in support for this "invisible firewall" via the bridge interface and the new packet filter, pf.
Let's assume that we currently have cable internet access from an ISP that has provided us with a small number of IP addresses. Because we need all of the addresses for a few workstations and servers, our network is unprotected at this point, with CAT5 cabling running directly from our cable modem to the hub where the workstations and server are connected.
The following diagram (thanks Marek!) shows the inclusion of a regular PC running OpenBSD (our "invisible firewall") that has been inserted inline between the cable modem and the hub.
The finished network topology will look like the diagram below.
The minimum requirements for the OpenBSD machine are as follows:
This article assumes that the user is familiar with installing OpenBSD. Please see the OpenBSD website for questions regarding installation or upgrading. A default OpenBSD 3.0 or higher install with the GENERIC kernel will support the bridge/pf configuration.
Once the OpenBSD installation is finished, remove any IP address information that you may have configured during the install. OpenBSD's bridging support is highly evolved: while the bridge operates solely at Layer 2, Layers 3 and 4 can still be filtered and manipulated while in transit through the bridge interfaces by pf.
For more specific information on OpenBSD bridging, please see the man page for bridge.
First, we need to enable ip forwarding between the two network interfaces. Edit /etc/sysctl.conf and uncomment the line that reads: net.inet.ip.forwarding=1
Assuming the 2 bridge interfaces are fxp0 and fxp1 (if your interface names are different, change the interface names accordingly), create the following files with these parameters:
# ifconfig fxp0 delete # echo 'up' > /etc/hostname.fxp0 # ifconfig fxp1 delete # echo 'up' > /etc/hostname.fxp1 # echo 'add fxp0 add fxp1 up' > /etc/bridgename.bridge0Reboot and verify that the bridge is up by running ifconfig -a. You should see output that includes this entry:
bridge0: flags=41 <UP,RUNNING> mtu 1500Your bridge is now up and running and we can begin to configure the ruleset for pf.
pf (Packet Filter) is the packet filtering system in OpenBSD 3.0 and later. Its syntax and functionality are very similar to ipf in both FreeBSD, NetBSD, and earlier versions of OpenBSD. If you are familiar with ipf ruleset syntax, pf syntax should be readable.
In /etc/rc.conf, pf is disabled by default. Use pf=YES to enable. (pf will not actually be enabled until you reboot the machine once again.)
Because this is a home network, our ruleset will reflect functionality for a mixed Unix and Windows environment.
Our example filtering requirements:
######################################################################### # OpenBSD bridged packet filter /etc/pf.conf example # # Some changes will likely be required for your specific setup! #### Interface aliases # Interface aliases should be created for ease of administration. ext_if = "fxp0" # Untrusted (from cable modem) side int_if = "fxp1" # Trusted (to hub/switch) side #### External Bridge interface rules (allow all in - filter on internal) # In bridge mode, we only filter on one interface. pass in quick on $ext_if all pass out quick on $ext_if all #### Internal Bridge interface rules (main ruleset) # Rule order does not matter # Block (Deny) and LOG everything IN by default block in log on $int_if all ### IN RULES # Allowed incoming tcp services (ssh, https) pass in on $int_if proto tcp from any to any port \ { ssh, https } \ keep state # Allow http traffic to our webserver pass in on $int_if proto tcp from any to 1.2.3.4 port = http keep state # Allow MS RDP (TCP 3389) from work to win2k server pass in on $int_if proto tcp from 2.2.3.4 to 1.2.3.5 port = 3389 keep state # Allow Certain UDP services IN (DNS, NTP) pass in on $int_if proto udp from any to any port \ { domain, ntp } \ keep state # Allow ICMP (ping) IN # pass out/in certain ICMP queries and keep state (ping) pass in on $int_if inet proto icmp all icmp-type 8 code 0 keep state ### END of IN RULES ### OUT RULES # Allow ICMP (ping) OUT pass out on $int_if inet proto icmp all icmp-type 8 code 0 keep state # Pass (Allow) all UDP/TCP OUT and keep state pass out on $int_if proto udp all keep state pass out on $int_if proto tcp all modulate state ### END of OUT RULES ########################################################################More information and ruleset examples can be found in the pf.conf man page.
The pfctl command controls the loading and viewing of the rules, as well as a number of other rule-related items (e.g., viewing state tables).
The example /etc/pf.conf is loaded like this:
# pfctl -R /etc/pf.confTo view the loaded rules:
# pfctl -s rules
Because we added a log parameter to the block rule in the above example, we can use tcpdump to view traffic on the pf log interface (pflog0) in real time to see the traffic that is being dropped.
To view pf logged traffic in real time:
# tcpdump -i pflog0Real-time logging will be shown, which can be extremely helpful in ruleset configuration or any problems that may occur.
One other helpful troubleshooting test that you can run with tcpdump will read the pf logfile (/var/log/pflog) and show you accepted and rejected packets along with a matching rule number.
# tcpdump -n -e -ttt -r /var/log/pflogThese methods will prove invaluable as you develop more complex rulesets and enable more sophisticated logging.
That's it. We now have an "invisible firewall" capable of stateful packet inspection and advanced capabilities without using any of our precious IP addresses. From a security standpoint this is nearly the perfect firewall solution because of its stealth. It cannot be compromised over the network, cannot be portscanned and doesn't waste IP space. To someone on the outside of your network, denied packets simply mysteriously "disappear" for no apparent reason.
There are many other uses for this kind of invisible or stealth packet filtering, from segmenting flat corporate networks to building a portable invisible traffic monitoring device. You might even add another NIC to it and create an addressed interface that plugs into a secure management VLAN for ease of administration... the possibilities are vast.
I hope this article has been helpful, and I hope that you will find a myriad of ways to incorporate this solution into your particular networking environment.