|
Setting up an OpenBSD firewall
Introduction to this web pageMy two Red Hat 9 based Linux firewalls have provided excellent service - one of them has worked faultlessly for over two years now, the other one has worked faultlessly since it was built several months ago. However time moves on, and the kernel they use, which is version 2.4.20, is now old hat, and anyway, even with the recompiling I did, it has a bug that affects the state table used by packet forwarding. So it was time to think about replacements - I thought about going with Red Hat Fedora which is based on kernel 2.6, however Red Hat Fedora is getting more and more bloated, so I finally went down the road of OpenBSD and pf - as far as using it as a firewall is concerned, OpenBSD has a distinct advantage over most other open source unix look-alikes - it is designed from the basement up with security as the primary design parameter.
So this web page is about setting up an OpenBSD firewall - in this case this is OpenBSD 3.8 on i386 architecture.
The function of the firewallThe two OpenBSD firewalls I have built are direct replacements for my previous Linux firewalls. In each case the firewall box has an external ethernet network interface which eventually connects to the open internet through a series of routers. Also, in each case the firewall box has an internal ethernet network interface connected to a secure subnet which hosts a small number of pc`s. The secure subnet uses one of the reserved ip network addresses, ie, 192.168.100.0/24. So the firewall box is doing Network Address Translation, as well as ip address based packet filtering and stateful packet filtering.
Installing OpenBSDThe first challenge was to install OpenBSD - if you think Linux is for geeks, try OpenBSD !! Installation is far from being intuitive. The easiest ( or least difficult ) way is to install from a cd, which is what I did. Here is the step by step process that worked for me, on an Intel 500 MHz P3 with two 10/100 Intel network cards. :- Insert cd, make sure the BIOS is set to boot from the cd Once the scrolling stops, you should have a prompt (I)nstall, (U)pgrade or (S)hell? Type I to select install, next prompt is Terminal type? [vt220] Accept the default by pressing "Return", next prompt is kbd(8) mapping? (`?` for list) [none] This is asking you what keyboard mapping you require - if you want a UK mapping, then enter "uk" and press "Return" If you want a mapping from a different country, enter "?", and choose the one you want. You now get a warning about data on the computer - you are about to wipe your hard drive ! Proceed with install? [no] The default is no, so type "y" to proceed, and the installation program then goes off and looks for your hard drive or drives. In my case, the hard drive type is called "wd", and they are numbered from 0 upwards. As I had only one hard drive, it is known as wd0. Press "Return" to accept wd0 Do you want to use *all* of wd0 for OpenBSD? [no] I guess this is self-explanatory, the following assumes that you type "y" to have the install program re-partition the whole hard drive. If you want to preserve some existing partitions, then type "n" and now you`re own your own ! Read the next bit of text carefully - you are going to have manually divide up your hard drive into several OpenBSD partitions using the OpenBSD label editor. Having typed "y", the prompt changes to a chevron, and you are now within the label editor. Typing "?" at the chevron prompt gives a list of commands. Type "p", to get a printout of the current hard drive configuration. At the bottom of the printout, you will see a number of lines that look roughly like a: 16498692 63 unused 0 0 c: 16514064 0 unused 0 0 In my case, a: is the existing single primary partition. In every case, c: is the hard drive itself - this is of course quite different from Microsoft Windows, where C: is always the active primary partition. We need to get rid of a:, so at the chevron prompt, type d a and now doing another printout, we now only have c: 16514064 0 unused 0 0 Don`t try to delete c: We can now start to add our OpenBSD partitions - and here a little arithmetic is required. To maximise the security of your Open BSD installation, the designers of OpenBSD advise that some parts of the directory structure should be given their own partitions. I set up the following partitions and mount points :- a: / b: swap space d: /usr e: /var f: /tmp g: /home I think that by convention, a: is always set to the root directory. Partition b: is always swap space, the label editor is configured this way. Partition c: is always the whole hard drive, so don`t try to change it. We need to decide how large to make each partition - I started with a 10GB hard drive, so to make life easy, I just gave each partition 1GB, except the swap partition, which I made 250MB. So now back to our label editor - start by creating the a: partition - a a We get the response - offset: [63] This is asking you to specify the start point of the partition - just press "Return" to accept the start point it is offering. In my case, it responds with size: [16498692] We definitely do not want to accept the size it is offering, as it wants to use the whole free space on the hard drive. Fortunately we don`t have to think in terms of sectors, we can specify a size in Megabytes, so for a 1GB partition, we can type in size: [16498692] 1000M and it responds with Rounding to nearest cylinder: 2048193 FS type: [4.2BSD] So it has more or less accepted our size request. Then it asks us about the file system to go on this partition - press "Return" to accept the default. Now it is looking for a mount point :- mount point: [none] As we are setting up the partition for the root directory, we can respond with mount point: [none] / After pressing return, we are back to the chevron prompt, so that partition is setup, and we can start on the next one, which is b:, ie, the swap partition. The label editor responds differently when setting up the b: partition - the b: partition is always swap space a b After pressing "Return", we get the response offset: [2048256] Accept this by pressing "Return" again, and then enter the required size -
size: [14450499] 250M After pressing return, we get Rounding to nearest cylinder: 512064 FS type: [swap] After pressing "Return" again, we are back to our chevron prompt, and can do the next partition. So repeat the process that was used to create a:, in order to set up d:, e:, f:, and g:, with the mount point as shown above. Once this is done, entering "p" at the chevron prompt should give us the response a: 2048193 63 4.2BSD 2048 16384 16 # / b: 512064 2048256 swap c: 16514064 0 unused 0 0 d: 2048256 2560320 4.2BSD 2048 16384 16 # /usr e: 2048256 4608576 4.2BSD 2048 16384 16 # /usr f: 2048256 6656832 4.2BSD 2048 16384 16 # /usr g: 2048256 8705088 4.2BSD 2048 16384 16 # /usr We now need to save all this, so press "q" - we get the response Write new label?: [y] Press "Return" to confirm,and we get a whole new type of response Mount point for wd0d (size=1024128k)? (or `none` or `done`) [/usr] Pressing "Return" gives us another similar line, etc, for as long as you can be bothered pressing "Return". A better response is for us to type "done". We get a summary of what we have done, and a request for confirmation. Press "y" to confirm, then sit and watch it creating the partitions ! Now it looks for a system hostname, then asks to configure the network, which of course we do. After pressing "Return", it gives us a list of available interfaces. In my case, as I am using Intel network cards, it identifies these as "fxp0" and "fxp1". We might as well start with fxp0, since that is offered as the default. Again, in my case fxp0 is the network interface that will be connecting to the internet, so it gets configured with the ip address and subnet details of the subnet to which the box is attached. The questions that it requires answers to are fairly self-explanatory, so I shall not list them here. You can invent a symbolic host name for each interface, and you probably don`t need to change the media options. After doing fxp0. just repeat for fxp1. The default IPv4 route is the ip address of the gateway of the external subnet to which the box is connected. You probably don`t want to edit hosts with ed, and you shouldn`t need to do any manual network configuration. Let`s install the sets! Location of sets? (cd disk ftp http or `done`) [cd] This actually refers to the software you want installed. If you are using a cd, then just accept the default of cd, then accept the default of cd0 ( if you only have one cd player ), then accept the default path. You are now offered a list of software which can be installed - for a firewall, the default selection will do fine. It may be possible to set up a firewall with less software than the default selection, but I haven`t tried it yet. To accept the default, just enter "done" at the prompt. Then accept the default response of [yes], and the software gets installed. Once that is finished, we don`t want to install any more software, so accept the default of [done]. Start sshd(8) by default? [yes]
It is up to you if you want to run ssh by default, so make the appropriate response, and again for ntp. Do you expect to run the X Windows System? [yes] On a firewall, definitely no ! Accept the default for the default console. For the UK, the timezone setting is GMT. Follow the instructions to "halt" and then reboot, and you are finished.
Configuring OpenBSD for pfpf is the recognised abbreviation for Packet Filter - the system used in OpenBSD for filtering IP traffic and doing network address translation. Having installed the default configuration of OpenBSD, we now have to configure it so that pf works. There isn`t a lot to do, it only involves some small changes to some OpenBSD configuration files. We can use /bin/vi to do this. Start with /etc/rc.conf - look for a line about halfway down that says pf=NO # Packet Filter / NAT Change this to pf=YES # Packet Filter / NAT to enable pf at bootup time. Now scroll further down this file, to just before the bottom - look for a line pf_rules=/etc/pf.conf # Packet filter rules file This sets the default configuration file for pf, which you can change if you want. However whichever file is specified here is the one that needs to contain the ruleset for our firewall, which ruleset we still have to write. Now open up in vi the file /etc/sysctl.conf, and look for the fifth line of text - #net.inet.ip.forwarding=1 # 1=Permit forwarding (routing) of packets Remove the initial "#" at the start of the line, so the line becomes active. This enables packets to be forwarded between the two network interfaces. That completes the changes to the OpenBSD configuration files, now we need to look at writing the ruleset that will be saved into pf.conf, or whatever alternative you have chosen.
Configuring pf via its configuration fileJust for convenience, I am going to refer to the pf configuration file as pf.conf. But as said above, it doesn`t have to be pf.conf, it can have any filename you want, as long as you remember to put the file name into /etc/sysctl.conf There is an evil looking script in the default pf.conf file - I personally think it is easier to ignore it altogether - it includes tables, macros, nat, port forwarding, etc, with no explanations of any kind. Start from scratch with an empty file, and build up your own script that you understand. The pf.conf file should contain 7 sections - these are Macros Tables Options Scrub Queueing Translation Filter Rules It isn`t neccessary to use all 7 sections, but those that are used should be in the above order in the pf.conf script. Personally, I think that using macros and tables makes it more difficult to understand your script, and makes it much more difficult to match your human view of the configuration of pf with the kernel view. So currently I don`t use either. There is plenty of documentation available from the OpenBSD website on writing a pf.conf script, so I am not going to try to give instructions here. Instead, here is the script that I am using on one of my firewalls - the script is fully commented. This is still early days for me in understanding OpenBSD and pf, so my scripts will change as my understanding increases. However this is a basic working script, that provides ip address blocking, network address translation, and stateful packet filtering. It also allows a PPTP based VPN to work through the firewall, where it is the VPN client that is behind the firewall on the secure subnet. # This is pf configuration file # Version = pf-2-hm.conf # ------------------- # MACROS # TABLES # OPTIONS # SCRUB # This section cleans up incoming tcp packets scrub in all # QUEUEING # TRANSLATION nat on fxp0 inet from 192.168.100.0/24 to any -> 10.0.0.100 # FILTER RULES # This section sets the default policies to Block block in all block out all # These ip addresses should not appear on the outside of # the firewall block in quick on fxp0 from 0.0.0.0/32 # block in quick on fxp0 from 10.0.0.0/8 block in quick on fxp0 from 127.0.0.0/8 block in quick on fxp0 from 172.16.0.0/12 block in quick on fxp0 from 192.0.2.0/24 block in quick on fxp0 from 192.168.0.0/16 block in quick on fxp0 from 240.0.0.0/5 block in quick on fxp0 from 224.0.0.0/4 # NAT occurs before filtering, so secure subnet # network address should not appear outside the firewall block out quick on fxp0 from 192.168.100.0/24 # Block spoofed ip addresses from pc`s on secure # subnet block in quick on fxp1 from ! 192.168.100.0/24 block in quick on fxp1 from 192.168.100.1 # Allow traffic on loopback interface pass quick on lo0 all # Set up stateful packet filtering pass out on fxp0 inet proto tcp from any to any keep state pass out on fxp0 inet proto udp from any to any keep state pass out on fxp0 inet proto icmp from any to any icmp-type echoreq keep state pass out on fxp0 inet proto 47 from any to any keep state # Open up fxp1 pass in on fxp1 inet from 192.168.100.0/24 to any pass out on fxp1 inet from any to 192.168.100.0/24 In my Linux firewalls, as well as doing ip address blocking, NAT, and stateful packet filtering, I also had a default deny policy for all TCP and UDP ports, and then added rules to allow specific ports through the firewall. Currently I haven`t gone down this road with my OpenBSD + pf firewalls, as it is going to increase very considerably the number of rules that every packet would have to go through. But it may happen in the future.
pfctlIn order for humans to interact with pf, OpenBSD provides a tool called "pfctl" which can be used to view the existing configuration of pf, and also make changes on the fly. NB - making changes on the fly will change the current configuration of pf, but if you do a reboot, pf loses these changes, and goes back to the configuration as specified in the /etc/pf.conf file. Again, there is lots of documentation on pfctl, so there is no point in me providing full details on this web page, but here are some of the things you can do with it :- pfctl -f /etc/pf.conf reload the /etc/pf.conf configuration file pfctl -sa view all configuration settings pfctl -sr view just the filter rules pfctl -ss view the state table This last one, viewing the state table, is somewhat limited, as it only shows a snapshot of the state table at the time you run the command. However the contents of the state table are continuously changing as new packets need to be recorded. It would be great if you could view the state table in real time, so you could see each new entry as it happens. It would make troubleshooting so much easier. Dream on !
That`s itThat is as far as I have got so far, I`ll add some more if I get deeper into pf
© 2006 Ron Turner Return to the Index page
|
|