A transparent firewall is a firewall running at Layer 2 in the OSI layer, that is Data link layer. Its main feature is that an attacker, usually remote, can’t actually see it. At Layer 2 we have MAC addresses offering local addressing, and we don’t have IP addresses. If you think that this has no point whatsoever, think again [1].
So, after reading this I’ve searched for a software solution. I was mainly motivated by [2] and [3]. A similar solution is presented at [4] for OpenBSD. I will describe a working solution for NetBSD in more detail, in a bottom up fashion, to reduce the need of googleing.
A transparent firewall is mainly a Layer 2 device with added filtering capabilities. Since firewalls usually need at least two physical interfaces, the logical choice is a bridge. It turns out that OpenBSD and NetBSD support building such a transparent firewall. Very good documentation is provided at [5].
First of all, a small introduction to Netbsd and OpenBSD.
Although many of you appreciate the openness and novelty of systems based on GNU/Linux, I recommend taking a look at NetBSD and OpenBSD.
OpenBSD started as a fork of NetBSD, and it is advertised in the community as being the most secure Operating System. Although I disagree with this kind of assertions, I can tell you that it is rather difficult to do stupid things on it.
NetBSD is advertised as the most portable OS. And it actually is.
For those of you who want to experiment on a Dell Inspiron 1525 laptop, surprises await you. NetBSD does not offer out-of-box support for the Marvell Ethernet controller, while OpenBSD does. Neither of the two offer any support for Broadcom BCM4312 802.11b/g wireless network controller, if you were wondering.
Therefore, the best solution for a transparent firewall that I could think of was an ancient AMD Duron based computer. The computer has two PCI based Gigabit Ethernet NICs: RealTek 8169/8110 Gigabit Ethernet (rev. 0×10) and D-Link DGE-528T Gigabit Ethernet (rev. 0×10), and an on-board VIA VT6102 (Rhine II) 10/100 Ethernet.
For those of you who think that a dual-core or quad-core computer would be blazing fast running this OSes, I tell you … support for SMP was just recently added and has much to catch up to match the Linux Kernel. At the same time, a 200 MB and 27 user processes OS is quite tempting for those experimenting with XEN virtualization.
What I really enjoy in the case of OpenBSD and NetBSD is the kernel source code documentation and the style of writing the code. Please, don’t thrust me. Just download and look at it. You would gain a better understanding of the Linux kernel by doing so.
To decline my preferences, I commonly use and enjoy Ubuntu and Fedora. But I also started to enjoy and appreciate BSD based system.
I also tried OpenSolaris. I have never encountered such an awful OS in my entire life. Its just a very big piece of crap. I don’t care what others say about its commercial brother, the so-called “most advanced OS”. The correct way of presenting it is: “the crappiest OS that mankind has ever witnessed”.
Ok, returning to our discussion one thing that would annoy any living being regarding NetBSD and OpenBSD is the lack of applications. There are less applications than on GNU/Linux and usually they are outdated. Yes, of course there is a reason for this. A funny thing is that tcpdump is not present in the ports tree. The main argument being the high number of bugs that could threaten the security of the system.
So lets start building a transparent firewall using NetBSD.
Install NetBSD, currently at version 5.0.2
Download it from: http://www.netbsd.org/releases/.
Accept default settings.
Building a custom made NetBSD kernel [6]
1) Copy the GENERIC kernel config to your local directory:
-
cp /usr/src/sys/arch/`machine`/conf/GENERIC ~/TranspareFIREWALL
And make a symbolic link to it:
-
ln -s ~/TranspareFIREWALL /usr/src/sys/arch/`machine`/conf/TransparentFirewall
Now in our custom kernel config add / modify the networking options to look as following :
-
# Networking options
-
options GATEWAY # packet forwarding
-
options INET # IP + ICMP + TCP + UDP
-
options INET6 # IPV6
-
options IPSEC # IP security
-
options IPSEC_ESP # IP security (encryption part; define w/IPSEC)
-
options IPSEC_NAT_T # IPsec NAT traversal (NAT-T)
-
options IPSEC_DEBUG # debug for IP security
-
options MROUTING # IP multicast routing
-
#options PIM # Protocol Independent Multicast
-
#options ISO,TPIP # OSI
-
#options EON # OSI tunneling over IP
-
options NETATALK # AppleTalk networking protocols
-
options PPP_BSDCOMP # BSD-Compress compression support for PPP
-
options PPP_DEFLATE # Deflate compression support for PPP
-
options PPP_FILTER # Active filter support for PPP (requires bpf)
-
options PFIL_HOOKS # pfil(9) packet filter hooks
-
options IPFILTER_LOG # ipmon(8) log support
-
options IPFILTER_LOOKUP # ippool(8) support
-
options IPFILTER_DEFAULT_BLOCK # block all packets by default
-
#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG
-
options ICMP_BANDLIM
-
options ALTQ # Manipulate network interfaces' output queues
-
options ALTQ_BLUE # Stochastic Fair Blue
-
options ALTQ_CBQ # Class-Based Queueing
-
options ALTQ_CDNR # Diffserv Traffic Conditioner
-
options ALTQ_FIFOQ # First-In First-Out Queue
-
options ALTQ_FLOWVALVE # RED/flow-valve (red-penalty-box)
-
options ALTQ_HFSC # Hierarchical Fair Service Curve
-
options ALTQ_LOCALQ # Local queueing discipline
-
options ALTQ_PRIQ # Priority Queueing
-
options ALTQ_RED # Random Early Detection
-
options ALTQ_RIO # RED with IN/OUT
-
options ALTQ_WFQ # Weighted Fair Queueing
Enable this if they aren’t by default:
-
pseudo-device bpfilter # Berkeley packet filter
-
pseudo-device pf # PF packet filter
-
pseudo-device pflog # PF log if
Increase the memory available in kernel to a value specific to your available memory. The memory available to the firewall, among others, depends on it.
-
options NMBCLUSTERS=16384
Then build the kernel:
-
cd /usr/src/sys/arch/`machine`/conf/
-
config ./TransparentFirewall
-
cd ../compile/TransparentFirewall/
-
make depend && make
Save the old kernel and copy the new one:
-
cp /netbsd /netbsd.original
-
cp /usr/src/sys/arch/`machine`/compile/MYKERNEL/netbsd /netbsd
and do a simple reboot.
If you encounter problems, read the available documentation.
Mainly, you can return to the original kernel using, at boot, the following commands:
-
boot netbsd.original -s
-
fsck /
-
mount /
-
mv netbsd.old netbsd
-
reboot
Now that you have a working kernel supporting the pf firewall and traffic shaping (ALQ options specified), you can start configuring the transparent firewall. Basically, as the documentation says, you can achieve this by setting up bridge between two physical NIC and filtering packets on one of them, using pf.
It is possible to set one of the interfaces to have an IP address for administrative purposes (static / dhcp) or use another network interface. The later strategy was adopted.
The re0 and re1 (Realtek driver naming) will denote the two bridge interfaces while sis0 will be the administrative interface. For each of these interfaces create a file such as the ones below:
-
#vi /etc/ifconfig.re0
-
up
-
#vi /etc/ifconfig.re1
-
up
and the configuration interface:
-
#vi /etc/ifconfig.sis0
-
up
-
dhcp
To configure the bridge to use cycle detection (STP) and packet filtering:
-
#vi /etc/ifconfig.bridge0
-
create
-
!brconfig bridge0 add re1 add re0 up stp re1
Now you have to set up the /etc/rc.conf. A sample configuration file is:
-
rc_configured=YES
-
dhclient="YES" #<- comment if you don't need DHCP for the configuration interface
-
sshd="YES"
-
hostname=mycomputer.mynetwork
-
firewall_enable="YES"
-
pf=YES #enable pf
-
pf_rules=/etc/pf.conf #pf configuration file
-
pf_program="/sbin/pfctl"
-
pf_flags=""
-
pflogd=YES
-
inetd=NO
-
syslogd=YES
-
pflog_enable="YES" #log network packets, similar to ulog on GNU/Linux
-
pflog_logfile="/var/log/pflog" #log file location
-
pflog_program="/sbin/pflogd"
-
pflog_flags=""
and … reboot. You’ve just built a bridge using NetBSD.
The last thing you have to do is to set the firewall rules. Please note that despite the fact that we have built a bridge, Layer 2 device, we have access to the whole packet information. This has to do with the way the bridge code uses the BPF interface to copy packets from one interface to the other.
The main feature that distinguishes PF from iptables is the fact that rules that don’t employ the “quick” keyword are not definitive. In iptables, the action taken by the firewall is given by the first matching rule. In PF the action is given by the last matching rule or a rule having the “quick” keyword.
Therefore
-
#vi /etc/pf.conf
-
block in all
-
pass in inet proto tcp from any to any port ssh
will allow just ssh session to be established, while
-
#vi /etc/pf.conf
-
pass in inet proto tcp from any to any port ssh
-
block in all
will block any packets from entering the local network.
A feature similar to the one provided by ulog is given by:
-
#vi /etc/pf.conf
-
block in log (all to pflog0) all
-
block out log (all to pflog0) all
which will block all the packets and log them to pflog0. The packets could be later retrieved from the pflog0 interface using tcpdump or from /var/log/pflog (as specified in rc.conf).
Another awesome feature is that this interface is clonable. That is if we create a file with the content:
-
#vi /etc/pflog1
-
up
a new (cloned) logging interface is created. NetBSD supports many such interfaces. We can then specify firewall rules that send packets to different logs.
-
#vi /etc/pf.conf
-
block in log (all to pflog0) all
-
block out log (all to pflog1) all
Thats it folks ! I will write a more advanced firewall configuration in a next post.