May 2004 Archives

!!!WARNING!!!
This HOWTO - which should be renamed the "qmail quick, uninformed install guide" is horribly outdated. Please see lifewithqmail.org for better and nore up-to-date instructions or help!
SF 2005-11-30

(with support for vqadmin, qmailadmin and sqwebmail)

Steven N. Fettig
See Creative Commons Copyright for copyright details.
Rev 1: 14 May 2004

This howto is very similar to the one I started translating a few years back from Oliver Lehman and is intended for people running FreeBSD 4.9 and up (it may work on lower versions, but I have not tested it and make no implied guarantee that it will work either way). I have found that a number of items in Oliver's howto didn't fit my needs, so I altered the HOWTO accordingly. Firstly, I don't totally understand the ssl certs, so I have not taken the time to make sure they are compiled/created correctly. The qmail and patchset I install includes the tls version of qmail and the courier-imap version I install will handle connections over ssl. I have installed and reinstalled various versions of qmail, vpopmail and courier-imap on the test server and have hosed certain portions of the installation. I have things working well, however, for new domains and intend to do a rebuild with the ssl support.

Assumptions:
- You have a fair grasp of FreeBSD and how to move around the filesystem.
- You can install services/programs via the ports.
- You understand that incorrectly configured email systems can be used as spam gateways - if you don't understand how to test and make sure you have NOT set up an open relay, STOP. Do us all a favor and learn/test/learn before placing a server on the net that is open to spammers.
- I don't know what I am doing half of the time.
- You may need to modify parts of these instructions to get this service combination to work on your machine.
- The smtp-auth patch will only work with vpopmail 5.4 and above.
- I use /usr/ports/distfiles/qmail/ as my SRC directory for compiling and installing software not installed via the ports.

Chapter 1 - Installation of Services

1.1 qmail

Install netqmail-1.05-tls with smtpauth patch (installation instructions are right in the text of the beginning of the patch):


cd /usr/ports/distfiles/qmail
fetch http://qmail.org/netqmail-1.05.tar.gz
fetch http://shupp.org/patches/netqmail-1.05-tls-smtpauth-20040207.patch
tar -xzvf netqmail-1.05.tar.gz
cd netqmail-1.05
./collate.sh
patch -p0 < ../netqmail-1.05-tls-smtpauth-20040207.patch
cd netqmail-1.05
mkdir /var/qmail
pw groupadd nofiles
pw useradd alias -g nofiles -d /var/qmail/alias -s /nonexistent
pw useradd qmaild -g nofiles -d /var/qmail -s /nonexistent
pw useradd qmaill -g nofiles -d /var/qmail -s /nonexistent
pw useradd qmailp -g nofiles -d /var/qmail -s /nonexistent
pw groupadd qmail
pw useradd qmailq -g qmail -d /var/qmail -s /nonexistent
pw useradd qmailr -g qmail -d /var/qmail -s /nonexistent
pw useradd qmails -g qmail -d /var/qmail -s /nonexistent
make
make setup check
rm /usr/sbin/sendmail
cp /var/qmail/bin/sendmail /usr/sbin/sendmail

Set sendmail_enable="YES" to sendmail_sendmail="NONE" in /etc/rc.conf

1.2 ucspi-tcp

ucspi-tcp is used so that use of inetd can be avoided in setting up tcp port connections. There are plenty of resources showing why people don't like inetd and I suggest you look for them on google.com.
There is a diff patch applied to rblsmtpd.c from Alan Curry so that "rblsmtpd works with A records." Same as Oliver's instructions:


cd /usr/ports/sysutils/ucspi-tcp
make extract
cd `make -VWRKDIR`
fetch http://www.qmail.org/ucspi-rss.diff
patch rm ucspi-rss.diff
cd -
make install clean

1.3 daemontools

Daemontools is used to start and log the services we are going to set up. In our case, daemontools only watches qmail, pop3 services and the smtp services. Courier-imap is started via sh scripts. I, personally, like daemontools, but people have made good arguments for and against its use. DJB is a person that people seem to love to hate or love to love, so some of the comments pro or contra are juvenile. So, decide for yourself whether you want to employ daemontools for other items.


cd /usr/ports/sysutils/daemontools
make all install clean
cd /usr/local/etc/rc.d
mv svscan.sh.sample 0svscan.sh
mkdir /var/service

1.4 vpopmail

vpopmail administers virtual domains. This allows you to set up multiple domains on one host and has many tools to go along with it (also from vpopmail's makers, inter7) that allow you to add and remove users/domains/etc. with very little effort.

cd /usr/ports/mail/vpopmail make all install clean

1.5 courier-imap

courier-imap is the service used to allow for imap access to email accounts. It is also an inter7 invention.

cd /usr/ports/mail/courier-imap make -DWITH_VPOPMAIL -DWITH_OPENSSL_PORT all install clean

If you want to make the ssl certificates you need to follow Oliver's instructions:


sh -c ' \
for i in imapd imapd-ssl imapd.cnf pop3d pop3d-ssl pop3d.cnf ; do \
cp /usr/local/etc/courier-imap/$i.dist /usr/local/etc/courier-imap/$i ; \
done'

/usr/local/share/courier-imap/mkpop3dcert
/usr/local/share/courier-imap/mkimapdcert


Like I said in the beginning - I don't understand enough about ssl to know whether this is the *right thing* or whether it will give you a false sense of security if connecting to imap and pop3 via ssl.

1.6 ezmlm-idx

If you want to enable your server for mailing lists, ezmlm-idx makes this very, very easy.

cd /usr/ports/mail/ezmlm-idx make all install clean cp /usr/local/etc/ezmlm/ezmlmrc.sample /usr/local/etc/ezmlm/ezmlmrc

1.7 qmail-conf

From Tetsu Ushijima's website:


What is it?
qmail-conf is a collection of tools for setting up various qmail services. They are like *-conf programs in djbdns.

With qmail-conf, for example, setting up a minimal SMTP service takes the following four steps:

     qmail-smtpd-conf qmaild qmaill /var/qmail/service/smtpd
     cd /var/qmail/service/smtpd
     make
     ln -s /var/qmail/service/smtpd /service

qmail-conf assumes that (recent versions of) daemontools and ucspi-tcp have already been installed. It also assumes that svscan is already running.

qmail-conf tries to provide reasonable defaults: it avoids DNS reverse lookups; it avoids IDENT lookups; it lets TCP connection attempts be logged with multilog; and for POP3 and QMQP, connection attempts are denied unless you explicitly authorize your clients.

qmail-conf reduces the need for editing ./run scripts by using envdir. For example, to raise the concurrency limit for the SMTP connection to 100, all you have to do is:

     echo 100 > /service/smtpd/env/CONCURRENCY
     svc -t /service/smtpd

qmail-conf does not help you set up /var/qmail/alias, /var/qmail/control, /var/qmail/rc, and /var/qmail/users.

We will end up modifying the vanilla smtp run script so that we can enable smtp-auth. BUT, these -conf scripts have made the creation of run scripts for qmail extremely easy.

cd /usr/ports/distfiles/qmail
fetch http://www.din.or.jp/~ushijima/qmail-conf/qmail-conf-0.60.tar.gz
fetch http://cr.yp.to/djbdns/djbdns-1.05.tar.gz
tar -xzf qmail-conf-0.60.tar.gz
cd qmail-conf-0.60
tar -xzf ../djbdns-1.05.tar.gz
make -f Makefile.ini
make
make setup check

Chapter 2 - Configuration of start scripts, vpopmail, smtp-auth and courier-imap

2.1 vpopmail crontab script

vpopmail is automatically sets up a selective relay when a user authenticates via pop3. We need to make sure that the tcp.smtp under /usr/local/vpopmail/etc is "cleaned" every 40 minutes.
Add the following line to your favorite root, vpopmail OR system crontab:


40 * * * * /usr/local/vpopmail/bin/clearopensmtp >/dev/null 2>&1

if adding to the system crontab:

40 * * * * root /usr/local/vpopmail/bin/clearopensmtp >/dev/null 2>&1

2.2 Make the courier-imap startup scripts readable

The courier-imap port sets up install scripts in /usr/local/etc/rc.d that aren't yet readable at boot time because they are appended by the name .sample. We are simply going to copy the default the same name while removing the .sample ending.

mv /usr/local/etc/rc.d/courier-imap-imapd-ssl.sh.sample /usr/local/etc/rc.d/courier-imap-imapd-ssl.sh

mv /usr/local/etc/rc.d/courier-imap-imapd.sh.sample /usr/local/etc/rc.d/courier-imap-imapd.sh

mv /usr/local/etc/rc.d/courier-imap-pop3d-ssl.sh.sample /usr/local/etc/rc.d/courier-imap-pop3d-ssl.sh

cp /usr/local/etc/courier-imap/authdaemonrc.dist /usr/local/etc/courier-imap/authdaemonrc

You should take a quick look at the authdaemonrc file and take note of the configuration changes you can make.

To increase the number of concurrent sessions per IP, change the default value of imapd under /usr/local/etc/courier-imap


cd /usr/local/etc/courier-imap
ee imapd

Look through the file for MAXPERIP and change to a value you think will be reasonable for your needs. I need to be able to access 10 plus accounts at any given time, so I set mine to a high number of 20. You may not need to change this value, but it might become important if you find your clients timing out all the time.

2.3 Create the qmail control files and start scripts

We will start by creating the control files and dot postmaster files:


touch /var/qmail/alias/.qmail-postmaster \
/var/qmail/alias/.qmail-root \
/var/qmail/alias/.qmail-mailer-daemon
echo "" > /var/qmail/control/locals
hostname > /var/qmail/control/me
hostname | sed "s/`hostname -s`.//g" > /var/qmail/control/defaultdomain
hostname | sed "s/`hostname -s`.//g" > /var/qmail/control/plusdomain

We also need to make sure that the rcpthosts file is created so that the smtp server does not act as an open relay:


touch /var/qmail/control/rcpthosts

The following commands are almost identical to Oliver's, but I do not want to go though the hack to set up the selective relaying through vpopmail because I want to use auth-smtp. Also, we are going to edit the qmail-smtp run file afterwards. I still go through this process because I am not a good script writer and I like to see what someone else thinks is going to be a good run script.


/var/qmail/bin/qmail-pop3d-conf /usr/local/vpopmail/bin/vchkpw \
qmaill /var/qmail/service/pop3d
cd /var/qmail/service/pop3d/
echo ":allow" >tcp
echo "200" > env/CONCURRENCY
make

/var/qmail/bin/qmail-smtpd-conf qmaild qmaill /var/qmail/service/smtpd
cd /var/qmail/service/smtpd/
echo "200" > env/CONCURRENCY

echo '#!/bin/sh' >/var/qmail/rc
echo 'exec env - PATH="/var/qmail/bin:$PATH" \' >>/var/qmail/rc
echo 'qmail-start ./Maildir/ /usr/local/bin/multilog t /var/log/qmail qmaill' >>/var/qmail/rc
chmod 755 /var/qmail/rc
/var/qmail/bin/qmail-delivery-conf qmaill /var/qmail/service/qmail
mkdir /var/log/qmail
chmod 750 /var/log/qmail
chown qmaill /var/log/qmail

Now, go into /var/qmail/service/smtpd and we will change the run file:


cd /var/qmail/service/smtpd/
mv run run.orig
ee run

Copy the following into run:

#!/bin/sh

exec /usr/local/bin/softlimit -m 4000000 tcpserver -H -l0 -R -c 512 -x \
/usr/local/vpopmail/etc/tcp.smtp.cdb -u VCHKPWUID -g VCHKPWGID 0 smtp \
/var/qmail/bin/qmail-smtpd mail.yourdomain.tld \
/usr/local/vpopmail/bin/vchkpw /usr/bin/true &


and replace VCHKPWUID and VCHKPWGID with the appropriate UID and GID for vchkpw. Also replace mail.yourdomain.tld with your domain or fdqn of the server.

Now, create symlinks to the /var/service/ directory for qmail, pop3d and smtpd


ln -s /var/qmail/service/pop3d /var/service/pop3d
ln -s /var/qmail/service/smtpd /var/service/smtpd
ln -s /var/qmail/service/qmail /var/service/qmail

There are a number of ways you can proceed. Either start each of the start scripts you have installed under /usr/local/etc/rc.d manually or reboot the system. The next chapter covers the basics of adding and removing domains/users and mailing lists.

3. Administration of vpopmail and ezmlm-idx

3.1 Adding/Removing Domains/Users

vpopmail offers a very easy interface with which you can add and remove both domains and users on the fly. The commands to do this are found under /usr/local/vpopmail/bin. If you run the commands directly with no options, the command will list the available switches and options that must be used with that command. Inter7's documentation is also a good source for information.

Add a domain:


vadddomain domain.tld

Add a user to that domain:

vadduser user@domain.tld

Create an alias domain:

vaddaliasdomain alias.tld domain.tld

Change a user's password:

vchangepw user@domain.tld

Delete a user:

vdeluser user@domain.tld

Delete domain:

vdeldomain domain.tld

There are also ways to specify directories other than the default (/usr/local/vpopmail/domains) to store the virtual domains and user files. I have found, however, that this isn't necessarily a better way to manage security because the domain has to still have vpopmail:vchkpw read/write priviledges, so until I can find a way to give the user AND vpopmail access to the domain information/users and not others, I see no reason to use this option.

3.2 ezmlm-idx mailing lists

These set of commands are taken directly from Oliver's howto - I have yet to use mailing lists although I have always had ezmlm-idx installed.
To set up a moderated list (TEST) whose moderator can be reached at user1@domain1.tld, do the following:


cd /usr/local/vpopmail/domains
ezmlm-make -rdug -5 user1@domain1.tld /usr/local/vpopmail/domains/domain1.tld/TEST \
     /usr/local/vpopmail/domains/domain1.tld/.qmail-TEST TEST domain1.tld
ezmlm-sub /usr/local/vpopmail/domains/domain1.tld/TEST user1@domain1.tld
ezmlm-sub /usr/local/vpopmail/domains/domain1.tld/TEST/digest user1@domain1.tld
ezmlm-sub /usr/local/vpopmail/domains/domain1.tld/TEST/mod user1@domain1.tld
chown -h vpopmail.vchkpw ./domain1.tld/.qmail-TEST*
chown -R vpopmail.vchkpw ./domain1.tld/TEST

3.3 Using SMTP-AUTH

The whole purpose for rewriting this howto was that I wanted to include smtp-auth into the mix. I have constantly had troubles with the courier-imap hack that allowed for selective relaying, so I decided a better way to open up the smtp server for relaying for my clients was to set up smtp-auth. In order to use smtp-auth (especially for those using imap folders and cannot open the smtp relay via the old hack), you simply need to set your email client to use smtp-auth with one of the usernames and passwords of one of the domains you have installed. Remember, a valid username is user@domain.tld and not simply user. I use Mozilla Thunderbird as my main email client these days and have not had any problems using smtp-auth. The only issue I have is that it slows the sending of emails because the authentication adds a delay to being able to send out the email. I would rather have the security, however - and perhaps it is an issue that I will find some solution to at a later time.

4. Web Administration

This is the section that I have been long waiting to work on. Now that I have a need for it - i.e. my own startup ISP that needs some remote-management interfaces - I have worked to get vqadmin, qmailadmin and sqwebmail working (all from inter7, of course).

I installed apache13-modssl from the ports and did do anything special to get it running other than making sure the ssl service started so that I could test running all of the above services via ssl.

4.1 Install apache13-modssl

cd /usr/ports/www/apache13-modssl make all install clean

To start apache13 with ssl activated:


apachectl startssl

I have had problems getting apache and ssl to start with the installed start script (/usr/local/etc/rc.d/apache.sh) and have yet to take the time to look further into the fact that neither apache nor the ssl portion of apache will start automatically once the server has been rebooted.

4.2 Install vqadmin

cd /usr/ports/mail/vqadmin
Make sure the destination directory for the cgi's is a place where you want them. Otherwise, modify your options or the Makefile accordingly. I set everything to install to /usr/local/www/cgi-bin-dist. While I know this may not be the proper way to do things, I wanted to have all of the web administration tools installed to the same directory so that I could first make sure they work. I will eventually modify this to fit my needs.
make all install clean
Then make sure you follow the instructions on setting up .htaccess password protection to the directory where you will access vqadmin (it will not work without password restriction). You also need to modify the vqadmin.acl file to set up access permissions for your users. In my case, I only added myself to the passwd file (which .htaccess points to) and gave myself full permissions under vqadmin.acl.

4.3 Install qmailadmin

cd /usr/ports/mail/qmailadmin make all install clean

4.4 Install sqwebmail

I modified this installation a little so that it always runs over the ssl server. Although email is inherently insecure and open in nature, at least the web clients cannot be directly monitored.

cd /usr/ports/mail/sqwebmail make -DWITH_VCHKPW -DWITH_HTTPS all install clean cp /usr/local/share/sqwebmail/authdaemonrc.dist \     /usr/local/share/sqwebmail/authdaemonrc
Add the following to your root or system crontab:
40 * * * * /usr/local/share/sqwebmail/cleancache.pl >/dev/null 2>&1
Again, if you are adding it to the system crontab:
40 * * * * root /usr/local/share/sqwebmail/cleancache.pl >/dev/null 2>&1

You need to use the run scripts installed in /usr/local/etc/rc.d to test sqwebmail or reboot the machine.

There you have it... You should have a fully functioning email server.

Written by Steven N. Fettig
Rev. 1.1 - 8 May 2004
(See Creative Commons Copyright in right pane for copy restrictions)
Materials:
IBM Small Form Factor Workstation (Overkill)
Integrated Intel 10/100 NIC
Sangoma Dual CSU/DSU T1 PCI Card

Preface: As part of the Darien-WiFi project, I spent the past two weeks trying to install a router for our two T1's from Global Crossing. I had originally intended to use FreeBSD as the base system. What I found was that there was no (documentation showing a) way to do native load balancing across both T1's. The Sangoma Wanpipe drivers for Linux were able to do load balancing using the TEQL module (used in firewall QoS). Although an open supporter of what works - which can often be Linux - there was no way that I was going to use Linux on my router considering that I have had much, much more experience with FreeBSD and am familiar with locking it down for security uses. With quite a bit of Google digging, I found that OpenBSD'spf was not only capable of doing load balancing, but a whole array of items that I had spent much time learning how to do with ipfw on FreeBSD. After working until 10:30 pm on a Wednesday, I decided not to try OpenBSD, but instead opted for the pf port for FreeBSD. At about 1 am the next morning, I found out that not only would pf not load on a pre-5.0 machine (I know, I know - it says so in the docs, but I'm not enough of a kernel hacker to understand that it really wouldn't work), but I also couldn't get the Wanpipe drivers to load on the FreeBSD 5.2.1 system I just installed. By this time, I had been in contact with the Wanpipe BSD developer, Alex Feldman, and found that he hadn't thoroughly tested the driver install packages on 5.1 + and he asked me to wait for him to do his work. (He was extremely helpful - if you continue reading, you will find that I found more than one helpful soul through this whole process.) Instead of waiting, though - I had already spent enough wasted time on this project (which might have been completely avoided by using a Cisco Router with dual CSU/DSU's)* - I decided to dive into OpenBSD for the first time. I thought, with all of the structural similarities, it shouldn't be that difficult to acclimate myself to OpenBSD's peculiarities. So, here are basic instructions as to how I was able to get load balancing to work using the Sangoma card and pf on OpenBSD.

Instructions:
It happens that the University of Wisconsin - Madison runs an OpenBSD mirror. I downloaded the 3.4 boot iso from http://mirror.cs.wisc.edu/pub/mirrors/OpenBSD/3.4/i386/ on my OS X workstation:


wget http://mirror.cs.wisc.edu/pub/mirrors/OpenBSD/3.4/i386/cd34.iso

Using DiskTools, I burned the bootable iso image to CD. There are a slew of tools out there to burn ISO's to CD. I assume that if you are reading how to configure a custom workstation/server to be your router, that you know how to burn a CD. I put the CD in my future router and booted the machine.
I was careful to follow the install instructions at:

Some people have complained that FreeBSD's install procedure was difficult... well, they obviously have not tried to install OpenBSD. This is not to say that I found it all too difficult - I'm neither afraid of a command line, nor am I worried if I hose the system - I can rebuild it, right? I learn best through trial-and-error anyway. This was one time, however, that I was able to get the base system installed without a hitch. Well, that is not entirely true - I tried to do a base install on a system with a Broadcom Gigabit NIC and could never get the NIC to activate during the install. Perhaps had I read the supported hardware information on the main site, I would have found that support for the NIC needs to be added via a custom kernel. I had another machine waiting idly by to get used - with an onboard Intel 10/100 NIC (supported by the generic kernel) - and went through the same procedure again.
Because I had not yet received the CD's I purchased (c'mon - support the open source projects you use!), I installed from the UW-Madison http server.
After choosing the install source, I selected the following filesets (in FreeBSD lingo, I suppose this is base packages):

The following sets are available. Enter a filename, 'all' to select all the sets, or 'done'. You may de-select a set by prepending a '-' to its name.
      [X] bsd
      [   ] bsd.rd
      [X] base34.tgz
      [X] etc34.tgz
      [   ] misc34.tgz
      [X] comp34.tgz
      [X] man34.tgz
      [   ] game34.tgz
      [   ] xbase34.tgz
      [   ] xshare34.tgz
      [   ] xfont34.tgz
      [   ] xserv34.tgz

There are a few more items that need to be configured after the appropriate distributions have been downloaded. Again, follow the install FAQ for assistance. I would take more time to outline how to install your OpenBSD system, but the FAQ provides an amazingly detailed explanation of the installation procedure. It would be wrong of me to provide another explanation when it is laid out so well in the OpenBSD documentation.
Since I had already physically installed the Sangoma card, I rebooted the system and started to install the drivers and configure the T1's (according to the settings that Global Crossing is using). I downloaded the Wanpipe drivers and software:

# wget ftp://ftp.sangoma.com/OpenBSD/current_wanpipe/wanpipe-obsd-1.5.2-b2.tgz

I took care to follow the installation instructions given to us by Sangoma and simply ran:

# pkg_add ./wanpipe-obsd-1.5.2-b2.tgz

I had the install script do all the defaults - install drivers, add support to kernel, install startup scripts, etc. Everything went off without a hitch. When I had originally tried the installation on the pre 5.x FreeBSD system, the compilation of the drivers failed. I have yet to test the Wanpipe installation on OpenBSD 3.5, so I can't say whether it works or not. Due to the stability of OpenBSD, I imagine the packages will install without any problems as they did on my 3.4 system.
Again, following instructions that come with the Sangoma card, I configured the T1's.

# /usr/sbin/wancfg

This part requires that you have pertinent protocol and IP information from your provider.
Sidenote: I must say that Global Crossing is amazing. Their Circuit Turn-up staff was amazingly helpful. Through this whole ordeal, a gentleman named John Brox helped me out and was patient with my insistence on doing a custom install - I say patient because I initially was not able to even bring up the circuits with a box I had intended to use (a Eden 500 VIA mini-itx machine), as the ethernet interface caused the circuits to cycle up and down at weird intervals. I don't know if this was a problem with the motherboard itself or with the VIA ethernet interface. I have yet to do the same install on another VIA mini-itx based system, so I don't know. He was more than willing to help me make sure the circuit was up for good before turning it over to the monitoring group.
I haven't worked on routers in years and considering that, not only does Sangoma make the circuit configuration easy, but Global Crossing made the circuit turn-up a breeze.
On to the actual configuration of the firewall and load balancing. The Wanpipe drivers give you two interfaces to work with (once the T1's have been enabled). The last line in wanrouter.rc (in /etc/wanpipe) should read:

WAN_DEVICES="wanpipe1 wanpipe2"

so that both lines are enabled when the machine is rebooted. If you have not rebooted the machine, you can start the wanpipes by (assuming you configured wanpipe1 and wanpipe2):

# wanrouter start wanpipe1
# wanrouter start wanpipe2

After starting the circuits, running

# ifconfig -A

gives you:

wpachdlc0: flags=51 mtu 1500
     inet 22.109.101.234 --> 22.109.101.233 netmask 0xfffffffc
wpbchdlc0: flags=51 mtu 1500
     inet 22.222.9.162 --> 22.222.9.161 netmask 0xfffffffc

at the end.
You also need to make sure that your machine is set up to act as a gateway. Straight from the FAQ: http://www.openbsd.org/faq/faq6.html

The GENERIC kernel already has the ability to allow IP Forwarding, but needs to be turned on. You should do this using the sysctl(8) utility. To change this permanently you should edit the file /etc/sysctl.conf to allow for IP Forwarding. To do so add this line in that configuration file.

net.inet.ip.forwarding=1

My internal ethernet interface (fxp0) was set as 24.192.154.1 - the beginning of my address block available for use. At first - just to try the load balancing - I modified the rules at http://openbsd.org/faq/pf/pools.html#outgoing for my interface:

lan_net = "24.192.154.1/24"
int_if  = "fxp0"
ext_if1 = "wpachdlc0"
ext_if2 = "wpbchdlc0"
ext_gw1 = "22.109.101.233"
ext_gw2 = "22.222.9.161"

so that the whole pf.conf looked like:

# define the interfaces
lan_net = "24.192.154.1/24"
int_if  = "fxp0"
ext_if1 = "wpachdlc0"
ext_if2 = "wpbchdlc0"
ext_gw1 = "22.109.101.233"
ext_gw2 = "22.222.9.161"

# nat outgoing connections on each internet interface
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)

# default deny
# I disabled these rules because we are in the testing phase - i.e. I am not yet using this as a real firewall - do not forget to re-enable these rules!
#block in from any to any
#block out from any to any

# pass all outgoing packets on internal interface
pass out on $int_if from any to $lan_net
# pass in quick any packets destined for the gateway itself
pass in quick on $int_if from $lan_net to $int_if
# load balance outgoing tcp traffic from internal network.
pass in on $int_if route-to \
{ ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
proto tcp from $lan_net to any flags S/SA modulate state
# load balance outgoing udp and icmp traffic from internal network
pass in on $int_if route-to \
{ ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
proto { udp, icmp } from $lan_net to any keep state

# general "pass out" rules for external interfaces
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state

# route packets from any IPs on $ext_if1 to $ext_gw1 and the same for
# $ext_if2 and $ext_gw2
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any


At this point, I was able to ping out of both interfaces, ping beyond the gateway, ping internally, etc. So, I set up a client behind the firewall and ran speed tests. Lo and behold, I was getting load balancing on the inbound (vis a vis Global Crossing's router configuration - it equally passes packets down both pipes), but it did not look like it was working on the outbound. It was about 12 am by this time and I was simply happy to see the OpenBSD machine working with the T1's and everything being pingable. Plus, John was gone by this time. I decided to call it quits and start again in the morning.
I woke up still puzzled as to why I couldn't get load balancing on the outbound route to work - theoretically, I had everything configured correctly! I called John and asked him if he could take a look at packet counts while I was running the bandwidth tests. After running a few tests, we found that the outbound were indeed being passed across both interfaces, but for some reason the bandwidth tests were not showing that. So, I decided to try to run more than one bandwidth test at once to see if I could fill up the pipes with more data. After getting my timing right (I kept starting one test well before the other), we were able to show that both pipes were indeed being load balanced, but for whatever reason, the speed tests would "sense" a limit at the 1 T1 barrier. Running multiple speed tests showed that just as much bandwidth was available down as it was up - i.e. just under 3 mbit/s. John was able to confirm that data was being sent down both pipes - one being favored by about 2% over the other. We chalked this up to "imperfect" round-robin'ing and called it a day. To this day, I still have not been able to figure out why the speed tests show outbound limited by one T1, but I don't really care as long as my available outbound is really the two T1's. I'm sure a ttcp test would be a better measure of throughput, but I haven't had the time to run such tests and am content that things are working as advertised.
After closing the firewall by enabling the default deny rules, I started working on allowing inbound connections. I struggled quite a bit with ssh. So much so that I finally emailed the OpenBSD misc list. I never did get a response to my question - I never really expected to seeing as I doubted many people were trying to do what I was and I further figured that they would pass my query off as being that of someone who failed to read the manual. They were wrong... I read the manual over and over but was never able to wrap my head around setting up the rules such that I could pass ssh through after default denying everything (I did confirm that ssh worked without the firewall...) So, I set out to test this through trial-and-error. Finally, after 5 hrs of testing, I came up with:

pass log quick on { $int_if, $ext_if1, $ext_if2 } inet proto tcp from any to \
     any port 22 flags S/SA keep state

This was the culmination of so many combinations of pass etc. I feign to write them all down out of sheer embarrassment. How simple and elegant it ended up being...
There are a number of other ports I ended up opening. There are also a few clients behind the T1 who want their IP's completely open. I was able to accomplish all of this with the following ruleset:

# define the interfaces
lan_net = "24.192.154.1/24"
int_if  = "fxp0"
ext_if1 = "wpachdlc0"
ext_if2 = "wpbchdlc0"
ext_gw1 = "22.109.101.233"
ext_gw2 = "22.222.9.161"

# a few macros
icmp_types = "echoreq"

priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"

## define all of the open hosts
open_hosts = "{ 24.192.154.15, 24.192.154.9 }"

## define some servers
dns_servers = "{ 24.192.154.3, 24.192.154.6 }"
email_servers = "{ 24.192.154.21 }"
http_servers = "{ 24.192.154.11 }"
# scrub all
scrub in all

# default deny
block log all

# pass all on internal loop
pass quick on lo0 all

# block spoofing from external interfaces
block drop in log quick on { $ext_if1, $ext_if2 } from $priv_nets to any
block drop out log quick on { $ext_if1, $ext_if2 } from any to $priv_nets

# allow ssh
pass log quick on { $int_if, $ext_if1, $ext_if2 } inet proto tcp from any to \
    any port 22 flags S/SA keep state

# allow dns
pass quick on { $int_if, $ext_if1, $ext_if2 } inet proto udp from any to \
    $dns_servers port 53

# allow mail
pass quick on { $int_if, $ext_if1, $ext_if2 } inet proto tcp from any to \
    $email_servers port 25 flags S/SA keep state

# allow traffic to httpd servers
pass quick on { $int_if, $ext_if1, $ext_if2 } inet proto tcp from any to \
    $http_servers port 80 flags S/SA keep state

# define the non-firewalled hosts
pass quick on { $int_if, $ext_if1, $ext_if2 } inet proto tcp from any to \
    $open_hosts flags S/SA keep state
pass quick on { $int_if, $ext_if1, $ext_if2 } inet proto udp from any to \
    $open_hosts

# allow icmp
pass inet proto icmp all icmp-type $icmp_types keep state

# pass all outgoing packets on internal interface
pass out on $int_if from any to $lan_net

# pass in quick any packets destined for the gateway itself
pass in quick on $int_if from $lan_net to $int_if

# load balance tcp
pass in on $int_if route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto tcp from $lan_net to any flags S/SA modulate state

# load balance udp and icmp
pass in on $int_if route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto { udp, icmp } from $lan_net to any keep state

# general "pass out" rules for external interfaces
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state

# route packets on external interfaces through the appropriate
# gateway
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 \
     to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 \
    to any


I realize that these rules can be redundant and must be rewritten in a much more efficient manner. That is what I am in the middle of working on. I hope, though, that these will help guide you to set the firewall and routing rules for your needs.
Remaining Problems:
One other item that needs to be cleaned up is having the rules loaded after the T1 interfaces are activated at boot time. This process usually is finished 45-60 seconds after the machine is fully booted. This means that if there is a power failure or problem with the machine and it reboots, one has to physically re-set the default gateway and load the rules. I don't understand enough of OpenBSD to make this happen, but when I do, I'll tell you how it is done.

HTH,
Steve

* In between all of this, I had given up on using pf for load balancing because of what I had seen as problems with pf - I was mistaken at the time, but I was convinced the problem was with pf and not with what I was seeing. I unwrapped a brand new Cisco 1721 and two T1 interfaces from a box - my just in case box - and spent eight hours trying to get it working. Fortunately, I was never able to bring up the circuits with the Cisco. I say fortunately because I ended up back with the BSD box and got it working - what I wanted in the beginning.

About this Archive

This page is an archive of entries from May 2004 listed from newest to oldest.

April 2004 is the previous archive.

July 2004 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Contact

Steven N. Fettig
Delavan, WI - somewhere between Delavan & Darien: map link
Phone: +1 262 432 1704
Email: snfettig AT gmail.com
AIM/Yahoo/MSN/GoogleTalk-
Skype/twitter:
snfettig

Technorati

Technorati search

» Blogs that link here

Powered by Movable Type 4.21-en