Computerglitch

An ongoing adventure

Transparent Firewall With OpenBSD VM

I had a job where I needed to place a firewall in front of a network of publicly accessible computers. I decided to use a virtual transparent firewall to protect the entire network and make no changes on the client computers. This is document describes how I did it.

First the hardware: I decided to use a Dell Poweredge 1900 with ESXi server. The server has (2) Quad Core Processors, 16GB of RAM and 3 NICs. The storage is local with 4 drives set in a RAID 5 providing 600GB of storage.

Now for the NIC setup. You can see from the below diagram the BSD Bridge is setup on vmnic0 and vmnic1, vmnic2 is reserved for management and other VM’s.

One VERY IMPORTANT note before I begin to explain the setup of the OpenBSD VM, the two NICS that will be used for the transparent firewall must be setup in ESXi for promiscuous mode! See the image below.

Configure the OpenBSD VM with two NICS, both tied to the NICs configured in promiscuous mode. Install OpenBSD on the VM.

For the configuration of OpenBSD do the following: Enable PF and IP forwarding (edit /etc/rc.conf and /etc/sysctl.conf)

Configure the bridge (substitute your NIC names in place of vic0 and vic1) First create the file /etc/bridgename.bridge0:

1
# touch /etc/bridgename.bridge0

Add the following to the bridgename.bridge0 file:

1
2
3
add vic0
add vic1
up

After you have added this file reboot the OpenBSD VM, when the system comes back up you should see the following when issuing ifconfig -a

1
2
bridge0: flags=41<UP,RUNNING> mtu 1500
groups: bridge

Once you have confirmed the bridge is running its time to configure pf to control the traffic. Here is an example /etc/pf.conf file that blocks all external traffic destined for the internal network and allows all internal traffic destined for the internet:

1
2
3
4
5
6
7
8
9
10
ext_if=vic0
int_if=vic1

#Allow all traffic out from our network (vic1)
pass out quick on $int_if all
pass in quick on $int_if all
pass out quick on $ext_if all

#Block all traffic on external interface (vic0) by default
block in log on $ext_if all

A more elaborate example allows SSH traffic from specific IP’s to the internal network and configures OpenDNS redirection for content filtering on the internal network:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ext_if=vic0
int_if=vic1

allowed_ips={ 68.180.206.184, 209.85.171.100 }
opendns={ 208.67.222.222, 208.67.220.220 }
internal_ips={ 206.46.232.39/27 }

#Redirect to OpenDNS for content filtering
rdr on $int_if inet proto udp from any to any port 53 -> $opendns

#Allow all traffic out from our network (vic1)
pass out quick on $int_if all
pass in quick on $int_if all
pass out quick on $ext_if all

#Block all traffic on external interface (vic0) by default
block in log on $ext_if all

#Inbound Allow Rules
pass in log quick on $ext_if proto tcp from $allowed_ips to $internal_ips port 22 modulate state

Here is a diagram of the hardware setup and wiring:

Comments