working from home this month

My last houses lease was up at the end of June, and the next house’s lease doesn’t start until August 2, so I’m stuck at home this month and that’s where I’m working from. I figured I’d save on rent and avoid moving more than I needed to. It’s also nice to be back here to take care of some things, but I do miss Bellingham during the summer.

ResTek’s been fairly smooth this summer. I haven’t implemented too many major changes yet (I can’t do things like repartition servers from remote…) but I did manage to switch our mail server from Qmail to a much, much cleaner Postfix setup. Qmail served us fairly well, but the way it was set up involved too many “moving parts” (most of which were used to filter spam). These included: ClamAV, simscan, SpamAssassin, some TLS+LDAP patches from Qmail (part of a port, fortunately).

I ended up doing away with the server-based spam filtering and instead enabled greylisting in the spamd setup on our OpenBSD firewalls. The number of spam messages we received per day went from around 150 to 5-10 just from the simple greylisting change, which took around 5 minutes. The whole process greatly reduced the complexity of our mail server and even impacted things like LDAP because we use LDAP to store mail delivery information. It had been at the back of my mind for months now; I’m glad I just went ahead and did it.

I announced on the forums today the existence of syweb.

I better get some sleep. I have a feeling John and/or Firass will be calling me in a few hours to ask why nothing on Dev is working….

Border Firewalling at ResTek

For those of you that weren’t aware, ResTek has a pair of machines acting as a border firewall. Both of the machines, hardware-wise, are the same and their configurations are close to identical as well. In this brief entry I will describe how they work, assuming the reader has zero understanding already.

First, a picture: http://www.flickr.com/photos/muskrat/2389614285/

A close look will reveal that the two 1U boxes sporting the OpenBSD and Puffy stickers are labeled “Firewall A” (top) and “Firewall B” (bottom).

Each of the firewalls has 4 Ethernet ports. Two of these are separate devices (fxp0 and em0 below), and the third and fourth are a dual-port PCI-X card. All of them are Intel-based cards. The interfaces associated with the devices are named as follows:

  • fxp0 – 100 mbps, connected directly to other firewall with crossover cable

  • em0 – currently unused

  • em1 – gigabit, “outside” (CARP)

  • em2 – gigabit, “inside” (CARP)

Because these two firewalls are on a critical path (between students and their internet), it’s very important that they are redundant. If we only had one, and it failed, there would be no internet connection for students until someone manually reconfigured the routes on the main router – this would mean hours of downtime at the very least every time something happened (including upgrades when the system needs to be rebooted)!

Common Address Redundancy Protocol (CARP)

CARP is a protocol written by the OpenBSD team (the firewalls are on the OpenBSD operating system, partly because of this incredibly useful protocol) to address this issue. From the official documentation:


CARP works by allowing a group of hosts on the same network segment to share an IP address. This group of hosts is referred to as a “redundancy group”. The redundancy group is assigned an IP address that is shared amongst the group members. Within the group, one host is designated the “master” and the rest as “backups”. The master host is the one that currently “holds” the shared IP; it responds to any traffic or ARP requests directed towards it.

In a simple setup like ours, one of the firewalls will be processing traffic passing between students and their internet at any given moment – whichever one doing that is referred to as the “master.” It advertises itself as master by sending out advertisements that the “backup” can see at a configurable interval. If ever the backup stops seeing these advertisements, thinking the master has failed or been shut down, it will “immediately” step in and take over.

Hopefully you noticed above that there were two interfaces (em2 and em1) referred to as “inside” and “outside”, respectively. This is just a way to describe which part of the path that network interface is facing. Consider the diagram below:

student --- (inside) em2 [firewall] em1 (outside) --- internet

A simple CARP firewall configuration will allow both firewalls to share one address on the inside, and another on the outside. The main router (to which the residence halls and firewalls are connected) will route traffic to these shared (CARP) addresses, rather than the unique addresses of either firewall. This way, the routes don’t have to change in the event of failure—the address is usually a fine route because usually at least one firewall will be up and running.

Up until now in the description, the firewalls probably don’t seem much like firewalls…

PF - The OpenBSD Packet Filter

PF is the OpenBSD packet filter (arguably the best packet filter/firewall software available today). It is part of the operating system itself, and it is responsible for deciding how to handle packets that it is configured to process. Like most packet filters, PF is configured through a configuration file (named pf.conf) that defines certain rules for how to handle different types of traffic. The rules are collectively known as a “ruleset.”

When a packet enters (or exits) the firewall, pf processes it. First, PF checks the packet against a list of existing connections—referred to as “states”. This is called a state table lookup. A “state” consists of: source address/port, destination address/port, and direction. If the packet is found to match an existing connection (and it is valid in the context of that connections current state, hence the name) it is passed. If no state match is found, the packet must be checked against the ruleset.

Most rules are very easy to read. Here are a few examples:

pass out quick from <firewalls>
block quick from any to <firewalls>
pass in on $ext_if from any to $servers

The packet is compared to the list of rules, and the last rule that matches (unless a special “quick” keyword is used in a rule), will determine how PF handles the packet. If it is “block”, it will be blocked. If it is “pass”, it will be passed. If no rule matches, the default action is to pass. The ruleset lookup is much slower than a state table lookup.

It is also important to note that, in our environment, traffic passing through the firewall is processed twice by PF (once on the “inside”, and again on the “outside”).

A primary way the firewalls are used at ResTek is to maintain a list of registered students on our network and pass their traffic, but not pass the traffic of a machine that has not been registered with us. Another way is to minimize incoming spam destined to our mail server, using OpenBSD’s spamd.

Obviously I won’t attempt to describe everything about PF, but I encourage curious readers to visit the OpenBSD documentation and learn about it.

Failover

Because state lookups are much faster (and we process a huge number of packets per second), we like to make use of them where possible. It’s possible to never create states by specifying “no state” in rules, but then the ruleset has to be checked for every single packet, and that’s much slower. In our environment, a state table lookup occurs around 40,000 times per second on average.

However, you might notice there is a possible problem with states. If the master is maintaining a list of all current states as connections pass through it, and then it fails, the backup will have no idea which packets are part of states and which aren’t. Obviously this would lead to interrupted connections where stateful filtering is in place.

OpenBSD developed “pfsync” to address this. Pfsync runs on both firewalls, and allows them to update each other on current states. So, the backup firewall, formerly blind about what connections are going through the master, would now be sent a list of updates to states. In other words, their state tables are synced at all times. If the master fails, the backup knows exactly how to handle existing connections. This is where the “fxp0” interface comes in. As said above, the two fxp0 interfaces are connected directly to each other using a crossover cable. Pfsync traffic is sent across this dedicated link.

Conclusions

The redundancy created by OpenBSD on the firewalls is extremely valuable and also extremely easy to configure. You can literally unplug the master and streaming audio/video won’t miss a beat as the backup takes over.

A few things to be aware of about our firewalls:

  • As for our policy, ResTek does not block ports. We recently removed the ones that used to be blocked. The main router still blocks a few ports, but we are working with the department that manages it to get that cleaned up. We do not feel that blocking ports is a worthwhile security practice in the majority of cases, and our role as an Internet Service Provider is not to police traffic in such a useless/potentially damaging way.
  • When traffic is denied by the firewall, it is not simply discarded. The firewall will send back the appropriate response. This is known as a “block policy” in PF. You can define “drop” (discard) or “return”. It is good practice to “return” (send back a response indicating that the connection was denied) to avoid confusion for people that are trying to troubleshoot. Our philosophy is that it is better to “return” than to “drop”.
  • Inbound connections to resident machines are not blocked. Now that most operating systems (Windows) ship with firewalls enabled by default, we don’t want to hinder your internet experience by trying to “protect” you. We find that usually it causes more problems than it solves, specifically for people trying to host games or whatever else. Some providers allow outbound connections, and inbound traffic associated with those connections, but drop inbound connections. We feel this practice causes more problems than it solves.
  • We do not use the firewalls to monitor what you do. We monitor how much traffic IP addresses are using to make sure nobody is taking up our limited bandwidth and making things slow for everyone else. We also keep an eye out for suspiciously high numbers of outbound e-mails (almost always an indication of a virus-infected machine spamming), but we do not monitor the e-mails themselves at all and look down on people that do.

Hope that clarifies some things!

Have a look at our graphs, specifically the “pf” layout, for some visuals.

LDAP group-based access in Apache 2 … and some other stuff

Because I am currently managing both Housing and ResTek servers (separate entities, similar needs), I’ve been trying to find a few ways to share resources between them. My manager also requested that the staff over at Housing be able to access the ResTek wiki (and maybe vise versa).

Thanks to former administrator Gordon, Housing servers were switched from SLES to FreeBSD, which is what most of our ResTek servers are. The setups now are really similar, with one exception being the fact that ResTek uses LDAP (PAM+NSS) for authentication and other things. Housing is still using local accounts because there hasn’t been a need to move to LDAP.

The goal was to add accounts for Housing employees into our ResTek LDAP directory, and then eventually share things like our wiki, Nagios, etc.

To accomplish this, I simply created another group (posixGroup) in our directory: cn=webteam. All of our ResTek employees have a primary group of cn=restek. All Housing “web team” members would have a primary group of ‘webteam.’

This seems simple enough, but there was one problem, and that was for special cases like myself, that needed to be in both groups (to access both resources). In other words, I needed a way to make myself a member of ‘webteam’ without it being a primary group. That is as simple as adding my short user name to the group’s entry as a memberUid attribute. So, we end up with something like the following (abbreviated):

Groups:
cn=restek,ou=Group,dc=restek,dc=wwu,dc=edu
gidNumber: 5000
memberUid: jonny

cn=webteam,ou=Group,dc=restek,dc=wwu,dc=edu
gidNumber: 4000
memberUid: kian
People:
uid=kian,ou=People,dc=restek,dc=wwu,dc=edu
gidNumber: 5000

uid=jonny,ou=People,dc=restek,dc=wwu,dc=edu
gidNumber: 4000

What does this result in? Kian’s primary group will be ‘restek’, and he will also be a member of ‘webteam’. Jonny’s primary group will be ‘webteam’, but he’ll be a member of the ‘restek’ group too.

Now, to allow Webteam Jonny into our Nagios page, the following can be added to Apache’s httpd.conf:

<directory "/usr/local/www/nagios/">
    Options All

    Order allow,deny
    Allow from all

    Include etc/apache22/ldap-auth-base.conf
    require valid-user
</directory>
ldap-auth-base.conf:
# Don't want people to be allowed to authenticate insecurely
SSLRequireSSL

AuthType Basic
AuthBasicProvider ldap
AuthName "ResTek Login"
AuthLDAPURL "ldap://ldap.restek.wwu.edu/ou=People,dc=restek,dc=wwu,dc=edu?uid??" TLS
AuthLDAPBindDN "cn=BINDUSER,dc=restek,dc=wwu,dc=edu"
AuthLDAPBindPassword SUPERSECRETPASSWORD
# group members are short names (uid), not full distinguished names
AuthLDAPGroupAttributeIsDN off
AuthLDAPGroupAttribute memberUid

In other words, any valid user will be allowed to log in. If we want to restrict it to members of the ‘restek’ group (primary OR secondary, we would do the following instead:

Include etc/apache22/ldap-auth-base.conf
require ldap-attribute gidNumber=5000
require ldap-group cn=restek,ou=Group

In other news, we’ve moved our IDS/monitoring tools off of our firewalls and onto a separate OpenBSD server. All of our WAN traffic is mirrored from the router onto the second interface of that server, where the monitoring tools listen. It’s helping reduce the CPU load on our firewalls a bit, and is also probably a better practice security-wise.

Another little Nagios plugin - check_carp

A little while back I created a small plugin to monitor CARP states on our firewalls and proxies. It’s very similar to check_pf but simpler since I mostly just use it to make sure I remember to reset advskew when I’m doing maintenance. Works on both OpenBSD 4.2 and FreeBSD 6.3 and FreeBSD 7. You can check it out here.

New Desktop

I finally built myself a new computer. So far I’m more than happy with it, and have just been configuring things how I like them and testing out a couple of games. I am, of course, afraid to get too involved in any games with the schedule I have lately…especially ones like World of Warcraft. Anyway it’s running one of the new(er) Intel Core 2 Duo E8400 Wolfendale processors and a pretty decent NVIDIA video card that happens to be gigantic. Case is an Antec Sonata III and I’m happy with it.

One thing I’m really impressed with is the onboard sound quality. My old computer was about 6-7 years old custom-built (Athlon XP 1.6GHz, GeForce Ti-4400, EPoX 8KHA+ motherboard, etc.), so I really noticed a huge difference in the sound quality even with my low-quality speakers. And, now, I don’t have to close every single application that is open when I want to play a game.

The plan is to turn my old box into a fileserver for my dad’s business.

Other than that, my schedule has been super busy. I bought an organizer to replace my Moleskine pocket notebook to-do lists, and have been trying to keep on top of my tasks.

phpBB3, awk, and books

phpBB 3 was finally released and I upgraded the ResTek/WWU Student Forums the other night. Luckily an upgrade (2.x -> 3.0) script is provided. After all of the tables are created during the guided setup process, there is also a tab for upgrading an old site. It basically just imports data from your old phpBB2 instance into the new tables and copies over avatars, etc. directly.

Anyway the process is very simple but when setting a table prefix (so you can potentially use one database for multiple forums), I set the prefix without the trailing underscore. So, all of my tables were incorrectly named things like forumsbbcodes, forumsbanlist, etc. There are about 40 tables named like this, and I didn’t want to rename them all by hand, so I came up with the list and used this short Awk script:

kian@alvis:~/testing
> awk '{ str = $0
         sub(/forums/, "forums_", str)
         print "RENAME TABLE", $0, "TO", str, ";"
       }' tables.txt

That will create the SQL commands necessary to correctly rename each of the tables, e.g.:

RENAME TABLE forumsthis_that TO forums_this_that ;

All that is needed next is to execute these commands using mysql(1) or an interface of choice.

For Christmas books this year, I will be reading The Plague, Three Cups of Tea, and Julius Winsome (title is spelled incorrectly on the spine!). I also got a subscription to National Geographic, so I’ll be reading those as they arrive. I still need to finish The Brothers Karamazov. I’m still trying to completely understand the last two chapters I read: Rebellion and especially The Grand Inquisitor. Dostoyevsky was clearly a genius.

new logo

What could be more productive during Finals Week than creating a new Planet ResTek logo in Photoshop… Oh that’s right, nothing.

World of Warcraft PacketShaper rules

I’ve updated the list of World of Warcraft servers described in an earlier post. There is a built-in World of Warcraft class in PacketWise, so I don’t really advise using this unless the detection doesn’t seem to be working (I’d be curious to hear results).

I don’t know how often these addresses change or if they’re even correct ;)

Anyway, here is the World of Warcraft server list and the PacketShaper CMD script.

IMPORTANT: The PacketShaper command script isn’t tested because our shaper is currently offline. Use at your own risk.

Simplifying mass IP address changes

For those that aren’t aware, ResTek is switching to a new internet provider, which also involves changing to a new IP address space. ARIN allocated us 67.201.192.0/18 (~16,000 hosts), which is awesome. Fortunately, we recently resubnetted our existing network in the 66.165.0.0/19 address space, and that involved moving the servers and networking equipment to their own subnets. We decided to preserve much of that order in this move, so a lot of the changes involved simply replacing octets 1-3 of our server IP addresses with the new ones. A job for sed!

I decided to create a very simple script to make the cutover easier, and also make sure that it would be possible to switch back to the old configuration files if something went awry.

The script is simple and has 3 modes:

  1. copy a list of files to new/ and old/ for editing

  2. install the new set

  3. revert to the old set

[kian@alvis ~/ipswitch]$ ls
alvis.lst       new             old             switch.sh

The ‘alvis.lst’ file is simply a file containing a list of files that are going to change between the two sets.

First, we backup all of the current files into two places—one will be the original set, the other will be changed.

[kian@alvis ~/ipswitch]$ sudo sh switch.sh grab
Password:
/etc/rc.conf -> old/rc.conf
/etc/rc.conf -> new/rc.conf
/etc/hosts -> old/hosts
/etc/hosts -> new/hosts
/etc/resolv.conf -> old/resolv.conf
/etc/resolv.conf -> new/resolv.conf
/etc/pf.conf -> old/pf.conf
/etc/pf.conf -> new/pf.conf
/usr/local/etc/apache22/httpd.conf -> old/httpd.conf
/usr/local/etc/apache22/httpd.conf -> new/httpd.conf
/usr/local/etc/apache22/httpd.conf-chroot -> old/httpd.conf-chroot
/usr/local/etc/apache22/httpd.conf-chroot -> new/httpd.conf-chroot
/usr/local/etc/apache22/httpd.conf-nochroot -> old/httpd.conf-nochroot
/usr/local/etc/apache22/httpd.conf-nochroot -> new/httpd.conf-nochroot
/usr/local/etc/nrpe.cfg -> old/nrpe.cfg
/usr/local/etc/nrpe.cfg -> new/nrpe.cfg
/etc/ssh/sshd_config -> old/sshd_config
/etc/ssh/sshd_config -> new/sshd_config

Next, we modify the files in the “new” directory. It could be as simple as:

[kian@alvis ~/ipswitch/new]$ sed -i .bak -e 's/66.165.31/67.201.255/g' *

...but in our case it involved a little more work (though sed was used!).

Now I could simply install the new set while preserving the originals in “old”:

[kian@alvis ~/ipswitch]$ sudo sh switch.sh new
Installing new configs...
rc.conf -> /etc/rc.conf
hosts -> /etc/hosts
resolv.conf -> /etc/resolv.conf
pf.conf -> /etc/pf.conf
httpd.conf -> /usr/local/etc/apache22/httpd.conf
httpd.conf-chroot -> /usr/local/etc/apache22/httpd.conf-chroot
httpd.conf-nochroot -> /usr/local/etc/apache22/httpd.conf-nochroot
modsecurity_crs_60_custom.conf -> /usr/local/etc/apache22/Includes/mod_security2/modsecurity_crs_60_custom.conf
nrpe.cfg -> /usr/local/etc/nrpe.cfg
sshd_config -> /etc/ssh/sshd_config
[kian@alvis ~/ipswitch]$

Useful to have on each server, in our case. It allows you to avoid the error-prone way of simply copying an original to file.bak.tmp.foo and restarting…

Here it is.

Server Admin. vs. Tech Innovator/Special Projects (mspaint style)

Yesterday’s quote of the day:


i was pinging it to check latency, and suddenly it did this … Destination Host Unreachable

I decided to use MS Paint last night. While I was feeling creative, I painted the normal interaction between our server administrator and tech innovator/special projects guy.

At ResTek, our group chemistry is unmatched, but so we get a lot done :)

Here’s to our new internet connection. :)

Server Admin vs. Tech Innovator/Special Projects