by Real Ouellet (hello@realo.ca)
Why would one install his own personal gateway to the Internet? Because it is
quite easy to do. And also because it simply is the most reliable, safest way to
connect machines to a dedicated xDSL modem. Moreover, we can stash a whole
bunch of useful features in such a little box. Here is a list:
This page is for all those of you who have are lucky enough to enjoy a dedicated xDSL connection and would like to have a small firewall installation. In my search for the holy grail, i found the answer to most of my wishes in the OpenBSD package. This step-by-step guide is a collection of notes taken while I was installing the thing. They are intended to help my friends do their own setups very quickly and easily, without having to bug me too much ;) They should help you too.
Constructive comments can be sent there ... Have fun and GOOD LUCK!
The first thing to think about when one embarks on the firewalling adventure is to establish on what hardware you are going to install the thing. This seems unimportant at first, but don't forget that this box will be turned on 24/7, so the components you use must be reliable.
What are the minimum requirements? My system uses about 50% of its CPU to support Sympatico's ADSL rate (around 900 kbps). It is built with the following components:
This gives a good approximation of what you need. The MOST important part is the RAM. Make absolutely sure that whatever RAM you use is reliable. Old boxen were usually setup to run Windoze, and it was not a big deal if the machine had flaky RAM because of the way Windoze works...
OpenBSD (like any real OS out there) is much less tolerant of flaky RAM, because it actually uses all of it. It will crash quite quickly if your RAM is marginal, probably within 5-10 minutes. You have been warned.
Finally, the OpenBSD hardware list is there. Try to make sure that whatever hardware you use in your gateway box figures on that list. It's a long list ;)
There is a boring thing of which we must talk about here. You see, there are many kinds of ethernet cards, and you must make sure you have the right ones for your machine. If you have a PCI-based machine, then all is well. Whatever ethernet card you put in there will probably be supported by OpenBSD. However, you must be a bit more careful if you have an ISA-based machine.
It is most likely that your box will not have any ethernet cards to start with since most people did not have networks at home in the pre-historic era of 4 years ago. You need two cards. One will be connected to the DSL modem (the big, bad outerworld), while the other is connected to your internal network hub (your intranet). The gateway's job will be to pass (or block) packets between those two network cards. For security, its very important that the outside world packets cannot reach directly any of the intranet machines. This is the reason why we use two ethernet cards: complete logical and electrical isolation. Why so much isolation? For example, if someone(s) were launching a full (distributed or not) denial of service attack on your gateway box, its internet-connected ethernet card would be extremely busy, but your intranet would see nothing of this. While any communication with the outside world would probably fail, at least your intranet machines would still be able to talk to each other.
ISA cards use dedicated I/O ports and IRQ's in your machine. Those must be setup either with jumpers directly on the card, or with a special DOS program if the card is of the more recent "Plug & Play" type. This DOS program is always supplied with the card, when purchased brand new.
If your card is Plug&Play, you must disable the Plug&Play, and program specific I/O port and IRQ values with the setup software that comes with the card. Make sure that you program both cards with different sets of I/O ports and IRQs! Otherwise they will battle each other for cycles on the bus and the result will not be pretty. Once you have set the parameters on the card it will remember them and you don't have to reprogram anything later on, even if the computer is turned off.
It is good at this point to know a few magic numbers:
| Card Type | I/O #1 | IRQ #1 | Mem #1 | I/O #2 | IRQ #2 | Mem #2 |
|---|---|---|---|---|---|---|
| NE2000 (ne) | 0x240 | 9 | -- | 0x300 | 10 | -- |
| SMC WD-8003 (we) | 0x280 | 9 | 0xd0000 | 0x300 | 10 | 0xcc000 |
For example, i use two cards made by AOpen: the model ALN-101. They are Plug&Play and use the NE2000 chip. The first one is setup at I/O port 0x240, IRQ 9. It is known as "ne0" in the GENERIC openBSD kernel. The second one is set at I/O port 0x300, IRQ 10. It is known as "ne1". If the cards were programmed differently, the GENERIC kernel would not recognize them "out of the box" and you would have to re-configure the kernel. It can be done, but its much easier to setup the hardware once than re-configure the kernel every time it gets upgraded.
Some of you might have problems setting the card to an arbitrary combination of IO port and IRQ number. This is allright, just let the card decide what it wants and simply reconfigure your kernel to accomodate that. What is important is that both ethernet cards are not set to conflicting values. Otherwise, any combination that the cards like will be programmable in the kernel.
Last but not least: some cards can be used in the so-called "full-duplex" mode. Be aware that if you want to use an ethernet card in full-duplex, your hub must also be full-duplex, as well as the other ethernet cards in the system. A full-duplex hub is much more expensive and not necessary at all. Unless you know what you are doing, program your ethernet cards to use the half-duplex mode, otherwise it won't play nice with the other components in your local network, including the xDSL modem ;)
The most secure storage medium is one which can't be erased. Some firewalls actually use setups like this (with CD-ROMS) but we'll build our firewall with a classic, writeable hard drive because:
Almost any hard disk out there will work OK, since 200 MB is a safe minimum size. The only thing you must remember is that this disk will run 24/7, so if you use an old drive, it will likely die relatively soon. The venerable drive my friend gave me lasted 6 months before i had to change it, YMMV.
Of course you'll need a keyboard... and a monitor too, but just for the installation. After the firewall is successfully installed, you will be able to talk to it through encrypted ssh connections over your internal network, so a keyboard & monitor will not be really useful at that point.
We will be using OpenBSD. Why? Because it is the most secure freely available operating system out there. All the source code included in the mainstream distribution CD's has been audited for years by the OpenBSD team, which is why sometimes an exploit published on BugTraq is found not to work on OpenBSD simply because the faulty code was already fixed months ago.
I strongly suggest you buy their CD-ROM kit as it comes with a set of very cool stickers... You can also download their stuff for free, of course, but you won't have the stickers then ;)
This Guide is written for OpenBSD 3.0.
The easiest way to install the software is to use a CD-ROM drive on your firewall box. If you don't have that, you can do a network install with the "ftp" protocol, either directly to an outside OpenBSD mirror, or to one of your own internal machines equipped with an ftp server. Be aware that if your DSL provider forces you to use PPPoE (boooo!), then of course your link to the outside world will not be functional yet at installation time, which is one more reason to use the CD-ROM. If your machine can boot a CD-ROM, great! It will gladly boot the OpenBSD disc. Otherwise, simply create a boot diskette according to the README and boot that. This diskette is also your rescue disk, so don't lose it.
The installation of OpenBSD is very easy, once you have the right hardware, and the right answers to some of the questions. In the following steps, i'll assume you can follow the instructions of the install program and focus only on the tricky little things you should know to make your life easier.
The default OpenBSD fdisk partition setup choice is in slot #3. If you want, you can move your OpenBSD partition in slot #0 with no ill effect.
Important: On some systems, to make sure your system boots off the hard disk, you must set the starting CHS (cylinder/head/sector) to C=0, H=0, S=1, because fdisk suggested an incorrect value for H in OpenBSD 2.7, and still does in 2.8 ... If you use "1", as it suggests, your system will not be able to boot from the hard disk.
After the disk is partitioned with fdisk, you use disklabel to further organize the partition. A label behaves like a traditional partition (as used in Linux, for example), except that you can put as many labels as you want in the single OpenBSD partition. This is useful.
On a fully partitioned system, the disk labels might look like this:
a: 2097648 0 4.2BSD 1024 8192 16 # / 1 GB b: 262080 2097648 swap # SWAP 128 MB c: 20015856 0 unused 0 0 # (whole disk) 10 GB d: 2097648 2359728 4.2BSD 1024 8192 16 # /usr 1 GB e: 2097648 4457376 4.2BSD 1024 8192 16 # /tmp 1 GB f: 2097648 6555024 4.2BSD 1024 8192 16 # /var 1 GB g: 4194288 8652672 4.2BSD 1024 8192 16 # /usr/local 2 GB h: 7168896 12846960 4.2BSD 1024 8192 16 # /home 3 GB
# size offset fstype [fsize bsize cpg] a: 18874800 0 4.2BSD 1024 8192 16 # (Cyl. 0 - 18724) b: 1141056 18874800 swap # (Cyl. 18725 - 19856) c: 20015856 0 unused 0 0 # (Cyl. 0 - 19856)
As you see, the 'c' label is a placeholder for the whole disk, in all cases. Don't delete or otherwise change this, or you'll be in trouble.
One of the main disadvantages of having a single partition is that one could do bad things in such quantity that the log files would simply fill up the whole drive. OpenBSD doesn't like it when all its disk space is full. You can guess the rest of the story. In practice, this is not an issue, since i monitor my log files daily, but it could be an issue for someone out there.
On a fully partitioned system, the "df" command says this, after the OS is installed,
with its complete source trees:
Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/wd0a 1015269 25985 938521 3% / /dev/wd0d 1015269 480284 484222 50% /usr /dev/wd0e 1015269 1 964505 0% /tmp /dev/wd0f 1015269 5141 959365 1% /var /dev/wd0g 2030307 8698 1920094 0% /usr/local /dev/wd0h 3470505 27 3296953 0% /home
On my system i have this:
Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/wd0a 9137589 503054 8177656 6% /
In this example, the full OpenBSD source tree is installed, which explains why the thing uses up about 500 MB. Without the source tree, you only need about 120 MB in there, but having the source tree allows you to make security patches as they are published. This is important and i'll talk about it more later.
Why not GMT instead? Read all about it there.
Normally, the installer will ask you for a time zone at install time.
If you want to change it later, simply make /etc/localtime point to /usr/share/zoneinfo/UTC with a soft link:
ln -s /usr/share/zoneinfo/UTC
/etc/localtime
On first boot, you will probably get a message like "ssh-keygen: generating new DSA host key...", followed with an equivalent message for the RSA host key. They might take quite a long time on a 486 (5-10 minutes), so Don't Panic! (tm) , the machine is not crashed, and the boot process will eventually follow its course, given time. This will happen only on the first boot.
config -e -f /bsd
For now, just make sure that the following are enabled:
net.inet.ip.forwarding=1
sendmail_flags="-L sm-mta -bd -q30m" named_flags="" httpd_flags="-DSSL"
Notice that there is an excellent Network FAQ available from the OpenBSD site. It contains a lot of information on what to do with those ethernet adapters.
The configuration file for ppp is in /etc/ppp/ppp.conf. Mine contains exactly this:
default: set log Phase Chat IPCP CCP tun command set redial 15 0 set reconnect 15 10000 pppoe: set device "!/usr/sbin/pppoe -i ne0" disable acfcomp protocomp deny acfcomp set mtu max 1492 set speed sync enable lqr set lqrperiod 5 set cd 5 set dial set login set timeout 0 set authname xxxxxxx set authkey xxxxxx add! default HISADDR enable dns enable mssfixup
Notice how we specify the real network interface ne0 to pppoe (with double quotes), and that i use "max 1492" for the MTU value, as suggested by many people. Also, no value is specified for the MRU, the PPP network address translation is not enabled, the magic "mssfixup" is enabled and i use the "add!" command instead of plain "add" (suggested by Chris Pockele).
Also notice that the authname and authkey fields don't contain double-quote characters. You should put in there your own ISP identification and password. Some ISPs require authname to have a full identification (e.g. "username@sympatico.ca"), while other ISPs will want to have only "username" in the authname field. Experiment.
Robert Jameson (thanks Robert!) reports that some ISPs require you to specify the pppoe service you want. This is done on the "set device" line. For example:
set device "!/usr/sbin/pppoe -n Shasta_1 -i ne0"
VERY IMPORTANT!
For some reason, the routes setup automatically by ppp at linkup time were not correctly defined prior to OpenBSD version 3.0. The MTU's were wrong, leading to all sorts of subtle problems. This is now fixed, and we can safely use the "add default HISADDR" command in the ppp config file, with no special route commands at all in the ppp.linkup file. The MTUs will be properly set to 1492 on all the routes which go through the external interface.
The command "netstat -rn" confirms this:
pcreal# netstat -rn Routing tables Internet: Destination Gateway Flags Refs Use Mtu Interface default 65.92.185.1 UGS 3 13423 1492 tun0 65.92.185.1 65.92.185.97 UH 1 0 1492 tun0 127.0.0.1 127.0.0.1 UH 1 1045 33224 lo0 192.168.1/24 link#2 UC 0 0 1500 ne1 192.168.1.1 0:e0:18:90:a7:c7 UHL 3 10475 1500 ne1 ...
A friend from Australia (thanks Doug!) suggested i clarify the following points:
(1) The 64.229.x.x adresses will NOT be the same in your setup! Those are the adress blocks of my PPPoE service provider (Sympatico). Your own setup will use, most likely, different address blocks.
(2) The ppp daemon creates a virtual network interface ("tun0") out of thin air. This virtual network interface is internally linked to the actual physical interface ("ne0" in my system), but you will never have to deal directly with "ne0" in your configuration files. For example, the firewall rules are written with the virtual "tun0" interface, not the physical "ne0" interface. In my setup, the internal interface is "ne1", and the external interface is "tun0". Here is Doug's analogy with the Windows world:
"... think of the PPPoE adaptor like the dialup adaptor in a Windows control panel. it doesn't really exist but you gotta have it..."
(3) The ppp daemon takes care of automatically assigning the name servers and the routes. Consequently, make sure there is no file "/etc/mygate", and bear in mind that "/etc/resolv.conf" will be automatically generated as well, at connection time. This has the advantage that you don't need to know anything about the details of your connection (name server adresses, etc...) to your ISP. Your user ID and password are sufficient, as the ppp daemon will negociate with the server and obtain the information it needs to open the connection.
(4) Since the ppp daemon will take are of the external network interface, you don't need a "/etc/hostname.ne0" file. However, you do need a file to describe your internal network interface (in my case, "ne1"):
pcreal# cat /etc/hostname.ne1 inet 192.168.1.2 255.255.255.0 NONE
Normally, this file should have been built by the setup program of OpenBSD, but if not, you must manually put it there and replace the "192.168.1.2" with whatever address you want your gateway to have as seen from your internal network.
Another friend, from France (thanks Xavier!), sent me this ascii picture of the network connections:
| |
internet| ====> |DSL Modem| ====>|server|=====>|LAN (HUB)
| tun0 ne1 |
| =ne0 |
Note: I consider this PPP/PPPoE setup to be a work in progress. I continually discover new things about it... so, please bear with me and do send me your feedback about your own experience regarding PPP/PPPoE. It really is a pain, but apparently we will be stuck with it for a long long time, so we might as well learn how to tame the thing!
reboot ... your machine should boot correctly. You won't have internet access yet because the ppp program is not activated. If you want to try it out, just issue
ifconfig ne0 up ppp -ddial pppoe
and ping/telnet away. Don't worry if you get "carrier settings ignored", or "change route failed" messages. Be careful because at this point you have no firewall rules set, so you are very vulnerable. Also, make sure your xDSL modem is plugged in the correct ethernet card...
If all works well, then you should kill the "ppp" process. Only restart it when the firewall rules are in place.
* [15]afterboot(8) - things to check after the first complete boot
* [16]boot(8) - system boot strapping procedures
* [17]passwd.conf(5) - format of the password configuration file
* [18]adduser_proc(8) - procedure for adding new users
* [19]adduser(8) - command for adding new users
* [20]vipw(8) - edit the pass word file
* [21]man(1) - display the on-line manual pages
* [22]sendbug(1) - send a problem report (PR) about OpenBSD to a
central support site.
* [23]disklabel(8) - Read and write disk pack label.
* [24]ifconfig(8) - configure network interface parameters.
* [25]route(8) - manually manipulate the routing tables.
* [26]netstat(1) - show network status.
* [27]reboot, halt(8) - Stopping and restarting the system.
* [28]shutdown(8) - close down the system at a given time.
* [29]boot_config(8) - how to change kernel configuration at boot
One of the first things you should do at this point is to add an unprivileged user and make him member of the wheel group. This is because, for security reasons, it is never a good idea to log in directly as root. The preferred way to gain root privileges is to login as a wheel member, and then use the "su -" command to gain root privileges.
OpenBSD will not prevent you from logging in directly as root, but will warn you every time against doing it.
Have fun!
Here are my own pf rules, in all their glory. They were heavily influenced by the various man pages and HOW-TO's pertaining to "pf". Be aware that they might be either too restrictive, or not enough, depending on your context. My philosophy about this is to disallow everything by default, and only open whatever is known to be useful. This restrictive ruleset will prevent ftp from working correctly, from the firewall itself. However, the ftp proxy currently available will work correctly for client machines located on the intranet.
Don't forget to send me your tips for better rules... Thanks!
nat on tun0 from 192.168.1.0/24 to any -> tun0
rdr on ne1 proto tcp from any to any port 21 -> 127.0.0.1 port 8081
#--------------------------------------------------------------------------
# PF ruleset, 11 dec. 2001
#
# Liberally adapted from the pf man page, the OpenBSD "Network How-To",
# and my own rulesets.
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Definitions
Ext = "tun0" # External interface
Int = "ne1" # Internal interface
Loop = "lo0" # Loopback interface
IntNet="192.168.1.0/24" # Internal network
NoRoute = "{ 127.0.0.1/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 255.255.255.255/32 }"
InServicesTCP = "{ ssh, smtp, auth, http, https, pop3 }"
#InServicesUDP = "{ domain }"
OutServicesTCP = "{ http, https, smtp, pop3, whois, domain, ssh, telnet, ftp, ftp-data, nntp, auth, ntp }"
OutServicesUDP = "{ ntp, domain }"
XMMS = "{ 6000, 7500, 8000, 8004, 8044, 8034, 8052, 8038, 8010, 8400, 8014, 8026, 8048, \
8002, 8024, 8028, 8080 }"
RealAudio = "{ 554, 7070, 8080 }"
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Clean up fragmented and abnormal packets
# By default in pf, packets which contain IP options are blocked. Good.
scrub in on { $Ext, $Int } all
#--------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Defaults
# block and log everything
block out log on $Ext all
block in log on $Ext all
block return-rst out log on $Ext proto tcp all
block return-rst in log on $Ext proto tcp all
block return-icmp out log on $Ext proto udp all
block return-icmp in log on $Ext proto udp all
block in quick inet6 all
block out quick inet6 all
#-------------------------------------------------------------------------
#--------------------------------------------------------------------------
# loopback packets left unmolested
pass in quick on $Loop all
pass out quick on $Loop all
#--------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Immediate blocks
# fuzz any 'nmap' attempt
block in log quick on $Ext inet proto tcp from any to any flags FUP/FUP
block in log quick on $Ext inet proto tcp from any to any flags SF/SFRA
block in log quick on $Ext inet proto tcp from any to any flags /SFRA
# don't allow anyone to spoof non-routeable addresses
block in log quick on $Ext from $NoRoute to any
block out log quick on $Ext from any to $NoRoute
# silently drop broadcasts (cable modem noise)
block in quick on $Ext from any to 255.255.255.255
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# PASS rules
# ALL -- we don't normally do that. For debugging only.
#pass out quick on $Ext all keep state
# pass in data mode connections for ftp-proxy running on this host.
pass in quick on $Ext inet proto tcp from any to any port > 49151 flags S/SA keep state
# ICMP
pass out quick on $Ext inet proto icmp all icmp-type 8 code 0 keep state
pass in log quick on $Ext inet proto icmp all icmp-type 8 code 0 keep state
# Services we provide to the outside world
#pass in quick on $Ext inet proto udp from any to any port $InServicesUDP keep state
pass in quick on $Ext inet proto tcp from any to any port $InServicesTCP flags S/SA keep state
# Standard services we want to access in the world
pass out quick on $Ext inet proto udp from any to any port $OutServicesUDP keep state
pass out quick on $Ext inet proto tcp from any to any port $OutServicesTCP flags S/SA modulate state
# Special services
pass out quick on $Ext inet proto tcp from any to any port $XMMS flags S/SA modulate state
pass out quick on $Ext inet proto tcp from any to any port $RealAudio flags S/SA modulate state
That's it! Nothing too painful, as you see. Since pf is a stateful inspection firewall, we can keep our ingress rules to a strict minimum. Notice the sheer elegance of the ruleset, with all services defined at once in a single IN or OUT rule.
One last thing: in order to automagically enable your firewall when the link comes up, you can put the following lines in the /etc/ppp/ppp.linkup file. Notice the extra space in front of each "!" character:
MYADDR: ! sh -c "/sbin/ifconfig pflog0 up" ! sh -c "/sbin/pfctl -e -l tun0 -F all -O aggressive -R /etc/pf.conf -N /etc/nat.conf"
If you want tight security, and no FTP available on your intranet, simply remove the hole at 49152, and the "rdr" command in the file "nat.conf". However, if you want to be able to use FTP from the intranet, then you must keep those, as well as enable the "ftp-proxy" service in inetd. Simply add this line to inetd.conf :
8081 stream tcp nowait root /usr/libexec/ftp-proxy ftp-proxy
Don't forget that you still won't be able to do FTP'ing from the firewall itself, when the packet filtering is enabled. Hopefully, it is very easy to temporarily disable pf with the command "pfctl -d", and later re-enable it with the command "pfctl -e". This comes in handy when we install packages from ftp.openbsd.org with the command "pkg_add".
We are confident that ftp-proxy will improve with time and eventually dynamically manipulate the state tables of the firewall in order to open/close needed connections on-the-fly.
This is where our custom startup instructions go. Those things are started while the kernel is in secure level 1. If you need anything started in a lower security level, modify /etc/rc.securelevel instead. In order to start up PPPoE correctly, I added this at the end of my /etc/rc.local :
ifconfig ne0 up route flush ppp -ddial pppoe
This starts PPP, PPPoE, the firewall and the NAT translator (because the firewall and the NAT are started automatically in the ppp.linkup file). If you're curious, you can reboot at this point, and confirm that you have a fully firewalled internet access:
pcreal# ifconfig -a lo0: flags=8009mtu 33224 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x5 inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 lo1: flags=8008 mtu 33224 ne0: flags=8863 mtu 1500 media: Ethernet autoselect (10baseT) inet6 fe80::240:f4ff:fe2b:190d%ne0 prefixlen 64 scopeid 0x1 ne1: flags=8863 mtu 1500 media: Ethernet autoselect (10baseT) inet 192.168.1.2 netmask 0xffffff00 broadcast 192.168.1.255 inet6 fe80::240:f4ff:fe2b:16b1%ne1 prefixlen 64 scopeid 0x2 pflog0: flags=141 mtu 33224 sl0: flags=c010 mtu 296 sl1: flags=c010 mtu 296 ppp0: flags=8010 mtu 1500 ppp1: flags=8010 mtu 1500 tun0: flags=8011 mtu 1492 inet 65.92.185.97 --> 65.92.185.1 netmask 0xffffffff tun1: flags=10 mtu 3000 enc0: flags=0<> mtu 1536 bridge0: flags=0<> mtu 1500 bridge1: flags=0<> mtu 1500 vlan0: flags=0<> mtu 1500 vlan1: flags=0<> mtu 1500 gre0: flags=8010 mtu 1450 gif0: flags=8010 mtu 1280 gif1: flags=8010 mtu 1280 gif2: flags=8010 mtu 1280 gif3: flags=8010 mtu 1280 pcreal# pfctl -sr @0 scrub in on ne1 all @1 scrub in on tun0 all @2 block out log on tun0 all @3 block in log on tun0 all @4 block return-rst out log on tun0 proto tcp all @5 block return-rst in log on tun0 proto tcp all @6 block return-icmp out log on tun0 proto udp all @7 block return-icmp in log on tun0 proto udp all @8 block in quick inet6 all @9 block out quick inet6 all @10 pass in quick on lo0 all @11 pass out quick on lo0 all @12 block in log quick on tun0 inet proto tcp all flags FPU/FPU @13 block in log quick on tun0 inet proto tcp all flags FS/FSRA @14 block in log quick on tun0 inet proto tcp all flags /FSRA @15 block in log quick on tun0 inet from 255.255.255.255/32 to any @16 block in log quick on tun0 inet from 10.0.0.0/8 to any @17 block in log quick on tun0 inet from 172.16.0.0/12 to any @18 block in log quick on tun0 inet from 192.168.0.0/16 to any @19 block in log quick on tun0 inet from 127.0.0.1/8 to any @20 block out log quick on tun0 inet from any to 255.255.255.255/32 @21 block out log quick on tun0 inet from any to 10.0.0.0/8 @22 block out log quick on tun0 inet from any to 172.16.0.0/12 @23 block out log quick on tun0 inet from any to 192.168.0.0/16 @24 block out log quick on tun0 inet from any to 127.0.0.1/8 @25 block in quick on tun0 inet from any to 255.255.255.255/32 @26 pass in quick on tun0 inet proto tcp from any to any port > 49151 flags S/SA keep state @27 pass out quick on tun0 inet proto icmp all icmp-type echoreq code 0 keep state @28 pass in log quick on tun0 inet proto icmp all icmp-type echoreq code 0 keep state @29 pass in quick on tun0 inet proto tcp from any to any port = pop3 flags S/SA keep state @30 pass in quick on tun0 inet proto tcp from any to any port = https flags S/SA keep state @31 pass in quick on tun0 inet proto tcp from any to any port = www flags S/SA keep state @32 pass in quick on tun0 inet proto tcp from any to any port = auth flags S/SA keep state @33 pass in quick on tun0 inet proto tcp from any to any port = smtp flags S/SA keep state @34 pass in quick on tun0 inet proto tcp from any to any port = ssh flags S/SA keep state @35 pass out quick on tun0 inet proto udp from any to any port = domain keep state @36 pass out quick on tun0 inet proto udp from any to any port = ntp keep state @37 pass out quick on tun0 inet proto tcp from any to any port = ntp flags S/SA modulate state @38 pass out quick on tun0 inet proto tcp from any to any port = auth flags S/SA modulate state @39 pass out quick on tun0 inet proto tcp from any to any port = nntp flags S/SA modulate state @40 pass out quick on tun0 inet proto tcp from any to any port = ftp-data flags S/SA modulate state @41 pass out quick on tun0 inet proto tcp from any to any port = ftp flags S/SA modulate state @42 pass out quick on tun0 inet proto tcp from any to any port = telnet flags S/SA modulate state @43 pass out quick on tun0 inet proto tcp from any to any port = ssh flags S/SA modulate state @44 pass out quick on tun0 inet proto tcp from any to any port = domain flags S/SA modulate state @45 pass out quick on tun0 inet proto tcp from any to any port = whois flags S/SA modulate state @46 pass out quick on tun0 inet proto tcp from any to any port = pop3 flags S/SA modulate state @47 pass out quick on tun0 inet proto tcp from any to any port = smtp flags S/SA modulate state @48 pass out quick on tun0 inet proto tcp from any to any port = https flags S/SA modulate state @49 pass out quick on tun0 inet proto tcp from any to any port = www flags S/SA modulate state ... @72 pass out quick on tun0 inet proto tcp from any to any port = 6000 flags S/SA modulate state @73 pass out quick on tun0 inet proto tcp from any to any port = 8080 flags S/SA modulate state @74 pass out quick on tun0 inet proto tcp from any to any port = 7070 flags S/SA modulate state @75 pass out quick on tun0 inet proto tcp from any to any port = 554 flags S/SA modulate state
With the new pf firewall code comes a new way to log firewalled packets and look at them. The log is actually taken care of by a separate daemon ( pflogd ) which should be started in "ppp.linkup" and killed in "ppp.linkdown". This daemon puts its data in a special log file ( /var/log/pflog ) which is not directly human readable, for performance reasons. To get a dump of the file, simply issue the command "tcpdump -n -e -ttt -r /var/log/pflog", or , if you want a real-time display of the logs, simply issue "tcpdump -n -e -ttt -i pflog0".
Dynamic DNS is a wonderful thing. Basically, you just go to a dyndns provider like those nice people and 10 minutes later you have your very own domain, for free. In order to make that domain dynamically follow your IP address changes, you must use a special client program which must be called whenever your IP changes.
Until recently I liked ddup, but now i use ipcheck. The latter is truly compliant with all of dyndns's client specification, and maintains its state automatically in system files. You will have to install the python package if you use "ipcheck". Also, you'll need your user ID and password from the dyndns provider.
One more advice: it is perfectly acceptable to have more than one domain pointing at the same IP address. Remember this when choosing one or more domain names...
xDSL connections are very reliable, but ISP's are not ;) For many reasons unfathomable, you will sometimes lose your connection. There are many methods of re-establishing that connection automatically, and i'll describe here the one i use.
Make sure you initialise ppp with the "-ddial" command, and NOT the "-background" command...
The automatic restart of the ppp link is handled by ppp itself (using the "-ddial" command), which is quite handy. This leaves us with the dyndns updates, which are performed intelligently by ipcheck.py . An easy way of doing it is to create an executable file named "do_ipcheck" which contains this:
#!/bin/sh /usr/local/sbin/ipcheck.py -q -d /etc/ipcheck -i tun0 -w Username Password DomainName1,DomainName2
with your own Username, Password and Domain names, of course. Then, all you have to do is to add the following line to crontab:
*/5 * * * * /usr/local/sbin/do_ipcheck
Also, don't forget to create the directory /etc/ipcheck and make sure your /etc/ppp/ppp.linkup file looks like this:
MYADDR: ! sh -c "/sbin/ifconfig pflog0 up" ! sh -c "/sbin/pfctl -e -l tun0 -F all -O aggressive -R /etc/pf.conf -N /etc/nat.conf" ! sh -c "/usr/local/sbin/ResetNTP.sh" !bg sh -c "/usr/local/sbin/do_ipcheck"
You can call "do_ipcheck" from "ppp.linkup" ... however, you must use the special "!bg" construct, in order to instruct ppp to fork it in the background. Nasty stuff happens if you don't use "!bg" here. Big thanks to Dan for this update!
This setup should garantee the proper restart of the firewall & ipnat each time the ppp link is brought up again.
Now would be a good time to install your htdocs directory. The way i like to do this is to mount a read-only NFS file system over the current htdocs. This is easily accomplished by adding a line like this to your /etc/fstab :
192.168.1.1:/usr/local/Apache/htdocs /var/www/htdocs nfs ro
Moreover, the web logs are kept in /var/www/logs. Interesting stuff.
We are in full virus season and i'm sure your log files will fill up as fast as mine with useless garbage, once your Apache is up. In order to remove some clutter, you can filter out the virus attacks and channel them to a specialized attack_log file. Simply insert the following lines into your /var/www/conf/httpd.conf file:
SetEnvIf Request_URI "^/default.ida" attacks # For Code Red SetEnvIf Request_URI "^/scripts" attacks # For nimda SetEnvIf Request_URI "^/c/winnt" attacks # ... ditto all the way down SetEnvIf Request_URI "^/_mem_bin" attacks SetEnvIf Request_URI "^/_vti_bin" attacks SetEnvIf Request_URI "^/MSADC" attacks SetEnvIf Request_URI "^/msadc" attacks SetEnvIf Request_URI "^/d/winnt" attacks CustomLog /var/www/logs/access_log combined env=!attacks CustomLog /var/www/logs/attack_log combined env=attacks
This will send all virus-related requests to "attack_log", while still logging other activities normally in access_log.
Someone (Chavous P. Camp, thanks!) sent me advice on optimizing "named" for faster throughput. He recommends to add two lines to the "/var/named/named.boot" file:
options forward-only forwarders ip.addresses.of.ISPs.nameservers.separated.by.spaces
This forces named to always use the same servers for dns. If your ISP's servers are always on fixed IP adresses, then it works well. However, ISP's who force you to use PPPoE will also sometimes change dynamically the DNS servers allocated to you (in "/etc/resolv.conf", automatically created by ppp at startup). In that case, there is no garantee that the name servers you hardwire as forwarders will always be available.
The GENERIC OpenBSD kernel comes precompiled with IP v6 support. This is the reason why you might see many "/bsd: tun0: not multicast capable, IPv6 not enabled" error messages in your logs. Those messages are completely harmless and do not alter the performance of your system. However, should you want to get rid of them, you can simply remove IPv6 support from your kernel by modifying "/usr/src/sys/conf/GENERIC" and removing the "option INET6" line. Then recompile your kernel in the usual way. Thanks Chavous for this info!
Another excellent suggestion from Chavous. Scripts and config files with passwords should have their permissions changed to 500 (for scripts) or 400 (for config files), for greater security. This includes "ppp.conf", "do_ipcheck", etc...
The ntpd daemon is not installed by default. However, you can download it as a package, and install it with the pkg_add command. Since you have internet connectivity by now, you can download & install it in a single command:
pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/3.0/packages/i386/ntp-4.1.71.tgz
Moreover, you will need a valid /etc/ntp.conf file:
pcreal# cat /etc/ntp.conf server 128.100.102.201 driftfile /etc/ntp.drift
Feel free to use any other atomic time server if you want. Also, the drift file will be created & maintained automagically.
Important tip from Chavous:=========================================
I found my ntp server would refuse to synchronize after a reboot because it
had no route to the time server. This was, of course, because PPPoE is
loaded AFTER ntp, and sometimes the PPPoE negotiation after a reboot takes a
few seconds.
Anyway, here is something you might want to add as a suggestion:
Turn ntpd OFF in the rc.conf file
add this line to your ppp.linkup file - AFTER the firewall initialization
! sh -c "/etc/ppp/ResetNTP.sh"
That script should then contain:
#!/bin/sh
if [ -f /var/run/ntpd.pid ]; then
kill `cat /var/run/ntpd.pid`
rm -f /var/run/ntpd.pid
fi
/usr/local/sbin/ntpd -p /var/run/ntpd.pid
(as I have said before, remind your readers that this script is executed as
root and should therefore be chmod 444 or less)
This kills the NTP daemon (if it exists) and restarts it. On boot, it would
not be restarted, but what if the link went down for a while? The ntp daemon
would give up and stop sending queries because it couldn't get a route to
host.
REALLY, the ntp daemon SHOULD NOT stop querying the server just because it
can't get a route to the host, but it seems to be written as such now
anyway. I haven't tested the ntp daemon over a long period of time (more
than about a day) so I don't know if it just gives up for some arbitrarily
long period (MORE than a day) and then tries again. I seriously doubt it
does, because a day is a LONG time. This workaround isn't ideal, because
for time consistency, one would want the time server to stay running at all
times. According to the ntpd documentation, ntpd tends to become more
accurate the longer it runs.
Chavous
=========================================
If you have followed all the steps of the recipe so far, your sendmail should be configured & ready to receive mail from the internet, however you should know a few more things about this. First, if you want your gateway to receive mail for more than one domain, you must make sure the all fully qualified domains are setup as aliases for your host in the file /etc/hosts.
All ingress mail is received & kept on the gateway untill some POP client on the intranet gets it. I use the "popa3d" server package because it is written with security in mind. It is now part of the main OpenBSD 3.0 distribution, so you don't have to download it as a separate package. Simply enable it in the file /etc/inetd.conf and you should be up & running.
Just to do a quick check, here are the packages i have installed on my system:
pcreal# pkg_info gmp-3.1.1 library for arbitrary precision arithmetic python-2.1.1 interpreted object-oriented programming language ntp-4.1.71 network time protocol implementation libiconv-1.7 character set conversion library gettext-0.10.40 GNU gettext mhash-0.8.9 strong hash library libtool-1.3.5p3 generic shared library support script postgresql-7.1.3 PostgreSQL RDBMS libmcrypt-2.4.15 interface to access block/stream encryption algorithms c-client-4.40p1 University of Washington's c-client mail access routines php4-4.0.6p1-gettext-imap-mhash-no_x11-mcrypt-postgresql server-side HTML-embedded scripting language
[real@pcreal Projects]$ ssh 192.168.1.2
real@192.168.1.2's password:
Warning: Remote host denied X11 forwarding.
Last login: Sun Nov 5 12:58:08 2000 from 192.168.1.1
OpenBSD 2.7 (GENERIC) #1: Thu Nov 2 16:05:11 GMT 2000
pcreal:real {39}
Once you are logged in as an unprivileged user, member of the wheel group, you can use su to gain superuser privileges:
pcreal:real {39} su -
Password:
Terminal type? [nxterm]
pcreal#
/var/log/messages /var/log/maillog /var/log/secure /var/www/logs/access_log
Moreover, you can grab interesting info about the blocked packets on your firewall with the "ipmon" utility.
There are many other log files available for all kinds of things. Dig around to find more about them.
Dave Cook has kindly provided us with a good description of how to install IPSEC on your OpenBSD boxen: http://www.realo.ca/ipsec.pdf, in PDF (Acrobat) format. Be aware that it is a largish file (440K), and it might take some time for your Acrobat reader to load afterwards, so don't hit the link repeatedly, it won't make things load faster... ;)
It is not really difficult, but you will need a copy of the complete, original source tree of the distribution. The compressed source archives are to be found with the distribution files. These are the 3.0 source files:
src.tar.gz 64447 Kb Tue May 1 16:18:00 2001 Unix Tape Archive
srcsys.tar.gz 13837 Kb Tue May 1 16:18:00 2001 Unix Tape Archive
They total about 80 MB. Once you have them, simply unpack them to '/usr/src' and '/usr/src/sys'. The latter is the kernel proper.
Once you have your source tree, you can start downloading the patches, and apply them. Usually, all the currently published patches are availble in a single file. For 3.0, it is there. After that, simply watch the patch page from time to time, to keep updated.
Patches are either applied to an application (in '/usr/src'), or to the kernel ( in '/usr/src/sys'). Since all kernel patches should be installed, the thing i do is to apply all the kernel patches in one session, then i recompile my kernel once.
The applications you don't use (e.g. 'X11', for example) don't have to be patched & recompiled.
The idea here is to create a unique fingerprint of each of your files at a point in time. Later on, when you suspect someone might have modified one of your files in a malicious way, you re-compute the fingerprints and compare with your previously stored set of fingerprints. Obviously you must be careful to encrypt the original set of fingerprints, or store them someplace safe.
The way to create the fingerprints is like this:
mtree -c -Ksha1digest -p / > fingerprint
Later on, to check your files against the fingerprint file, you simply do:
mtree -f fingerprint -p /
Of course, many files will be different (e.g. the log files, etc...). You will have to use your judgement in how to interpret the results. One thing is for sure: none of the basic operating system binary utilities should have changed, unless you did it yourself.