Setting up BIND on the ALIX firewall

June 27, 2012

Setting up BIND is probably the part that took more thought than any other when building the firewall. This is not because of any particular technical challenges; rather, BIND is managed by a consortium and its doc is… voluminous.

In the end, I went with the default /var/named/etc/named.conf on the assumption that it would do the right thing. According to its comment, it does both “recursive and authoritative queries using one cache,” which is what I want.

There are four files that need to change:

  1. /etc/rc.conf
  2. /var/named/etc/named.conf
  3. /var/named/master/mydomain.net
  4. /var/name/master/mydomain.net.rev

The last two can be named anything, but I stuck with conventions as I saw them.

Warning
Unlike everything up to now, the BIND files live on /var/. In flashrd, /var gets unpacked at boot time into a RAM disk. So you need to save any changes you make somewhere else. Do not reboot until you’ve saved your changes! Ultimately, we’ll put these changes in /flash/var.tar so they get re-created when the device reboots.

/etc/rc.conf
To enable named, change:

named_flags=""

/var/named/etc/named.conf
I used the default named.conf, which is really just a copy of named-simple.conf.

I made one addition in the options section:

       forwarders { 8.8.8.8; };

This tells DNS to look for answers at the Google DNS server if it can’t find the answer on the local DNS server. (Actually, I put a few DNS servers that were specific to my ISP, but the Google server will work too.)

I also made a few changes near the end:

// Master zones
//
zone "mydomain.net" {
        type master;
        file "master/mydomain.net";
};

// Reverse mappings for mydomain.net domain
zone "150.168.192.in-addr.arpa" in {
     type master;
     file "master/mydomain.net.rev";
};

This tells named to look in /var/named/master/mydomain.net for mappings of mydomain.net, and to look in /var/named/master/mydomain.net.rev for mappings of 192.168.150.*.

/var/named/master/mydomain.net
Here’s my mydomain.net:

mydomain.net. IN SOA firewall.mydomain.net. myemail.yahoo.com. (
     1          ; Serial
     10800      ; Refresh after 3 hours
     3600       ; Retry after 1 hour
     604800     ; Expire after 1 week
     86400 )    ; Minimum TTL of 1 day

;
; Name Servers
;
mydomain.net.  IN NS   firewall.mydomain.net.

;
; Host addresses
;
localhost.mydomain.net.        IN A    127.0.0.1
firewall.mydomain.net.         IN A    192.168.150.1
firesign.mydomain.net.         IN A    192.168.150.170
frantics.mydomain.net.         IN A    192.168.150.171
bundolo.mydomain.net.          IN A    192.168.150.172

The first bit says my domain is called mydomain.net. I’ve published my email as myemail@yahoo.com (but note the dot instead of the at sign there).

The next bit is serial number / expiration times. You’re supposed to bump up the serial number every time you edit, but I usually just kill and restart named.

After that, I say that the firewall will be the nameserver for the domain.

Next is the interesting bit: the mapping of host names to host addresses. They must all end in . because BIND requires it. It’s very easy to miss a . in your config file and be confused about why things aren’t working.

/var/name/master/mydomain.net.rev
In addition to DNS doing lookup for names, it usually also does lookup for IP addresses. This is what you get when you do nslookup 192.168.150.1, for instance. The reverse domain name file holds that:


150.168.192.in-addr.arpa. IN SOA firewall.mydomain.net. myemail.yahoo.com. (
     1          ; Serial
     10800      ; Refresh after 3 hours
     3600       ; Retry after 1 hour
     604800     ; Expire after 1 week
     86400 )    ; Minimum TTL of 1 day

;
; Name Servers
;
150.168.192.in-addr.arpa.       IN NS   firewall.mydomain.net.

;
; Addresses point to canonical name
;
1.150.168.192.in-addr.arpa.     IN PTR  firewall.mydomain.net.
170.150.168.192.in-addr.arpa.   IN PTR  firesign.mydomain.net.
171.150.168.192.in-addr.arpa.   IN PTR  frantics.mydomain.net.
172.150.168.192.in-addr.arpa.   IN PTR  bundolo.mydomain.net.

Once again, watch for . characters at the end of .arpa. and .net.

At this point, you can kill and restart named, then:

nslookup
server localhost
frantics

You should see something like:

Server:         localhost
Address:        127.0.0.1#53

Name:   frantics.mydomain.net
Address: 192.168.150.171

/etc/resolv.conf.tail
The DHCP client overwrites /etc/resolv.conf, but then appends whatever/s in /etc/resolv.conf.tail to that. So let’s tell OpenBSD that Change /etc/resolv.conf to point to the running nameserver:

nameserver 192.168.150.1
domain mydomain.net
search mydomain.net
lookup bind file

This sets up the firewall as the nameserver to look for, tells what my domain is, says to search foo.mydomain.net when looking for foo, and to look up via bind first and then /etc/hosts.

/etc/dhcpd.conf
Now is a good time to change dhcpd.conf to point to your nameserver instead of someone else:

option domain-name-servers 192.168.150.1;

Save those changes
To save the changes that are in /var, use the following command:

tar cf /flash/var.tar -C /var .

Might as well save a copy somewhere else too:

tar cf /root/named.tar /var/named

Things are saved away as well as they’re going to be; time to reboot and hope you didn’t miss anything!

(This post is part of Building an ALIX firewall)


Setting up PF for the ALIX firewall

June 26, 2012

The next step on the firewall is to set up the packet filter PF. Most of what I do here comes from the OpenBSD PF FAQ.

Setting up PF itself
The file to edit is /etc/pf.conf. Here’s mine:

# macros
int_if="vr0"
ext_if="vr1"

# FTP Proxy rules
anchor "ftp-proxy/*"
pass in quick on $int_if inet proto tcp to any port ftp \
    divert-to 127.0.0.1 port 8021

# options
set block-policy return
set loginterface $ext_if
set skip on lo

# match rules
match out on egress inet from !(egress) to any nat-to (egress:0)

# filter rules
block in log
pass out quick
antispoof quick for { lo $int_if }
# uncomment this to respond to pings
# pass in inet proto icmp all icmp-type echoreq
pass in on $int_if

It’s basically the example config file for home or small office, with a couple of changes:

  1. I define an int_if and ext_if for internal network and external network
  2. I don’t have any port forwarding from outside through to the inside network except ftp-proxy
  3. I block all incoming ICMP traffic (which is broken according to spec, but might keep me safer from denial of service attacks).
  4. I keep port 22 closed on the firewall machine.

Basically, I present a blank wall to the Internet. Traffic I initiate can get out, but outside doesn’t get in except via ftp-proxy.

One thing to note is that if you mess up pf, you can get into a state where you can’t talk to your ALIX over the network. So make sure you have a serial port handy to talk to it. I’d recommend making changes to pf.conf over serial, and then testing with the network.

To test, run:

pfctl -F all
pfctl -f /etc/pf.conf

The first command flushes whatever existing PF config is there; the second command loads your new pf config.

Next, hook up a machine to the switch that’s connected to the LAN side of the firewall, and see if you have Internet. If you do, life is good!

Getting FTP running
You might have noticed I use ftp-proxy in my pf.conf. That’s a daemon that needs to be enabled in /etc/rc.conf:

ftpproxy_flags=""

According to the PF FAQ, you can run ftp-proxy to get the daemon going, but I rebooted instead after changing /etc/rc.conf. Also according to the FAQ, some (fussy) clients may need “-r” on ftpproxy_flags.

Blocking IP addresses using PF
I haven’t done this before, but I wanted to try blocking ad servers by IP address using PF. Some instructions are here.

My list of IP addresses came from the excellent pgl.yoyo.org/adservers site. I picked “list ad server IP addresses” as plain HTML text, checked the “view list as plain text” button, and pressed “go”. This gave me a URL that I copied.

I wanted a semi-automatic way to download this list. Luckily, OpenBSD’s ftp is a lot more than plain FTP. You can use it instead of wget/curl/etc. Here’s the command I used:

ftp -o /etc/pf.blocked.ip.conf "http://pgl.yoyo.org\
/adservers/iplist.php?ipformat=plain&;showintro=1&\
mimetype=plaintext"

Then I updated my pf.conf to account for that:

# macros
int_if="vr0"
ext_if="vr1"

# Table of IP addresses to block
table <blockedips> persist file "/etc/pf.blocked.ip.conf"

# FTP Proxy rules
anchor "ftp-proxy/*"
pass in quick on $int_if inet proto tcp to any port ftp \
    divert-to 127.0.0.1 port 8021

# options

set block-policy return
set loginterface $ext_if
set skip on lo

# match rules

match out on egress inet from !(egress) to any nat-to (egress:0)

# filter rules

# These two rules block traffic from blacklisted IP addresses
block drop in quick on $ext_if from <blockedips> to any
block return out quick from any to <blockedips>

block in log
pass out quick

antispoof quick for { lo $int_if }

# pass in inet proto icmp all icmp-type $icmp_types

pass in on $int_if

I’m not sure if this strategy will work long term. Previously I excluded ad servers in named instead. Excluding by IP address seems to take less RAM (I’ve got about 163M free of my 256M RAM with this table loaded) and has the advantage of blocking sneaky servers that use IP address URLs. The downside is that if another server uses the same IP address, I won’t get the content, and I have no real way to unblock by name if I need to.

At any rate, to update, I just need to do the ftp command again, and then:

pfctl -t blockedips -T replace -f /etc/pf.blocked.ip.conf

(This post is part of Building an ALIX firewall)


Setting up networking for the ALIX firewall

June 24, 2012

The next step in building an ALIX firewall is to set up networking.

Setting the hostname

  1. Edit the file /etc/myname to be the hostname you want (don’t forget to rw first if you need to).
  2. Run:

    hostname `cat /etc/myname`

    to set the hostname in lieu of rebooting.

Figuring out which port is which
On my ALIX, Ethernet port vr1 is the port nearest to the
serial port and vr0 is the one nearest to the power cable. I figured this out by plugging one port into the network and running ifconfig. In my case I saw:

vr1: flags=8802 mtu 1500
        lladdr 00:0d:ba:36:d9:30
        priority: 0
        media: Ethernet autoselect (none)
        status: active

whereas vr0 had status: no carrier. That told me that vr1 was the one on the network. I labelled the ports so I wouldn’t forget. (Since my plan is to have a firewall with one port for the internal LAN and another for the world, I used labels vr0:lan and vr1:world.)

Setting up the DHCP client on vr1
My ISP assigns me an IP address using DHCP. In the older flashdist, you had to edit /etc/rc to start up dhclient to get this address. With flashrd, it’s easier once again:
echo dhcp > /etc/hostname.vr1
sh /etc/netstart

At this point the ALIX will go to your local network and request an IP address via dhclient. Hopefully you have a DHCP server somewhere on your network; otherwise you’ll need to read Section 6 of the OpenBSD FAQ.

Setting up the LAN interface
I decided that I wouldn’t mess around with IPv6 just yet… I want to set up a NAT firewall using IPv4. To start with, I had to pick an IP address for my internal network. I’m going to use my ALIX box for DHCP, name resolution, and as a gateway. (Yes, I know this is bad practice… but I’m on a limited budget!)

I picked address 192.168.150.* for my network. This means my firewall will be 192.168.150.1, and I’ll use that as the gateway address of other machines which are its DHCP clients.

echo inet 192.168.150.1 255.255.255.0 NONE > /etc/hostname.vr0
sh /etc/netstart

Run the dhcpd server
So that the firewall can serve IP addresses, it needs to have dhcpd enabled. The right place to do this is in a section of rc.conf.local, but I got lazy and edited it in /etc/rc.conf. If I had to do this over, I’d use /etc/rc.conf.local. The code I changed was:

dhcpd_flags=""

Next we need to tell it what the subnet is that it will serve DHCP addresses to. This is defined in /etc/dhcpd.conf:

option domain-name "mydomain.net";
option domain-name-servers 8.8.8.8;

subnet 192.168.150.0 netmask 255.255.255.0 {
option routers 192.168.150.1;

range 192.168.150.32 192.168.150.127;

# host static-client {
# hardware ethernet 22:33:44:55:66:77;
# fixed-address 192.168.1.200;
# }

# host pxe-client {
# hardware ethernet 02:03:04:05:06:07;
# filename "pxeboot";
# next-server 192.168.1.1;
# }

In my case for absolutely arbitrary reasons, I said to serve from 192.168.150.32 to 192.168.150.63. I left the pxe-client and static-client things in case I needed them later.

Also note that right now I’m using Google’s 8.8.8.8 as the DNS server. I could have used my ISP’s instead – either way, it’s going to change once I get BIND running on the firewall.

Add myself to hosts
This is a good time to add myself to the /etc/hosts file (both under the short name and fully-qualified domain name):

192.168.150.1 myname myname.mydomain.net

Enabling port forwarding
Next we need to allow the firewall to forward IPv4 traffic. To do this, edit /etc/sysctl.conf:

net.inet.ip.forwarding=1

Update the time from the network
Since the ALIX doesn’t have a real time clock that stores the time, we need to update it from the network every time we reboot. This is in /etc/rc.conf:

ntpd_flags="-s"

The -s says “update the time now to the server time and don’t try to adjust it slowly.” That’s the right thing to do when the box thinks the time is way in the past.

At this point, I figured it was time to reboot the device and see if everything came up as expected.

/sbin/shutdown -r now

Now plug a switch into the vr0:lan port, a computer into the switch, and see if you can get an IP address. You’re not doing enough yet to have an Internet connection, but ipconfig /all on a Windows laptop should show a correct IPv4 address, subnet mask, gateway, dhcp server and DNS server. Groovy, you’ve got a network!

(This post is part of Building an ALIX firewall)


Getting OpenBSD 5.1 on the ALIX firewall

June 20, 2012

Getting OpenBSD on the ALIX used to be quite an effort. You had to figure out what your CF card looked like, enter the right drive parameters, and hope. Now it’s dead easy:

  1. Download the flashrd binary image. I used flashimg.i386.wd0.com0-20120531.gz, which is root wd0, com0 38400 console. This matches the Alix BIOS default, which also spits out 38400 serial.
  2. Unzip the image with gzip -d
  3. Write the image to the CF card. I have Cygwin installed, so I was able to use dd. Since I’m running this on Windows 7, I had to open my Cygwin shell as Administrator. The command I used:
    dd if=flashdist.i386.wd0.com0-20120531 of=/dev/sdd bs=128k

    I was pleasantly surprised that dd worked. (I found the device by doing sfdisk -l /dev/sda, then sdb, then sdc, until I found a partition table that looked like my 4 GB flash drive.) I picked 128k as the block size because the image was evenly divisible by that. I don’t know if it makes a difference, but I figured why risk it.

  4. Next I hooked up a DB9 F/F mini null modem to my PC serial port, connected that to the Alix serial port, ran hypertrm (which I had to get from an earlier Windows release) and was talking to OpenBSD. Root password was “root” (no quotes).
  5. At this point I reset the password:
    rw
    passwd root
    ro

    rw is the flashrd way to say “mount the file system read/write”, and ro says “mount the file system read-only”. flashrd boots up read-only (which saves wear on the flash card) so you need to set it to read/write if you want to do pretty much anything.

That’s all there is to it!

(This post is part of Building an ALIX firewall)


Building an ALIX firewall

June 20, 2012

It’s been a long time since I updated my firewall. Right now it’s a PC Engines ALIX 2c2 that I’ve been really happy with. I used flashdist and put OpenBSD 4.4 on it.

I think that’s a winning combination, but it’s time to upgrade. First, I want to go to OpenBSD 5.1. Next, flashdist has been replaced with flashrd, which is easier to install and use, and more appropriate for larger CF cards.

I started by getting an ALIX 2d2 (just one more IDE header than the 2c2, not much change). I bought it from mini-box.com, and I also picked up the custom enclosure for it and a power supply.

I already had a 4 GB CF card: a Kingston 4GB elite pro 133X, which was new when I built the original firewall. Make sure you have a good CF writer. I’ve had failures with cheapies, but got a Kingston FCR-HS219/1 and that worked.

There are a number of steps to get a working firewall. They are:

  1. Getting OpenBSD 5.1 on the ALIX
  2. Setting up networking for the ALIX firewall
  3. Setting up PF for the ALIX firewall
  4. Setting up BIND on the ALIX firewall
  5. Final cleanup for the ALIX firewall

Solving Youtube “Cannot Play Video” on Android

June 20, 2012

Recently, my phone entered a state where it would “sort of crash” when I tried to play Youtube links using the internal Youtube app. I could play in Flash fine, but if I opened the same link with the Youtube app, it would:

  1. vibrate twice
  2. vibrate again
  3. open a dialog titled “Cannot play video” with the text “Sorry, this video cannot be played”

Lots of users have seen this, but there weren’t too many solutions. I started out by uninstalling and reinstalling the Youtube app. No luck there. Then I found
this AndroidCentral thread and in particular Sumabot’s post.

That set me down the right path. I didn’t want to wipe out as much as he did, but I did do this:

  1. Open the web browser
  2. Menu -> More -> Settings
  3. Clear Cache
  4. Clear history
  5. Clear all cookie data
  6. Clear location access
  7. Reset to default

I might just have needed to “Reset to default” – if it happens again that’s what I’ll try next.

Update: I’ve figured out that opening a Youtube video in another window (regardless of cache state) will cause the browser to crash. In my case, just clicking on the link (as opposed to long-pressing and saying “Open”) seems to work.