Wednesday, July 22, 2009

OpenBSD MAC Filtering using a Bridge and Packet Tagging

A need came up for MAC address filtering on one of the networks I manage. The only way I know of filtering on MAC address is through the use of a bridge and pf packet tagging. At first I thought I would have setup a transparent bridging firewall in front of the gateway firewall; however, through the use of an additional network card and a bridge to nowhere I was able to accomplish this task.

Here is the setup:

Gateway firewall with three network cards
bge0 (external interface)
bge1 (internal interface)
re0 (monitor interface)

Standard gateway setup
echo 'inet xxx.xxx.250.194 255.255.255.252 NONE' > /etc/hostname.bge0
echo 'inet xxx.xxx.3.254 255.255.255.0 NONE' > /etc/hostname.bge1
echo 'xxx.xxx.250.193 ' > /etc/mygate

Then configure a bridge between the internal interface and the monitor interface. Added the bridge options to change the default MAC address cache size from 100 to 300 and to automatically load the bridge rules from a file.
echo 'up' > /etc/hostname.re0
echo 'add bge1 add re0 maxaddr 300 rulefile /etc/brrules.conf up' > /etc/bridgename.bridge0

The bridge rule file serves only one purpose, to assign a certain tag to all packets from a list selected MAC addresses. An example of the file can be found below. The tag applied to the packet stays with it even after it leaves the bridge and passes onto PF. This allows you to filter on it using PF. The tag is only internal to the system and won't travel over the wire. When using tagging on a bridge only the interface that is connected on layer 2 to the MAC address you want to tag can assign it.

Then you can simply use the tagged keyword in your egress pf rules to filter out the non-authorized traffic. Please note that you will have to create special rules for the IPs of the firewall so that it can get out.

# DNS out
pass out quick log on $ext_if proto { tcp udp } to any port { 53 } tagged goodmac label "dns out" queue std_bis

# Firewall DNS Out
pass out quick log on $ext_if proto { tcp udp } from $fw to any port { 53 } label "dns fw" queue std_bis

For services that require redirect rules (FTP and Squid) you will need to place the tagged keyword before the redirect assignment.

# FTP Redirect
rdr on $int_if proto tcp from $intnwk to any port 21 tagged goodmac -> 127.0.0.1 port 8021

# Squid Redirect
rdr on $int_if proto tcp from $squidies to any port { 80 8080 } tagged goodmac -> 127.0.0.1 port 3128

Below are some helpful brconfig commands for managing the bridge. I had to manually start the bridge the first time after initial setup but not so after numerous reboots.


I know this won't prevent someone from spoofing a MAC address but it will prevent the standard user from casually assigning a static IP on a non authorized system. If anything now I have a nice monitor port on the firewall for when the IT auditor shows up.

Load Rules File
$ sudo brconfig bridge0 rulefile /etc/brrules.conf

Flush Rules
$ sudo brconfig bridge0 flushrule bge1

View Loaded Rules
$ sudo brconfig bridge0 rules bge1

Add a New MAC into the Rules
$ sudo brconfig bridge0 rule pass in on bge1 src 00:13:72:3b:fc:f8 tag goodmac

Example of a Bridge Rule File
pass in on bge1 src 00:12:3f:76:96:dd tag goodmac
pass in on bge1 src 00:1e:2a:c2:ae:95 tag goodmac
pass in on bge1 src 00:19:d1:e5:af:f9 tag goodmac

Contents of /etc/bridgename.bridge0
add bge1 add re0 maxaddr 300 rulefile /etc/brrules.conf up

Display the Addresses Learned by the Bridge
$ sudo brconfig bridge0 addr

Manually Start the Bridge
$ sudo brconfig bridge0 up

Example of PF Rule Utilizing Tagging
pass out quick log on $ext_if proto tcp to any port 80 tagged goodmac label "Web Traffic"

PF: Packet Tagging
http://www.openbsd.org/faq/pf/tagging.html

brconfig
http://www.openbsd.org/cgi-bin/man.cgi?query=brconfig&sektion=8

No comments: