Building a Filtering Bridge With DragonFlyBSD

2
Building a filtering bridge with DragonFlyBSD A filtering bridge transparently filters packets in a network. This has its advantages and disadvantages. Disadvantages include: getting the bridge up (the handbook is outdated on this), active FTP, directions. I have spent many days getting my bridge up & running. Thought I would share the information with others in order to help avoiding the hassle I had to face Materials and Methods I used a dual PII/400 system with 2 Planet-ENW-9607 /sk(4)/ NICs and the machine was running DragonflyBSD 1.6.1. Setting up bridging To enable bridging and PF support on DragonFly you have two options: load the required kernel modules or compile them directly into the kernel. I chose the latter, because ALTQ support ha to be compiled into the kernel anyway in order to use traffic shaping (and I had to recompile for SMP as well :P). Here is my kernel config (only the parts that differ from GENERIC.): machine i386 cpu I686_CPU ident SMP # Bridging support pseudo-device bridge # ALTQ options ALTQ #alternate queueing options ALTQ_CBQ #class based queueing options ALTQ_RED #random early detection options ALTQ_RIO #triple red for diffserv (needs RED) options ALTQ_HFSC #hierarchical fair service curve options ALTQ_PRIQ #priority queue options ALTQ_NOPCC #don't use processor cycle counter options ALTQ_DEBUG #for debugging # PF device pf device pfsync device pflog # Symmetric Multiprocessing support options SMP # Symmetric MultiProcessor Kernel options APIC_IO # Symmetric (APIC) I/O After compiling, installing and rebooting I got bridging support. If you don't need/want to compile a kernel you can simply open (or create) * /boot/loader.conf* and add these lines: if_bridge_load="YES" pf_load="YES" pflog_load="YES" and if you don't want to reboot, you can load the modules realtime: # kldload pf.ko # kldload pflog.ko # kldload if_bridge.ko Well, we have bridging support now, we have to create an interface that represents the bridge and tell which NICs belong to it. Edit /etc/rc.conf and include: # Replace x.x.x.x with the desired IP. ifconfig_sk0="inet x.x.x.x netmask 255.255.255.0" ifconfig_sk1="up" cloned_interfaces="bridge0" ifconfig_bridge0="addm sk0 addm sk1 up" pf_enable="YES" pflog_enable="YES" There is no need to have IPs in a bridge, but it is generally a good idea to have one interface with an IP address assigned, and if we would like to do filtering, it is necessary (well, for me at least. :P) It is also good because you can SSH into the machine or run it as a DHCP server, caching DNS server etc. as well (I run dhcpd on it, but won't cover that now, there are many great howto's out there). That's it, we have a running bridge with PF. Now let's go and configure filtering!

description

Building a Filtering Bridge With DragonFlyBSD

Transcript of Building a Filtering Bridge With DragonFlyBSD

Page 1: Building a Filtering Bridge With DragonFlyBSD

Building a filtering bridge with DragonFlyBSD

A filtering bridge transparently filters packets in a network. This has its advantages and disadvantages.

Disadvantages include: getting the bridge up (the handbook is outdated on this), active FTP, directions.

I have spent many days getting my bridge up & running. Thought I would share the information with

others in order to help avoiding the hassle I had to face

Materials and Methods

I used a dual PII/400 system with 2 Planet-ENW-9607 /sk(4)/ NICs and the machine was running

DragonflyBSD 1.6.1.

Setting up bridging

To enable bridging and PF support on DragonFly you have two options: load the required kernel

modules or compile them directly into the kernel. I chose the latter, because ALTQ support ha to be

compiled into the kernel anyway in order to use traffic shaping (and I had to recompile for SMP as well

:P). Here is my kernel config (only the parts that differ from GENERIC.):

machine i386

cpu I686_CPU

ident SMP

# Bridging support

pseudo-device bridge

# ALTQ

options ALTQ #alternate queueing

options ALTQ_CBQ #class based queueing

options ALTQ_RED #random early detection

options ALTQ_RIO #triple red for diffserv (needs RED)

options ALTQ_HFSC #hierarchical fair service curve

options ALTQ_PRIQ #priority queue

options ALTQ_NOPCC #don't use processor cycle counter

options ALTQ_DEBUG #for debugging

# PF

device pf

device pfsync

device pflog

# Symmetric Multiprocessing support

options SMP # Symmetric MultiProcessor Kernel

options APIC_IO # Symmetric (APIC) I/O

After compiling, installing and rebooting I got bridging support. If you don't need/want to compile a

kernel you can simply open (or create) * /boot/loader.conf* and add these lines:

if_bridge_load="YES"

pf_load="YES"

pflog_load="YES"

and if you don't want to reboot, you can load the modules realtime: # kldload pf.ko # kldload pflog.ko #

kldload if_bridge.ko Well, we have bridging support now, we have to create an interface that represents

the bridge and tell which NICs belong to it.

Edit /etc/rc.conf and include: # Replace x.x.x.x with the desired IP. ifconfig_sk0="inet x.x.x.x netmask

255.255.255.0" ifconfig_sk1="up" cloned_interfaces="bridge0" ifconfig_bridge0="addm sk0 addm sk1

up" pf_enable="YES" pflog_enable="YES" There is no need to have IPs in a bridge, but it is generally

a good idea to have one interface with an IP address assigned, and if we would like to do filtering, it is

necessary (well, for me at least. :P) It is also good because you can SSH into the machine or run it as a

DHCP server, caching DNS server etc. as well (I run dhcpd on it, but won't cover that now, there are

many great howto's out there). That's it, we have a running bridge with PF. Now let's go and configure

filtering!

Page 2: Building a Filtering Bridge With DragonFlyBSD

Configuring the firewall

I will not cover every PF option under the sun, go figure yourself, the PF FAQ is great, although it

lacks some details that I will partially cover. I insist on readingg how lists, macros and filtering rules

work before reading on. Be aware of DragonFly's PF version being the same as OpenBSD 3.6's one!

First off, one needs to understand that a bridge is symmetrical from the aspect of traffic, hence it's a

good idea to filter on only one interface. In my practice, the interface having the IP usually resides

LAN-side, while the IPless one does on the WAN-side:

int_if=sk0

ext_if=sk1

On other interfaces we just pass everything:

pass quick on { $int_if, lo0, bridge0} all

OK, we do the usual filtering, all good, then we get the good ol' active FTP problem. Well, since we

have no new-wave ftp-proxy in the base system, nor does ftpsesame work on DragonFly, we'll have to

stick with the ftp-proxy that comes with inetd. We enable it in /etc/inetd.conf (uncommenting the last

line in the default config):

ftp-proxy stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy

and (re)start inetd:

# rcrestart inetd

It will listen on any interfaces by default, so you may want to limit access to port 8021 in PF. Now we

set up PF to forward FTP traffic from the LAN to the ftp-proxy. On a router, this can be done with a

simple traffic redirection - we redirect traffic from the external interface to the internal interface (even

ftp-proxy needs an IP to listen on :-P):

# ftp-proxy S01E01

# Do you remember? ($int_if) always gives you the IP of that inerface, you can use

it like (rl0) as well.

rdr on $ext_if inet proto tcp from to any port ftp -> ($int_if) port 8021 but given that the bridge

operates in Layer 2, we just have rewritten this packet, nothing more, it will leave the bridge and

disappear ( rdr * directives never work on a bridge!*). However, we can actually route it to another

interface, and since the packet has just been changed to be destined to hit the IP of that interface, we

have successfully done a forwarding, on a bridge it requires these two steps, though. We use the route-

to keyword for this (and if you can NOT find anything about it in the PF FAQ, then you are right, there

are a few words on it in the pf.conf(5) manpage, though):

# ftp-proxy S01E02

pass in log quick on $ext_if route-to ( lo0 127.0.0.1 ) proto tcp from <intnet> to

($int_if) port 8021

We actually route it to the loopback interface, I am unsure why it has to be done this way. (FIXME)

Well, all we have to do now to allow FTPDATA connections from port 20 of the ftpserver to our

machine's IP. This can easily be achieved as ftp-proxy has a dedicated user called proxy, and we have

uid/gid filtering in pf (another poorly documented feature):

# ftp-proxy S01E03 a. k. a. season finale

pass in log quick on $ext_if inet proto tcp from port 20 to ($int_if) user proxy

keep state

and we will have working active FTP behind our bridge.