Chapter 4. Building a Linux Wireless Access Point

4.0. Introduction

Wireless networking is everywhere. Someday, we’ll have built-in wireless receivers in our heads. Meanwhile, times are improving for Linux wireless administrators, if you shop carefully and buy wireless interface cards with good Linux support and WPA2 support. Using well-supported wireless interfaces means you’ll be able to dive directly into configuring your network instead of hassling with funky driver problems. This chapter shows how to build a secure, flexible, robust combination wireless access point/router/Internet firewall using Pyramid Linux on a Soekris single-board computer. It supports wireless and wired Linux, Windows, and Mac OS X clients sharing a broadband Internet connection and LAN services. Just one big happy clump of wired and wireless clients together in harmony.

Why go to all this trouble? Because you’ll have more control, all the powerful features you could ever want, and save money.

You don’t have to have an all-in-one-device. The recipes in this chapter are easy to split apart to make separate devices, such as a dedicated firewall and a separate wireless access point.

I use Pyramid Linux, Soekris or PC Engines WRAP boards, and Atheros wireless interfaces because they are battle-tested and I know they work well. See Chapter 2 to learn how to use these excellent little routerboards.

The example configurations for the different services, such as DHCP, DNS, authentication, iptables, and so forth work fine on other Debian Linux-based distributions, and any x86 hardware. Adapting them for other distributions means figuring out different ways of configuring network interface cards; configuring applications like hostapd, dnsmasq, and iptables is pretty much the same everywhere.

Some folks are bit confused as to what “native Linux support” means. It doesn’t mean using ndiswrapper, which is a Linux wrapper around Windows binary drivers. I wouldn’t use it unless I were down to my last dime and couldn’t afford to buy an interface card with native Linux support. It’s only good on the client side, doesn’t support all devices or features, and extracting the Windows binary drivers is a fair bit of work. Even worse, it rewards vendors who don’t support Linux customers.

Currently, the Linux-friendliest wireless chipset manufacturers, in varying degrees, are Ralink, Realtek, Atheros, Intel, and Atmel. Then there are reverse-engineered GPL Linux drivers for the popular Broadcom and Intersil Prism chips.

While all of these have open source drivers (http://opensource.org), the Atheros chips require a closed binary Hardware Access Layer (HAL) blob in the Linux kernel. Older Intel chips need a proprietary binary regulatory daemon in user-space, but the current generation do not. Ralink and Realtek handle this job in the radio’s firmware. Supposedly, this is to meet FCC requirements to prevent users from changing frequencies and channels outside of the allowed range. Putting a closed blob in the kernel makes writing and debugging drivers for Linux more difficult, as key parts of the radio’s functions are hidden. Some additional concerns are that the binary blob taints the kernel, a buggy kernel blob can cause a kernel panic, and only the vendor can fix it. Buggy firmware is not as problematic because it just means the device won’t work. The issue of the regulatory blob is a moving target and subject to change. (Go to the See Also section for some interesting reading on these issues.)

I use the Wistron CM9 mini-PCI interface (based on the Atheros AR5213) in my wireless access points because it gives full functionality: client, master, ad hoc, raw mode monitoring, WPA/WPA2, and all three WiFi bands (a/b/g) are supported. On the Linux client side, any of the supported wireless interfaces will work fine. Be careful with USB WICs—some work fine on Linux, some don’t work at all. Get help from Google and the resources listed at the end of this introduction.

Discovering the chipset in any particular device before purchase is a real pain—most vendors don’t volunteer the information, and love to play “change the chipset” without giving you an easy way to find out before making a purchase. To get up and running with the least hassle, consult a hardware vendor that specializes in Linuxsupported wireless gear.

An inexpensive but powerhouse alternative to the Soekris and PC Engines router-boards are those little 4-port consumer wireless broadband routers, like the Linksys WRT54G series. There are many similar ones under various brand names, and you’ll find some for under $50. You don’t get all the nice flexibililty that you get with the bigger routerboards, but they’re a heck of a value and make excellent dedicated wireless access points. The key to converting these from mediocre home-user boxes into $500 powerhouses is replacing the firmware with OpenWRT (http://openwrt.org/) or DD-WRT (www.dd-wrt.com/). These are open source, free-of-cost (though sending a bit of cash their way wouldn’t hurt any feelings) firmwares designed especially for these little routers. With the new firmware, you can perform amazing feats of packet filtering, bandwidth-shaping, wireless security, VLANs, name services, and much more.

Security

Security is extra important when you’re setting up wireless networking. Your bits are wafting forth into the air, so it’s dead easy for random snoops to eavesdrop on your network traffic. Unsecured wireless access points expose you to two different threats:

  • LAN intrusions. Your data might get stolen, or your LAN hosts turned into malware-spewing botnets, or used as rogue MP3 and porn servers.

  • Loss of bandwidth. It’s nice to share, but why allow your network performance to suffer because of some freeloader? Or worse, allow your bandwidth to be used for ill purposes?

If you wish to provide an open access point for anyone to use, do it the smart way. Wall it off securely from your LAN, and limit its bandwidth. One way to do this is to use a second wireless interface, if your routerboard supports it, or a dedicated access point, then use iptables to forward traffic from it to your WAN interface and block access to your LAN. Pyramid Linux comes with the WiFiDog captive portal, which you can use to remind your visitors of your generosity. Use the web interface to set it up; it takes just a few mouse clicks.

Encrypting and authenticating your wireless traffic is your number one priority. How do you do this? In the olden days, we had Wired Equivalent Privacy (WEP). Using WEP is barely better than nothing—it is famously weak, and can be cracked in less than 15 minutes with tools that anyone can download, like AirSnort and WEPCrack. Don’t use WEP. Upgrade to devices that support Wi-Fi Protected Access (WPA).

There are two flavors of WPA: WPA and WPA2. WPA is an upgrade of WEP; both use RC4 stream encryption. It was designed to be a transitional protocol between WEP and WPA2. WPA is stronger than WEP, but not as strong as WPA2. WPA2 uses a new strong encryption protocol called Counter Mode with CBC-MAC Protocol (CCMP), which is based on Advanced Encryption Standard (AES). WPA2 is the complete implementation of the 802.11i standard. See Matthew Gast’s excellent book 802.11 Wireless Networks: The Definitive Guide (O’Reilly) for more information on these. The short story is that using WPA2 gives the best protection.

Using modern wireless devices that support WPA2 makes it easy to encrypt and authenticate all of your wireless traffic. WPA supports two different types of authentication: WPA-PSK (aka WPA-Personal, which uses preshared keys) and WPA-EAP (aka WPA-Enterprise, which uses the Extensible Authentication Protocol).

WPA-Personal is simple to set up. It depends on a shared key, which is a passphrase, and which must be distributed to all authorized users. There is no built-in automated method to distribute the keys; you have to do it manually, or write a clever script, or use something like cfengine. The obvious flaw in this scheme is everyone has the same key, so anytime you need to change the key it has to be changed on all clients. However, there is a way to give users unique keys—use hostapd, the host access point daemon. It’s part of the HostAP suite of wireless drivers and utilities, and it includes a simple mechanism for managing multiple keys. This is a slick, simple way to implement some good, strong security.

WPA-Enterprise requires an authentication server, most commonly a RADIUS server. It’s more work to set up, but once it’s up, it’s easier to manage users and keys. A RADIUS server is overkill if you’re running a single access point, but it’s a life-saver if your network has several points of entry, such as dial-up, a VPN gateway, and multiple wireless access points, because all of them can use a single RADIUS server for authentication and authorization.

HostAP includes an embedded RADIUS server. Other access points can use it just like a standalone RADIUS server.

wpa_supplicant handles the interaction between the client and the server. wpa_ supplicant is included in virtually all Linux distributions, though it may not be installed by default. Mac OS X and Windows also have supplicants. The word supplicant was chosen deliberately, with its connotations of humbly requesting permission to enter your network.

See Also

These articles discuss the “binary blob” issue:

For building your own wireless access points and getting product information in plain English without marketing guff, check out specialty online retailers like:

These sites identify wireless chipsets by brand name and model number:

General wireless resources:

4.1. Building a Linux Wireless Access Point

Problem

You don’t want to dink around with prefab commercial wireless access points. They’re either too simple and too inflexible for your needs, or too expensive and inflexible. So, like a good Linux geek, you want to build your own. You want a nice quiet little compact customizable box, and you want to be able to add or remove features as you need, just like on any Linux computer. For starters, you want everything on a single box: authenticated wireless access point, broadband Internet connection sharing, iptables firewall, and name services.

Solution

  • Install Pyramid Linux on a Soekris or PC Engines WRAP single-board computer.

  • Install an Atheros-based wireless mini-PCI card and connect an external antenna.

  • Configure and test LAN connectivity, and DHCP and DNS.

  • Keep your router off the Internet until it’s properly hardened, firewalled, and tested.

  • Add Internet connectivity, and voilà! It is done.

Continue on to the next recipes to learn how to do all of these things.

Discussion

If you prefer separating out your services on different physical boxes, such as wireless access point, firewall, and nameserver, the recipes in this chapter are easy to adapt to do this.

Soekris has two series of routerboards: 45xx and 48xx. Choose whatever model meets your needs. At a minimum, you need 64 MB RAM, a Compact Flash slot, a mini-PCI slot, and two Ethernet ports. More powerful CPUs and more RAM are always nice to have. A second mini-PCI slot lets you add a second wireless interface. PCMCIA slots give you more flexibility because these support both wired and wireless interfaces.

The 45xx boards have 100 or 133 MHz CPUs and 32 to 128 MB SDRAM. The 48xx boards have 233 or 266 MHz processors and 128 to 256 MB SDRAM. You’ll see network speeds top out on the 45xx boards around 17 Mbps, and the more powerful 48xx boards will perform at up to 50 Mbps. 17 Mbps is faster than most cable or DSLInternet connections. For ordinary web surfing and email, the 45xx boards are fine. If you’re running VoIP services, doing online gaming, serving more than 50 users, or running any peer protocols like BitTorrent, then go for the 48xx boards.

PC Engines WRAP boards are similar to the Soekris boards, and are usually a bit less expensive. Both use Geode CPUs, are about the same size, and similarly featured. Both vendors will customize the boards pretty much however you want.

4.2. Bridging Wireless to Wired

Problem

How do you integrate your wired and wireless clients so that they share an Internet connection and LAN services all in one big happy subnet? You know that when you have multiple Ethernet interfaces on the same box they cannot all be on the same subnet, but must all have addresses from separate subnets. You want everyone all in a single subnet, and don’t want a lot of administration headaches, so how will you do this?

Solution

Your routerboard needs at least three network interfaces: your Atheros interface, plus two Ethernet interfaces. ath0 is your wireless interface, eth0 is the LAN interface, and eth1 is your WAN interface.

What we will do is build an Ethernet bridge between ath0 and eth0. Copy this example /etc/network/interfaces, substituting your own LAN addresses and your own ESSID. Remember to run /sbin/rw first to make the Pyramid filesystem writable:

	pyramid:~# /sbin/rw
	pyramid:~# nano /etc/network/interfaces

	##/etc/network/interfaces
	## wireless bridge configuration
	auto lo
	iface lo inet loopback

	auto br0
	iface br0 inet static
	       address 192.168.1.50
	       network 192.168.1.0
	       netmask 255.255.255.0
	       broadcast 192.168.1.255
	       bridge_ports ath0  eth0
	        post-down wlanconfig ath0 destroy
	        pre-up wlanconfig ath0 create wlandev wifi0 wlanmode ap
	        pre-up iwconfig ath0 essid "alrac-net" channel 01 rate auto
	        pre-up ifconfig ath0 up
	        pre-up sleep 3

You can test this now by networking with some LAN hosts that have static IP addresses. First restart networking on the router:

	pyramid:~# /etc/init.d/networking restart

This creates a wide-open wireless access point. Point your clients to 192.168.1.50 as the default gateway, and you should be able to easily join any wireless clients to your LAN, and ping both wired and wireless PCs. When you’re finished, remember to return the filesystem to read-only:

	pyramid:~# /sbin/ro

Discussion

This recipe is totally insecure, but it lets you test your bridge and wireless connectivity before adding more services.

Let’s review the options used in this configuration:

bridge_ports

Define the two interfaces to bridge.

post-down wlanconfig ath0 destroy

This command tears down the access point when the network interfaces go down. wlanconfig is part of MadWiFi-ng. Use it to create, destroy, and manage access points. With wlanconfig, you can have multiple access points on a single device.

pre-up wlanconfig ath0 create wlandev wifi0 wlanmode ap

wifi0 is the name the kernel gives to your Atheros interface, which you can see with dmesg. Next, wlanconfig creates the virtual access point, ath0, on top of wifi0.

pre-up iwconfig ath0 essid "alracnet" channel 01 rate auto

Assign the ESSID, channel, and bit-rate. To see the channels, frequencies, and bit-rates supported by your interface card, use this command:

	pyramid:~# wlanconfig ath0 list chan

How do you know which channel to use? If you have only one access point, channel 1 should work fine. If you have up to three, try using channels 1, 6, and 11. For more complex networks, please refer to Matthew Gast’s excellent book, 802.11 Wireless Networks: The Definitive Guide (O’Reilly):

pre-upifconfigath0 up

Bring up ath0 before the bridge comes up.

pre-upsleep3

Brief pause to make sure that everything comes up in order.

You don’t have to build the bridge in the traditional way, by configuring eth0 with a zero-IP address, or bringing it up before the bridge is built, because scripts in /etc/network/if-pre-up.d handle that for you.

I’m sure some of you are wondering about ebtables. ebtables is like iptables for Ethernet bridges. iptables cannot filter bridge traffic, but ebtables can. There are many ingenious ways to use ebtables and Ethernet bridges in your network. In this chapter, I’m leaving ebtables out on purpose because we will be running an iptables Internet firewall on our access point. ebtables is not suitable for an Internet firewall, and trying to use both on the same box is too complicated for this old admin.

See Also

  • Pyramid Linux does not include manpages, so you should either install the applications in this chapter on a PC, or rely on Google

  • wlanconfig is part of MadWiFi-ng

  • man 8 brctl for bridge options

  • iwconfig is part of the wireless-tools package

  • man 8 iwconfig

  • Pyramid Linux: http://pyramid.metrix.net/

  • Recipe 3.2

  • 802.11 Wireless Networks: The Definitive Guide, by Matthew Gast (O’Reilly)

4.3. Setting Up Name Services

Problem

Your LAN is going to have a combination of hosts with static IP addresses and DHCP clients that come and go, especially wireless clients. And, you want DHCP clients to automatically be entered into DNS so they can be accessed by hostname just like the hosts with static IP addresses.

Solution

You don’t want much. Fortunately, you can have it all. Pyramid comes with dnsmasq, which handles DHCP and DNS, and automatically enters DHCP clients into DNS. This requires the clients to send their hostnames when they are requesting a DHCP lease. Windows clients do this by default. Most Linux clients do not, so go to Recipe 4.5 to learn about client configuration.

Now, we’ll edit /etc/dnsmasq.conf on your Pyramid box. First make the filesystem write able by running /sbin/rw. Copy this example, using your own network name instead of alrac.net, whatever DHCP range you prefer, and your own upstream nameservers:

	pyramid:~# /sbin/rw
	pyramid:~# nano /etc/dnsmasq.conf

	domain-needed
	bogus-priv
	local=/alrac.net/
	expand-hosts
	domain=alrac.net
	interface=br0
	listen-address=127.0.0.1

	#upstream nameservers
	server=22.33.44.2
	server=22.33.44.3

	dhcp-range=lan,192.168.1.100,192.168.1.200,12h
	dhcp-lease-max=100

Next, add all of your hosts that already have static IP addresses to /etc/hosts on your Pyramid box, using only their hostnames and IP addresses. At a minimum, you must have an entry for localhost and your Pyramid router:

	## /etc/hosts
	127.0.0.1      localhost
	192.168.1.50   pyramid
	192.168.1.10   xena
	192.168.1.74   uberpc

Restart dnsmasq:

	pyramidwrap:~# killall dnsmasq

To test your new nameserver, ping your LAN hosts from each other:

	$ ping pyramid
	$ ping xena$ ping uberpc

You should see responses like this:

	PING pyramid.alrac.net (192.168.1.50) 56(84) bytes of data.
	64 bytes from pyramid.alrac.net (192.168.1.50): icmp_seq=1 ttl=64 time=0.483 ms
	64 bytes from pyramid.alrac.net (192.168.1.50): icmp_seq=2 ttl=64 time=0.846 ms

You should be able to ping both wired and wireless clients, and DHCP clients should be entered automatically into the DNS table as well.

Finally, verify that their domain names are correctly assigned by DNS:

	$ hostname
	xena
	$ hostname -f
	xena.alrac.net
	$ dnsdomainname
	alrac.net

Discussion

Pyramid Linux mounts a number of files into a temporary, writeable filesystem, like /etc/resolv.conf. You can see which ones they are by looking in /rw, or running ls-l/etc to see which ones are symlinked to /rw. These are copied over from /ro on boot. It’s designed to keep flash writes down. So, you can either edit /ro, or make the files in /etc immutable.

dnsmasq.conf crams a lot of functionality into a few lines, so let’s take a closer look:

domain-needed

Do not forward requests for plain hostnames that do not have dots or domain parts to upstream DNS servers. If the name is not in /etc/hosts or DHCP, it returns a “not found” answer. This means that incomplete requests (for example, “google” or “oreilly” instead of google.com or oreilly.com) will be cut off before they leave your network.

bogus-priv

Short for “bogus private lookups.” Any reverse lookups for private IP ranges (such as 192.168.x.x) are not forwarded upstream. If they aren’t found in /etc/hosts, or the DHCP leases file, “no such domain” is the answer. Using domain-needed and bogus-priv are simple options for practicing good Netizenship.

local=/alrac.net/

Put your local domain name here so queries for your local domain will only be answered from /etc/hosts and DHCP, and not forwarded upstream. This is a nice bit of magic that lets you choose any domain name for your private network and not have to register it. To make this work right, you also need the expand-hosts and domain options.

expand-hosts

This automatically adds the domain name to the hostnames.

domain=alrac.net

expand-hosts looks here for the domain name.

interface

Define which interface dnsmasq should listen to. Use one line per interface, if you have more than one.

listen-address=127.0.0.1

This tells dnsmasq to also use its own local cache instead of querying the upstream nameservers for every request. This speeds up lookups made from the router, and it also allows the router to use your local DNS. You can verify this by pinging your LAN hosts from the router by their hostnames or FQDNs.

server

The server option is used for several different purposes; here, it defines your upstream DNS servers.

dhcp-range=lan,192.168.1.100,192.168.1.200,12h

Define your pool of DHCP leases and lease time, and define a network zone called “lan.” Using named zones lets you assign servers and routes to groups of clients and different subnets; see Recipe 3.13 to see this in action.

dhcp-max-lease

Maximum limit of total DHCP leases. The default is 150. You may have as many as your address range supports.

See Also

  • Recipe 4.12 for an example of using named zones

  • man 8 dnsmasq contains a wealth of helpful information about all the available command-line options, many of which are also dnsmasq.conf options

  • dnsmasq.conf is also a great help resource

  • dnsmasq home page is where you’ll find mailing list archives and excellent help documents: http://www.thekelleys.org.uk/dnsmasq/doc.html

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.4. Setting Static IP Addresses from the DHCP Server

Problem

You want to manage your LAN computers from DHCP instead of configuring them individually, so you don’t have to run around tweaking individual computers all the time. You want to assign static and dynamic IP addresses, gateways, and servers all via DHCP.

Solution

dnsmasq does it all. There are a couple of ways to assign static IP addresses from dnsmasq.conf. One is to use the client’s MAC address as the client identifier, like this:

	dhcp-host=11:22:33:44:55:66,192.168.1.75

My favorite way is to set it by hostname:

	dhcp-host=penguina,192.168.1.75

Make sure you do not have entries for these in /etc/hosts.

The only client configuration that’s necessary is the hostname, and for DHCP clients to send the hostname to the DHCP server when they request a new lease. Once youhave that, you can control everything else from the server.

Remember to run killall dnsmasq every time you change dnsmasq.conf.

There are some tricky bits to client configuration, so see Recipe 4.5 for this.

Discussion

Changes in dnsmasq.conf are easy to test. After restarting dnsmasq, try the following commands on your Linux clients.

ifupdown stops and restarts interfaces:

	# ifdown eth0
	# ifup etho

Sometimes, that doesn’t quite do the job, so you can also try:

	# /etc/init.d/network restart
	# /etc/init.d/networking restart

The first one is for Fedora, the second for Debian. You’ll see it acquire the address you assigned it from the DHCP server, and it will write the correct DNS server or servers to /etc/resolv.conf.

If those don’t work, reboot.

Find MAC addresses with ifconfig for wired NICs, and iwconfig for wireless NICs. ifconfig sees both, but it doesn’t differentiate them. iwconfig identifies only wireless interfaces.

When you use the MAC address, don’t forget to change the entry in dnsmasq.conf if you replace the client’s network interface card.

MAC addresses are unique, but hostnames are not, so you have to be careful not to have duplicate hostnames. You can’t have duplicate hostnames, anyway.

MAC addresses are ridiculously easy to spoof, so don’t think you’re adding any security by relying on them as secure, unique identifiers.

See Also

  • man 8 dnsmasq contains a wealth of helpful information about all the available command-line options, many of which are also dnsmasq.conf options

  • dnsmasq.conf is also a great help resource

  • dnsmasq home page (http://www.thekelleys.org.uk/dnsmasq/doc.html) is where you’ll find mailing list archives and excellent help documents

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.5. Configuring Linux and Windows Static DHCP Clients

Problem

What with having both Linux and Windows clients, and various Linux distributions that like to do things their own way, you’re a bit befuddled as to how to configure them to have dnsmasq give them static IP addresses.

Solution

The key to getting static IP addresses from DHCP is for the clients to send their hostnames to the DHCP server when they request a lease.

Windows 2000, 2003, and XP clients do this automatically. All you do is configure them for DHCP in the usual manner.

First, on all Linux machines, make sure there is nothing in /etc/hosts other than the localdomain entry.

Most Linux distributions are not configured to send the hostname by default. To fix this, add one line to their DHCP client files. On Debian, this is the /etc/dhcp3/dhclient.conf file. This example is for the computer named Penguina:

	send host-name "penguina";

You must also enter the hostname in /etc/hostname:

	penguina

Just the hostname and nothing else. Then, set up the normal DHCP configuration in /etc/network/interfaces, like this:

	##/etc/network/interfaces
	auto lo
	iface lo inet loopback

	auto eth0
	iface eth0 inet dhcp

On Fedora, each interface gets its own DHCP client file, like /etc/dhclient-eth1. You may need to create this file. This takes the same send host-name "penguina"; entry. Then, add this line to /etc/sysconfig/network-scripts/ifcfg-eth0:

	DHCP_HOSTNAME=penguina

Make sure the HOSTNAME line in /etc/sysconfig/network is empty.

The sure way to test your new configurations is to reboot, then run these commands:

	$ hostname
	penguina
	$ hostname -f
	penguina.alrac.net
	$ dnsdomainname
	alrac.net

Ping will look like this:

	carla@xena:~$ ping penguina
	PING penguina.alrac.net (192.168.1.75) 56(84) bytes of data.
	64 bytes from penguina.alrac.net (192.168.1.75): icmp_seq=1 ttl=128 time=8.90 ms
	carla@penguina:~$ ping penguina
	PING penguina.alrac.net (192.168.1.75) 56(84) bytes of data.
	64 bytes from penguina.alrac.net (192.168.1.75): icmp_seq=1 ttl=64 time=0.033 ms

Discussion

The most common cause of problems with this is not configuring the hostname correctly. Check all of your pertinent configuration files.

Here is a complete example Fedora configuration for eth0:

	##/etc/sysconfig/network-scripts/ifcfg-eth0
	DEVICE=eth0
	ONBOOT=yes
	BOOTPROTO=dhcp
	HWADDR=11.22.33.44.55.66
	DHCP_HOSTNAME=penguina
	TYPE=wireless
	PEERDNS=yes
	MODE=managed
	RATE=auto

Either edit Fedora configuration files directly, or use the graphical network configurator, but don’t use both because the graphical tool overwrites your manual edits.

dnsmasq automatically enters DHCP clients into DNS. This is a great convenience, and when you deploy IPv6, it will be more than a convenience—it will be a necessity, unless you’re comfortable with remembering and typing those long IPv6 addresses.

dnsmasq combines a lot of complex functions into a short configuration file, and can be used in conjunction with BIND, djbdns, MaraDNS, and other nameservers. Use dnsmasq for your private LAN services, and one of the others for a public authoritative server. This makes it easy to keep the two completely separate, as they should be. Remember the number one DNS server rule: keep your authoritative and caching servers strictly separated, which means using two physically separate network interfaces and different IP addresses. Authoritative servers do not answer queries for other domains; that is the job of a caching resolver like dnsmasq. Maintaining two separate servers might sound like more work, but in practice, it’s easier and safer than trying to configure a single server to handle both jobs.

See Also

  • man 5 dhclient

  • dnsmasq.conf is a great help resource

  • dnsmasq home page (http://www.thekelleys.org.uk/dnsmasq/doc.html) is where you’ll find mailing list archives and excellent help documents

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.6. Adding Mail Servers to dnsmasq

Problem

You have some local mail servers that you want your LAN hosts to know about. How do you do this with dnsmasq?

Solution

dnsmasq has a special record type for mailservers. You need these three lines:

	mx-host=alrac.net,mail.alrac.net,5
	mx-target=mail.alrac.net
	localmx

The mx-host line needs the domain name, server name, and MX priority. The mx-target line is the server name. localmx means all local machines should use this server.

Discussion

A priority number of 5 means the server is higher priority than servers with larger numbers, typically 10 and then multiples of 10. If you have only one mail server, you should still give it a priority to keep clients happy.

See Also

  • man 5 dhclient

  • dnsmasq.conf is also a great help resource

  • dnsmasq home page (http://www.thekelleys.org.uk/dnsmasq/doc.html) is where you’ll find mailing list archives and excellent help documents

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.7. Making WPA2-Personal Almost As Good As WPA-Enterprise

Problem

You’re nervous about sitting there with an unsecured wireless access point, and you really want to lock it up before you do anything else. You’ve made sure that all of your wireless network interfaces support WPA2, so you’re ready to go. You don’t want to run a RADIUS authentication server, but using the same shared key for all clients doesn’t seem very secure. Isn’t there some kind of in-between option?

Solution

Yes, there is. Pyramid Linux comes with hostapd, which is a user space daemon for access point and authentication servers. This recipe will show you how to assign different pre-shared keys to your clients, instead of everyone using the same one. And, we’ll use a nice strong AES-CCMP encryption, instead of the weaker RC4-based ciphers that WPA and WEP use.

First, run /sbin/rw to make the Pyramid filesystem writeable, then create or edit the /etc/hostapd.conf file:

	##/etc/hostapd.conf
	interface=ath0
	bridge=br0
	driver=madwifi
	debug=0
	ssid=alrac-net
	macaddr_acl=0
	auth_algs=3
	wpa=1
	wpa_psk_file=/etc/hostapd_wpa_psk
	wpa_key_mgmt=WPA-PSK
	wpa_pairwise=CCMP

Next, create /etc/hostapd_wpa_psk, which holds the shared plaintext passphrase:

	00:00:00:00:00:00 waylongpassword

Then, edit /etc/network/interfaces so that hostapd starts when the br0 interface comes up. Add these lines to the end of your br0 entry:

	up hostapd -B /etc/hostapd.conf
	post-down killall hostapd

Run /sbin/ro, then restart networking:

	pyramid:~# /etc/init.d/networking restart

Now, grab a Linux client PC for testing. On the client, create an /etc/wpa_supplicant.conf file with these lines, using your own ESSID and super-secret passphrase from /etc/hostapd_wpa_psk:

	##/etc/wpa_supplicant.conf
	network={
	   ssid="alrac-net"
	   psk="waylongpassword"
	   pairwise=CCMP
	   group=CCMP
	   key_mgmt=WPA-PSK
	}

Shut down the client’s wireless interface, then test the key exchange:

	# ifdown ath0
	# wpa_supplicant -iath0 -c/etc/wpa_supplicant.conf -Dmadwifi -w
	  Trying to associate with 00:ff:4a:1e:a7:7d (SSID='alrac-net' freq=2412 MHz)
	  Associated with 00:ff:4a:1e:a7:7d
	  WPA: Key negotiation completed with 00:ff:4a:1e:a7:7d [PTK=CCMP GTK=CCMP]
	 CTRL-EVENT-CONNECTED - Connection to 00:2b:6f:4d:00:8e

This shows a successful key exchange, and it confirms that the CCMP cipher is being used, which you want to see because it is much stronger than the RC4 stream encryption used by WEP. Hit Ctrl-C to end the key exchange test. So, you can add more clients, giving each of them a unique key. All you do is line them up in /etc/hostapd_wpa_psk, and match their passphrases to their MAC addresses:

	00:0D:44:00:83:CF    uniquetextpassword
	00:22:D6:01:01:E2    anothertextpassword
	23:EF:11:00:DD:2E    onemoretextpassword

Now, you have a good strong AES-CCMP based encryption, and if one user compromises her key, you don’t have to change all of them. Revoking a user’s access is as easy as commenting out or deleting their key.

You can make it permanent on the clients by configuring their wireless interfaces to call wpa_supplicant when they come up. On Debian, do this:

	##/etc/network/interfaces
	auto ath0
	iface ath0 inet dhcp
	pre-up wpa_supplicant -iath0 -Dmadwifi -Bw -c/etc/wpa_supplicant/wpa_supplicant.conf
	post-down killall -q wpa_supplicant

On Fedora, add this line to /etc/sysconfig/network-scripts/ifup-wireless:

	wpa_supplicant -ieth0 -c/etc/wpa_supplicant/wpa_supplicant.conf -Dmadwifi -Bw

Make sure your filepath to wpa_supplicant.conf is correct, that you specify the correct interface with -i, and that you specify the correct driver for your wireless interface with the -D option.

Discussion

When you test the key exchange, you need to specify the driver for your WIC (in the example, it’s -Dmadwifi). man8wpa_supplicant lists all options. The wext driver is a generic Linux kernel driver. You’ll see documentation recommending that you use this. It’s better to try the driver for your interface first, then give wext a try if that causes problems.

The example passphrases are terrible, and should not be used in real life. Make yours the maximum length of 63 characters, no words or names, just random jumbles of letters and numbers. Avoid punctuation marks because some Windows clients don’t handle them correctly. There are all kinds of random password generators floating around if you want some help, which a quick web search will find.

Windows XP needs SP2 for WPA support, plus client software that comes with your wireless interfaces. Older Windows may be able to get all the necessary client software with their wireless interfaces. Or maybe not—shop carefully.

It takes some computational power to encrypt a plaintext passphrase, so using plaintext passphrases could slow things down a bit. You can use wpa_password to encrypt your passphrases, then copy the encrypted strings into place:

	$ wpa_passphrase alrac-net w894uiernnfif98389rbbybdbyu8i3yenfig87bfop
	network={
	        ssid="alrac-net"
	        #psk="w894uiernnfif98389rbbybdbyu8i3yenfig87bfop"
	        psk=48a37127e92b29df54a6775571768f5790e5df87944c26583e1576b83390c56f
	}

Now your clients and access point won’t have to expend so many CPU cycles on the passphrase. Encrypted keys do not have quotation marks in wpa_supplicant.conf; plaintext passphrases do.

In our original example, 00:00:00:00:00:00 means “accept all MAC addresses.”

You can see your keys in action with the iwlist ath0 key command on the access point and clients.

Your access point supports virtually all clients: Linux, Mac OS X, Windows, Unix, the BSDs…any client with a supplicant and support for the protocols will work.

NetworkManager and Kwlan are good graphical network management tools for Linux clients. NetworkManager is designed for all Linux desktops and window managers, and comes with Gnome; Kwlan is part of KDE. Both support profiles, key management, and easy network switching.

When you’re using an Ethernet bridge, make sure that you enter your wireless and bridge interfaces in /etc/hostapd.conf.

hostapd.conf supports access controls based on MAC addresses. You’re welcome to use these; however, I think they’re a waste of time because MAC addresses are so easy to spoof your cat can do it.

HostAP was originally a project that supported only Prism wireless chips, but now it supports these drivers:

  • Host AP driver for Prism2/2.5/3

  • madwifi (Atheros ar521x)

  • Prism54.org (Prism GT/Duette/Indigo)

  • BSD net80211 layer

See Also

  • Pyramid Linux does not include manpages, so you should install the applications in this chapter on a PC to get the manpages, or rely on Google

  • wlanconfig is part of MadWiFi-ng

  • man 8 wlanconfig

  • The default hostapd.conf is full of informative comments

  • The default wpa_supplicant.conf is helpful

  • 802.11 Wireless Networks: The Definitive Guide, by Matthew Gast (O’Reilly)

  • MadWiFi.org: http://madwifi.org/

4.8. Enterprise Authentication with a RADIUS Server

Problem

The previous recipe is a slick hack for giving your wireless clients individual keys, but it’s still not a proper Public Key Infrastructure (PKI), which is better for larger deployments, and better for security. You have decided it’s worth running a standalone RADIUS server for your wireless authentication because it offers more security and more flexibility. You’ll be able to use it for all network authentication if you want to, not just wireless, and you can scale up at your own pace. So, how do you use a RADIUS server for wireless authentication?

Solution

Use FreeRADIUS together with OpenSSL. There are four steps to this:

  1. Install and configure the FreeRADIUS server

  2. Create and distribute OpenSSL server and client certificates

  3. Configure your wireless access point

  4. Configure client supplicants

Your WAP becomes a Network Access Server (NAS) because it passes along the job of user authentication to the FreeRADIUS server.

To ensure the least hair loss and lowest blood pressure, use your distribution’s package manager to install FreeRADIUS. If you prefer a source installation, refer to the INSTALL document in the source tarball.

This recipe requires a PKI using Extensible Authentication Protocol-Transport Layer Security (EAP-TLS) authentication, which means the server and client must authenticate to each other with X.509 certificates. So, you’ll need:

  • Your own certificate authority

  • Server private key and CA-signed certificate

  • A unique private key and a CA-signed certificate for each client

This is the strongest authentication you can use. See Recipe 9.5 to learn how to do this the easy way, with OpenVPN’s excellent helper scripts. If you don’t have OpenVPN, you can get the scripts from OpenVPN.net (http://openvpn.net/).

There are two things you will do differently. First, use password-protected client certificates:

	# ./build-key-pass [client hostname]

And, you will have to create PK12 certificates for Windows clients:

	# ./build-key-pkcs12 [client hostname]

In this recipe, the certificate authority, private server key, and public server key are kept in /etc/raddb/keys. This directory should be mode 0750, and owned by root and the FreeRADIUS group created by your Linux distribution. On Debian, this is root: freerad. On Fedora, root:radiusd. You’ll be editing these FreeRADIUS files:

/etc/raddb/clients.conf
/etc/raddb/users
/etc/raddb/eap.conf
/etc/raddb/radiusd.conf

Debian users, look in /etc/freeradius instead of /etc/raddb.

First, tell FreeRADIUS about your wireless access point or points in clients.conf, using one section per WAP. You can start over with a clean new file instead of adding to the default file:

	##/etc/raddb/clients.conf
	client 192.168.1.50 {
	        secret = superstrongpassword
	        shortname = wap1
	        nastype = other
	        }

Then, make a list of authorized users’ login names in the users file, and a nice reject message for users who are not in this file. The usernames are the Common Names on their client certificates. Add them to the existing users file:

	##/etc/raddb/users
	"alrac sysadmin" Auth-Type := EAP
	"terry rockstar" Auth-Type := EAP
	"pinball wizard" Auth-Type := EAP

	DEFAULT Auth-Type := Reject
	        Reply-Message = "I hear you knocking, but you can't come in"

Now, create two files containing random data, which EAP needs to do its job. These must be owned by root and the FreeRADIUS group, and readable only to the file owners:

	# openssl dhparam -check -text -5 512 -out /etc/raddb/dh
	# dd if=/dev/random of=/etc/raddb/random count=1 bs=128
	# chown root:radiusd /etc/raddb/dh
	# chown root:radiusd /etc/raddb/random
	# chmod 0640 /etc/raddb/dh
	# chmod 0640 /etc/raddb/random

Make sure you use the correct RADIUS group for your distribution.

eap.conf is where you configure the EAP module. Find and edit these lines in your existing file, using your own filenames:

	##/etc/raddb/eap.conf
	default_eap_type = tls
	tls {
	     private_key_password = [your password]
	     private_key_file = /etc/raddb/keys/xena.crt
	     certificate_file = /etc/raddb/keys/xena.key
	     CA_file = /etc/raddb/keys/ca.crt

	     dh_file = /etc/raddb/keys/dh2048.pem
	     random_file = /etc/raddb/keys/random
	     fragment_size = 1024
	     include_length = yes
	}

radiusd.conf is huge and replete with helpful comments, so I will show just the bits you may need to change. In the Authorization module, make sure the eap line is uncommented:

	##/etc/raddb/radiusd.conf
	# Authorization. First preprocess (hints and huntgroups files),
	authorize {
	...
	eap
	...
	}

Then, in the Authentication module, make sure the eap line is uncommented:

	# Authentication.
	authenticate {
	...
	eap
	...
	}

Finally, make sure these lines are uncommented and the correct user and group are entered. These vary, so check your own distribution:

	user = radiusd
	group = radiusd

Shut down FreeRADIUS if it is running, then run these commands to test it:

	# freeradius -X
	...
	"Ready to process requests"# radtest test test localhost 0 testing123

The first command starts it in debugging mode. The second command sends it a fake authentication test, which should fail. What you want to see is FreeRADIUS responding to the test. Debugging mode emits reams of useful output, so if there are any errors in your configurations, you’ll be able to track them down.

Discussion

The trickiest bit is getting your certificates right, but fortunately, the Easy-RSA scripts make the process easy. A good alternative is the excellent graphical PKI manager TinyCA (http://tinyca.sm-zone.net/).

A slick FreeRADIUS feature is that you don’t need to use a Certification Revocation List (CRL), though nothing’s stopping you if you want to because revoking a user is as simple as removing them from the users file.

The various Linux distributions handle the FreeRADIUS user and group in different ways. Some use nobody. Debian creates a freerad user and group. It’s important to run FreeRADIUS as an unprivileged user, so make sure that the user and group lines in radiusd.conf are configured correctly.

If you have several WAPs, you may control access by subnet instead of individual WAP:

	##/etc/raddb/clients.conf
	client 192.168.0.0/24 {
	   secret = superstrongpassword
	   shortname = wap_herd
	   nastype = other

This is less secure because it uses the same secret for all access points, but it’s easier to manage.

See Also

  • man 1 openssl

  • man dhparam

  • The default eap.conf, radiusd.conf, clients.conf, and users files are excellent help references

  • RADIUS, by Jonathan Hassell (O’Reilly) for a good in-depth tour of running a RADIUS server

  • The FreeRADIUS Wiki: http://wiki.freeradius.org/

  • TinyCA (http://tinyca.sm-zone.net/) is a nice graphical tool for creating and managing PKIs, and for importing and exporting certificates and keys

  • Recipe 9.5

4.9. Configuring Your Wireless Access Point to Use FreeRADIUS

Problem

OK, setting up FreeRADIUS was fun, now what do you do to make your WAP use it?

Solution

Your nice Pyramid Linux-based WAP needs but a few lines in /etc/hostapd.conf. In this example, the IP address of the FreeRADIUS server is 192.168.1.250:

	##/etc/hostapd.conf
	interface=ath0
	bridge=br0
	driver=madwifi
	debug=0
	ssid=alrac-net
	ieee8021x=1
	auth_algs=0
	eap_server=0
	eapol_key_index_workaround=1

	own_ip_addr=192.168.1.50
	nas_identifier=pyramid.alrac.net
	auth_server_addr=192.168.1.250
	auth_server_port=1812
	auth_server_shared_secret=superstrongpassword

	wpa=1
	wpa_key_mgmt=WPA-EAP
	wpa_pairwise=TKIP
	wpa_group_rekey=300
	wpa_gmk_rekey=640

Edit /etc/network/interfaces so that hostapd starts when your LAN interface comes up. Add these lines to the end of your LAN interface stanza:

	pre-up hostapd -B /etc/hostapd.conf
	post-down killall hostapd

Restart networking:

	pyramid:~# /etc/init.d/networking restart

And you’re almost there. See the next recipe for client configuration.

Discussion

All the different wireless access points are configured in different ways. The three things common to all of them are:

  • FreeRADIUS Server IP Address

  • FreeRADIUS Port: 1812 is the default

  • FreeRADIUS Key: shared secret

Remember, you don’t have to worry about keys and certificates on the access point. It’s just a go-between.

See Also

  • RADIUS, by Jonathan Hassell (O’Reilly) for a good in-depth tour of running a RADIUS server

  • The FreeRADIUS Wiki: http://wiki.freeradius.org/

  • The example hostapd.conf

4.10. Authenticating Clients to FreeRADIUS

Problem

Now that you have your access point and FreeRADIUS server ready to go to work, how do your clients talk to it?

Solution

All clients need a copy of ca.crt. Mac and Linux clients get their own [hostname].crt and [hostname].key files. Windows clients use [hostname].p12.

Your Windows and Mac clients have built-in graphical tools for importing and managing their certificates, and configuring their supplicants. What do you do on Linux? I haven’t found anything that makes the job any easier than editing plain old text files. Go back to Recipe 4.7, and start with the configuration for /etc/wpa_supplicant.conf. Change it to this:

	## /etc/wpa_supplicant.conf
	network={
	    ssid="alrac-net"
	    scan_ssid=1
	    key_mgmt=WPA-EAP
	    pairwise=CCMP TKIP
	    group=CCMP TKIP
	    eap=TLS
	    identity="alice sysadmin"
	    ca_cert="/etc/cert/ca.crt"
	    client_cert="/etc/cert/stinkpad.crt"
	    private_key="/etc/cert/stinkpad.key"
	    private_key_passwd="verysuperstrongpassword"
	}

The value for identity comes from /etc/raddb/users on the FreeRADIUS server. Certificates and keys can be stored anywhere, as long as wpa_supplicant.conf is configured correctly to point to them.

Continue with the rest of Recipe 4.7 to test and finish configuring wpa_supplicant.

Discussion

Be sure that .key files are mode 0400, and owned by your Linux user. .crt files are 0644, owned by the user.

You can have multiple entries in wpa_supplicant.conf for different networks. Be sure to use the:

	network{
	}

format to set them apart.

NetworkManager (http://www.gnome.org/projects/NetworkManager/) is the best Linux tool for painlessly managing multiple network profiles. It is bundled with Gnome, and is available for all Linux distributions.

See Also

  • man 8 wpa_supplicant

  • man 5 wpa_supplicant.conf

4.11. Connecting to the Internet and Firewalling

Problem

It’s high time to finish up with these LAN chores and bring the Internet to your LAN. Your wireless is encrypted, your LAN services are working, and your users want Internet. So you’re ready to configure your WAN interface and build a nice stout iptables firewall.

Solution

Easy as pie. First, configure your WAN interface, then set up an iptables firewall. (See Chapter 3 to learn how to do these things.) You’ll need to make some simple changes to /usr/local/bin/fw-nat to enable traffic to flow across your bridge. Add these two lines:

	$ipt -A INPUT -p ALL -i $LAN_IFACE -s 192.168.1.0/24 -j ACCEPT
	$ipt -A FORWARD -p ALL -i $LAN_IFACE -s 192.168.1.0/24 -j ACCEPT

Use your own subnet, of course. Then, change the value of LAN_IFACE to br0:

	LAN_IFACE="br0"

Restart and test everything according to Chapter 3, and you are set.

Discussion

Ethernet bridges join subnets into a single broadcast domain, with broadcast traffic going everywhere at once. A bridge is easy to set up and is transparent to your users. Your subnets function as a single network segment, so LAN services work without any additional tweaking, such as network printing, Samba servers, and Network Neighborhood. You can move computers around without having to give them new addresses.

Bridging is inefficient because it generates more broadcast traffic. So, it doesn’t scale up very far. An Ethernet bridge operates at the data link layer (layer 2) of the OSI Model. It sees MAC addresses, but not IP addresses. Bridge traffic cannot be filtered with iptables; if you want to do this, use ebtables, which is designed for bridging firewalls.

Routing gives more control over your network segments; you can filter traffic any way you like. It’s more efficient than bridging because it’s not spewing broadcasts all over the place. Routing scales up indefinitely, as demonstrated by the existence of the Internet. Its main disadvantage in the LAN is it’s a bit more work to implement.

See Recipe 4.12 to learn how to use routing instead of bridging on your wireless access point.

See Also

4.12. Using Routing Instead of Bridging

Problem

You would rather use routing between your two LAN segments instead of bridging because it gives better performance and more control. For example, you might set up a separate link just to give Internet access to visitors and easily keep them out of your network. Or, you want some separation and different sets of LAN services for each network segment. You know it’s a bit more work to set up, but that doesn’t bother you, you just want to know how to make it go.

Solution

The example access point in this chapter has three Ethernet interfaces: ath0, eth0, and eth1. Instead of bridging ath0 and eth0 to create the br0 LAN interface, ath0 and eth0 are going to be two separate LAN interfaces, and eth1 will still be the WAN interface. iptables will forward traffic between eth0 and eth0, and dnsmasq.conf will need some additional lines to handle the extra subnet.

This recipe assumes you are using either WPA-PSK or WPA-Enterprise with a separate RADIUS server. (See the previous recipes in this chapter to learn how to configure encryption and authentication.) You may create an open access point for testing by commenting out the two lines that control hostapd:

	##/etc/network/interfaces
	auto lo
	iface lo inet loopback

	auto ath0
	iface ath0 inet static
	        address 192.168.2.50
	        network 192.168.2.0
	        netmask 255.255.255.0
	        broadcast 192.168.2.255
	        post-down wlanconfig ath0 destroy
	        pre-up wlanconfig ath0 create wlandev wifi0 wlanmode ap
	        pre-up iwconfig ath0 essid "alrac-net" channel 01 rate auto
	        pre-up ifconfig ath0 up
	        pre-up sleep 3
	        up hostapd -B /etc/hostapd.conf
	        post-down killall hostapd

	auto eth0
	iface eth0 inet static
	       address 192.168.1.50
	       network 192.168.1.0
	       netmask 255.255.255.0
	       broadcast 192.168.1.255

	auto eth1
	iface eth1 inet static
	    address 12.169.163.241
	    gateway 12.169.163.1
	    netmask 255.255.255.0

	##/etc/dnsmasq.conf
	domain-needed
	bogus-priv
	local=/alrac.net/
	expand-hosts
	domain=alrac.net
	listen-address=127.0.0.1
	listen-address=192.168.1.50
	listen-address=192.168.2.50
	server=12.169.174.2
	server=12.169.174.3

	dhcp-range=lan,192.168.1.100,192.168.1.200,255.255.255.0,12h
	dhcp-range=wifi,192.168.2.100,192.168.2.200,255.255.255.0,12h
	dhcp-lease-max=100

	#default gateway
	dhcp-option=lan,3,192.168.1.50
	dhcp-option=wifi,3,192.168.2.50

	#DNS server
	dhcp-option=lan,6,192.168.1.50
	dhcp-option=wifi,6,192.168.2.50

	#assign static IP addresses
	dhcp-host=stinkpad,192.168.2.74,net:wifi
	dhcp-host=penguina,192.168.2.75,net:wifi
	dhcp-host=uberpc,192.168.1.76,net:lan
	dhcp-host=xena,192.168.1.10,net:lan

You’ll need to add a batch of iptables rules to your firewall script. See the Discussion for a complete example iptables firewall script.

Discussion

This iptables example forwards all traffic freely between your two LAN segments, and makes name services available to all. This is a liberal configuration with no restrictions.

Remember that broadcast traffic does not cross routes, and some network protocols are nonroutable, such as Samba and other NetBIOS traffic. All routable traffic, such as SSH, ping, mail and web servers, and so forth will travel between your subnets with no problems.

By routing between your wired and wireless network segments, your options are legion: limit the services available to either network segment, filter on individual hosts, do some fine-grained traffic shaping—anything you want to do is possible.

dnsmasq.conf uses RFC 2132 numbers to represent servers, so refer to it for a complete list. Some common servers are:

dhcp-option=2,[offset]

Time offset from UTC (Coordinated Universal Time). You’ll have to manually adjust this twice per year if you are afflicted with daylight saving time. But at least you’ll control everything from the server. For example, pacific standard time is written as dhcp-option=2,-28800, which equals UTC -8 hours.

dhcp-option=3,[IP address]

Send clients the default route. Use this when dnsmasq is not on the same box as your router.

dhcp-option=7,[IP address]

Syslog server.

dhcp-option=33, wifi,[destination IP address, routeraddress]

Assign a static route to the “wifi” group. You may list as many routes as you want. Each route is defined by a pair of comma-separated IP addresses.

dhcp-option=40,[domain]

NIS domain name.

dhcp-option=41,[IP address]

NIS domain server.

dhcp-option=42,[IPaddress]

NTP server.

dhcp-option=69,[IP address]

SMTP server.

dhcp-option=70,[IPaddress]

POP server.

dhcp-option=72,[IPaddress]

HTTP server.

Because our LAN routes pass through an iptables firewall with a default DROP policy, permitted traffic must be explicitly accepted and forwarded.

If you followed Chapter 3 to build your iptables firewall, don’t forget you can use /etc/init.d/firewall/stop|start|restart when you’re testing new rules.

Here is a complete example /usr/local/bin/fw-nat that gives the wired and wireless subnets nearly unlimited access to each other:

	#!/bin/sh
	#iptables firewall script for sharing a cable or DSL Internet
	#connection, with no public services

	#define variables
	ipt="/sbin/iptables"
	mod="/sbin/modprobe"
	LAN_IFACE="eth0"
	WAN_IFACE="eth1"
	WIFI_IFACE="ath0"

	#load kernel modules
	$mod ip_tables
	$mod iptable_filter
	$mod iptable_nat
	$mod ip_conntrack
	$mod ipt_LOG
	$mod ipt_limit
	$mod ipt_state
	$mod iptable_mangle
	$mod ipt_MASQUERADE
	$mod ip_nat_ftp
	$mod ip_nat_irc
	$mod ip_conntrack_ftp
	$mod ip_conntrack_irc

	# Flush all active rules and delete all custom chains
	$ipt -F
	$ipt -t nat -F
	$ipt -t mangle -F
	$ipt -X
	$ipt -t nat -X
	$ipt -t mangle -X

	#Set default policies
	$ipt -P INPUT DROP
	$ipt -P FORWARD DROP
	$ipt -P OUTPUT ACCEPT
	$ipt -t nat -P OUTPUT ACCEPT
	$ipt -t nat -P PREROUTING ACCEPT
	$ipt -t nat -P POSTROUTING ACCEPT
	$ipt -t mangle -P PREROUTING ACCEPT
	$ipt -t mangle -P POSTROUTING ACCEPT
	#this line is necessary for the loopback interface
	#and internal socket-based services to work correctly
	$ipt -A INPUT -i lo -j ACCEPT

	#Allow incoming SSH from the wired LAN only to the gateway box
	$ipt -A INPUT -p tcp -i $LAN_IFACE -s 192.168.1.0/24 --dport 22 \
	-m state --state NEW -j ACCEPT

	#Enable IP masquerading
	$ipt -t nat -A POSTROUTING -o $WAN_IFACE -j SNAT --to-source 12.34.56.789

	#Enable unrestricted outgoing traffic, incoming
	#is restricted to locally-initiated sessions only
	#unrestricted between WIFI and LAN
	$ipt -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
	$ipt -A FORWARD -i $WAN_IFACE -o $LAN_IFACE -m state --state \
	ESTABLISHED,RELATED -j ACCEPT
	$ipt -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -m state --state \
	NEW,ESTABLISHED,RELATED -j ACCEPT
	#$ipt -A FORWARD -i $LAN_IFACE -o $WIFI_IFACE -m state --state \
	NEW,ESTABLISHED,RELATED -j ACCEPT
	#$ipt -A FORWARD -i $WIFI_IFACE -o $LAN_IFACE -m state --state \
	NEW,ESTABLISHED,RELATED -j ACCEPT
	#$ipt -A FORWARD -i $WIFI_IFACE -o $WAN_IFACE -m state --state \
	NEW,ESTABLISHED,RELATED -j ACCEPT
	#$ipt -A FORWARD -i $WAN_IFACE -o $WIFI_IFACE -m state --state \
	ESTABLISHED,RELATED -j ACCEPT

	#Enable internal DHCP and DNS
	$ipt -A INPUT -p udp -i $LAN_IFACE -s 192.168.1.0/24 --dport 53 -j ACCEPT
	$ipt -A INPUT -p tcp -i $LAN_IFACE -s 192.168.1.0/24 --dport 53 -j ACCEPT
	$ipt -A INPUT -p udp -i $LAN_IFACE --dport 67 -j ACCEPT
	$ipt -A INPUT -p udp -i $WIFI_IFACE -s 192.168.2.0/24 --dport 53 -j ACCEPT
	$ipt -A INPUT -p tcp -i $WIFI_IFACE -s 192.168.2.0/24 --dport 53 -j ACCEPT
	$ipt -A INPUT -p udp -i $WIFI_IFACE --dport 67 -j ACCEPT

	#allow LAN to access router HTTP server
	$ipt -A INPUT -p tcp -i $LAN_IFACE --dport 443 -j ACCEPT
	$ipt -A INPUT -p tcp -i $WIFI_IFACE --dport 443 -j ACCEPT

	# Accept ICMP echo-request and time-exceeded
	$ipt -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
	$ipt -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
	$ipt -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT

	#Reject connection attempts not initiated from inside the LAN
	$ipt -A INPUT -p tcp --syn -j DROP

	echo "The firewall has now started up and is faithfully protecting your system"

See Also

  • Chapter 3

  • man 5 dhclient

  • dnsmasq.conf is a great help resource

  • dnsmasq home page (http://www.thekelleys.org.uk/dnsmasq/doc.html) is where you’ll find mailing list archives and excellent help documents

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.13. Probing Your Wireless Interface Card

Problem

Your wireless interface card came in a colorful box and wads of multilanguage documentation. But none of it gives you the technical specs that you really want, such as supported channels, encryption protocols, modes, frequencies—you know, the useful information.

Solution

Both wlanconfig, which is part of the MadWiFi driver package, and iwlist, which is part of wireless-tools, will probe your wireless card and tell you what it can do, like this command that displays what protocols the card supports:

	pyramid:~# wlanconfig ath0 list caps
	ath0=7782e40f<WEP,TKIP,AES,AES_CCM,HOSTAP,TXPMGT,SHSLOT,SHPREAMBLE,\
	TKIPMIC,WPA1,WPA2,WME>

This means this is a nice modern card that supports all of the important encryption and authentication protocols, and it can serve as an access point.

This command shows all of the channels and frequencies the card supports:

	pyramid:~# wlanconfig ath0 list chan

Find out what kind of keys your card supports:

	pyramid:~# iwlist ath0 key

Which card functions are configurable:

	pyramid:~# iwlist ath0 event

This particular card supports variable transmission power rates:

	pyramid:~# iwlist ath0 txpower

What bit-rates are supported?

	pyramidwrap:~# iwlist ath0 rate

The iwconfig command shows the card’s current configuration:

	pyramidwrap:~# iwconfig ath0

Discussion

What does this output mean?

	ath0=7782e40f<WEP,TKIP,AES,AES_CCM,HOSTAP,TXPMGT,SHSLOT,SHPREAMBLE,\
	TKIPMIC,WPA1,WPA2,WME>

It means this particular card supports WEP encryption, Temporal Key Integrity Pro-tocol (TKIP), Advanced Encryption Standard with Counter Mode with CBC-MAC Protocol (AES and AES_CCM), can function as an Access Point, has variable transmission power, supports TKIP Message Identity Check, WPA/WPA2, frame bursting, and Wireless Media Extensions.

SHSLOT and SHPREAMBLE stand for “short slot” and “short preamble,” which have to do with faster transmission speeds. Matthew Gast’s 802.11 Wireless Networks: The Definitive Guide (O’Reilly) tells you all about these.

See Also

  • Pyramid Linux does not include manpages, so you should install the applications in this chapter on a PC to obtain them, or rely on Google

  • wlanconfig is part of MadWiFi-ng

  • man 8 iwlist

  • man 8 wlanconfig

  • 802.11 Wireless Networks: The Definitive Guide, by Matthew Gast (O’Reilly)

4.14. Changing the Pyramid Router’s Hostname

Problem

Pyramid is a nice name, but you really want to change it to something else. You tried editing /etc/hostname, but the name reset to Pyramid after reboot. Arg! How do you make it what you want?

Solution

The files listed in /etc/rw/ are mounted in a temporary writeable filesystem, and are copied from /etc/ro at boot. /etc/hostname is symlinked to /rw/etc/hostname:

	pyramid:~# ls -l /etc/hostname
	lrwxrwxrwx 1 root root 18 Oct 30 2006 /etc/hostname -> ../rw/etc/hostname

So, you can make /etc/hostname immutable (remove the symlink to /rw/etc/ hostname), or edit /ro/etc/hostname.

Discussion

The filesystem is set up this way to reduce writes, because Compact Flash supports a limited number of writes.

You can use find to see which files in /etc are symlinks:

	pyramid:~# find /etc -maxdepth 1 -type l -ls
	  6051    0 lrwxrwxrwx  1 root     root      14 Oct  4 2006 /etc/mtab -> ../proc/
	mounts
	  6052    0 lrwxrwxrwx  1 root     root      21 Oct  4 2006 /etc/resolv.conf -> ../
	rw/etc/resolv.conf
	  6079    0 lrwxrwxrwx  1 root     root      30 Dec 31 2006 /etc/localtime -> /usr/
	share/zoneinfo/US/Pacific
	  6081    0 lrwxrwxrwx 1 root      root      18 Oct  4 2006 /etc/hostname -> ../rw/
	etc/hostname
	  6156    0 lrwxrwxrwx 1 root      root      15 Oct  4 2006 /etc/issue -> ../rw/
	etc/issue
	  6195    0 lrwxrwxrwx 1 root      root      17 Oct  4 2006 /etc/zebra -> ../usr/
	local/etc/
	  6227    0 lrwxrwxrwx 1 root      root      16 Oct  4 2006 /etc/resolv -> ../rw/
	etc/resolv
	  6426    0 lrwxrwxrwx 1 root      root      19 Oct  4 2006 /etc/issue.net -> ../
	rw/etc/issue.net
	  6427    0 lrwxrwxrwx 1 root      root      17 Oct  4 2006 /etc/adjtime -> ../rw/
	etc/adjtime

See Also

  • man 1 find

  • man 1 ls

4.15. Turning Off Antenna Diversity

Problem

Your wireless interface supports using two antennas, but you’re using just one. You know that this means half of your broadcast and unicast packets are hitting a dead end, which can hurt performance. How do you send power only to one antenna?

Solution

Set Pyramid’s filesystem to read/write, then add the following lines to /etc/sysctl.conf:

	dev.wifi0.diversity = 0
	dev.wifi0.rxantenna = 1
	dev.wifi0.txantenna = 1

Then, load the new configuration:

	pyramid:~# /sbin/sysctl -p

If the antenna is connected to the second port, just change 1 to 2 and reload sysctl.

Discussion

The Linux kernel sees the wireless interface as wifi0, which you can see by running dmesg | grep wifi. The MadWiFi driver creates a virtual interface named ath0.

Using two antennas might improve the quality of your wireless service, or it might not. Only one is used at a time, the one with the stronger signal.

Polarization diversity is when one antenna receives a stronger signal because it is lined up differently than the other one. Spatial diversity refers to distance between two antennas. A few inches might make a difference because of reflections, fading, physical barriers, and interference.

The radio hardware evaluates the signal strength at the beginning of the transmission and compares both antennas. Then, it selects the stronger antenna to receive the rest of the transmission. The only user-configurable options are to turn diversity on or off.

Multiple-input/multiple-output (MIMO) technology promises higher data rates and better performance by using both antennas at the same time. Different vendors mean different things when they say MIMO.

Some are referring to multiple data streams, while others use it to mean plain old channel bonding. The goal is the same: more bandwidth and reliability for delivering video, VoIP, and other high-demand applications.

There is considerable controversy and endless arguments over antenna placement, what kind of antennas to use, and how many. Pointless arguments can be fun; when that gets dull, whip out your 802.11 network analyzer and collect some useful data to help you figure it out.

See Also

  • Chapter 16, “802.11 Hardware,” in 802.11 Wireless Networks: The Definitive Guide, Second Edition, by Matthew Gast (O’Reilly)

  • Chapter 24, “802.11 Network Analysis,” in 802.11 Wireless Networks: The Definitive Guide, Second Edition

4.16. Managing dnsmasq’s DNS Cache

Problem

You know that dnsmasq automatically creates a local DNS cache. How do you know it’s working? How do you see what’s in it, and how do you flush it when you’re making changes to DNS and want to be sure it’s caching fresh data?

Solution

It’s easy to see if it’s working. From any Linux client or from your Pyramid server, query any Internet site with the dig command twice:

	$ dig oreilly.com
	<snip much output>
	;; Query time: 75 msec
	;; SERVER: 192.168.1.50#53(192.168.1.50)
	$ dig oreilly.com
	<snip much output>
	;; Query time: 3 msec
	;; SERVER: 192.168.1.50#53(192.168.1.50)

The second request is answered from your local dnsmasq cache, so it is faster. This also verifies that your clients are querying the correct DNS server.

What if you want to flush dnsmasq’s cache? Just restart it:

	pyramid:~# killall dnsmasq

dnsmasq is controlled from /etc/inittab, so it will automatically restart.

To view the contents of the cache, first open /etc/inittab and comment out the line that starts dnsmasq:

	pyramid:~# /sbin/rw
	pyramid:~# nano /etc/inittab
	# dnsmasq. This should always be on.
	# DN:23:respawn:/sbin/dnsmasq -k > /dev/null 2>&1

Tell init to reread inittab, stop the active dnsmasq process, then start dnsmasq in debugging mode:

	pyramid:~# telinit q
	pyramid:~# killall dnsmasq
	pyramid:~# dnsmasq -d

This runs it in the foreground, so the next thing you need to do is open a second SSH session, or log in on the serial console, and run this command:

	pyramid:~# killall -USR1 dnsmasq

This dumps the cache contents to your first screen. You should see just your localhosts. This line tells you your cache is empty:

	dnsmasq: cache size 150, 0/0 cache insertions re-used unexpired cache entries.

Start dnsmasq again, visit some web sites from client PCs to generate some cache entries, then dump the cache again to see what they look like. You should see a lot more entries now. When you’re finished, put /etc/inittab back the way it was, and rerun telinit q and /sbin/ro.

Discussion

It’s unlikely that you’ll ever have to do anything with your dnsmasq cache because it’s pretty much self-maintaining. There are three options in /etc/dnsmasq.conf for configuring cache behavior:

local-ttl

The default is zero, which means do not cache responses from /etc/hosts and your DHCP leases. This ensures fresh local data all the time. If your network is stable and doesn’t have DHCP clients popping in and out a lot, you can set a Time To Live (TTL) value to speed up local look ups.

no-negcache

Do not cache negative responses. Caching negative responses speeds up performance by caching “no such domain” responses, so your clients don’t wait for additional lookups to fail. dnsmasq handles negative caching well, so you shouldn’t disable negative caching unless it causes problems.

cache-size

The default is 150 names. The maximum is around 2,000. Because the cache is stored in RAM, having a too large cache will hurt router performance without appreciable gain. 150 is just fine for most sites; I wouldn’t go over 300.

You are at the mercy of the administrators of the authoritative servers for domains that you visit. If they make changes to their DNS without setting short TTLvalues, stale data will be cached all over the Internet until their TTLs expire. It can be helpful to flush your dnsmasq cache when you’re debugging DNS and trying to figure out if a DNS problem is local or remote.

Here are some examples of the output you’ll see. This is an empty cache showing only local DNS:

	pyramidwrap:~# dnsmasq -d
	dnsmasq: started, version 2.23 cachesize 150
	dnsmasq: compile time options: IPv6 GNU-getopt ISC-leasefile no-DBus
	dnsmasq: DHCP, IP range 192.168.1.100 -- 192.168.1.200, lease time 10h
	dnsmasq: using local addresses only for domain alrac.net
	dnsmasq: read /etc/hosts - 4 addresses
	dnsmasq: reading /etc/resolv.conf
	dnsmasq: using nameserver 12.169.174.3#53
	dnsmasq: using nameserver 12.169.174.2#53
	dnsmasq: using local addresses only for domain alrac.net
	dnsmasq: cache size 150, 0/0 cache insertions re-used unexpired cache entries.
	dnsmasq: Host                    Address                        Flags     Expires
	dnsmasq: stinkpad.alrac.net     192.168.1.102                  4FRI   H
	dnsmasq: localhost              127.0.0.1                      4F I   H
	dnsmasq: xena.alrac.net         192.168.1.10                   4FRI   H
	dnsmasq: pyramid.alrac.net      192.168.1.50                   4FRI   H
	dnsmasq: stinkpad               192.168.1.102                  4F I   H
	dnsmasq: xena                   192.168.1.10                   4F I   H
	dnsmasq: localhost.alrac.net    127.0.0.1                      4FRI   H
	dnsmasq: pyramid                192.168.1.50                   4F I   H

This is a snippet from a populated cache:

	dnsmasq: cache size 150, 0/178 cache insertions re-used unexpired cache entries.
	dnsmasq: Host                       Address           Flags     Expires
	dnsmasq: stinkpad.alrac.net        192.168.1.102     4FRI   H
	dnsmasq: localhost                 127.0.0.1         4F I   H
	dnsmasq: i.cnn.net                 64.236.16.137     4F        Wed Jan 24 15:36:42
	2007
	dnsmasq: i.cnn.net                 64.236.16.138     4F        Wed Jan 24 15:36:42
	2007
	dnsmasq: bratgrrl.com              67.43.0.135       4F        Wed Jan 24 17:45:49
	2007
	dnsmasq: a.tribalfusion.com        204.11.109.63     4F        Wed Jan 24 15:29:08
	2007
	dnsmasq: a.tribalfusion.com        204.11.109.64     4F        Wed Jan 24 15:29:08
	2007
	dnsmasq: ad.3ad.doubleclick.net    216.73.87.52      4F        Wed Jan 24 15:27:29
	2007
	dnsmasq: ads.cnn.com               64.236.22.103     4F        Wed Jan 24 16:21:41
	2007

Table 4-1 shows what the flags mean.

  • Both F and R may be set for names from DHCP or /etc/hosts.

Table 4-1. dnsmasq cache flags and their meanings

Flag

Meaning

4

IPv4 address

6

IPv6 address

C

CNAME

F

Forward (name → address) mapping

R

Reverse (address → name) mapping

I

Immortal (no expiry time)

D

Originates from DHCP

N

Negative (name known not to have address)

X

No such domain (name known not to exist)

H

Originates from /etc/hosts

See Also

  • man 8 dnsmasq contains a wealth of helpful information about all the available command-line options, many of which are also dnsmasq.conf options

  • dnsmasq.conf is also a great help resource

  • dnsmasq home page (http://www.thekelleys.org.uk/dnsmasq/doc.html) is where you’ll find mailing list archives and excellent help documents

  • Chapter 24, “Managing Name Resolution,” in Linux Cookbook, by Carla Schroder (O’Reilly)

4.17. Managing Windows’ DNS Caches

Problem

You know that Windows 2000, XP, and 2003 Server include DNS resolver caches by default. Which is a big surprise to most Windows users, who sometimes get stuck with stale data and don’t understand why some addresses are not resolving correctly. Most of the time you don’t even have to think about it, but when you’re making changes, you want to be sure that your clients are receiving fresh DNS information. How do you handle this?

Solution

On Windows clients, open a DOS window and run this command to see the contents of the cache:

	C:\> ipconfig /displaydns | more

This command clears the cache:

	C:\> ipconfig /flushdns

The default TTL is 86,400 seconds, or one day, for positive responses. Answers to negative queries are stored for 300 seconds (5 minutes). You may change these values, or disable caching entirely by editing the Windows Registry. On Windows 2000, open the Registry Editor and change the TTL for positive entries by creating or modifying the DWORD value in:

	HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters
	DWORD: MaxCacheEntryTtlLimit
	Value: 14400

14,400 seconds is four hours, which is typical for most ISPs these days. 0 disables all caching. Be sure you enter your values as Decimal Base, not Hexadecimal Base.

Disable negative answers with this key:

	HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters
	DWORD: NegativeCacheTime
	Value: 0

On Windows XP and 2003, change the TTL for positive entries with a different DWORD:

	HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\Dnscache\Parameters
	DWORD:  MaxCacheTtl
	Value: 14400

Turn off negative caching with this one:

	HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters
	DWORD:  MaxNegativeCacheTtl
	Value: 0

You may disable caching entirely by setting both values to zero. Reboot, as always, to activate the changes.

Discussion

Linux clients do not activate their own DNS caches by default; you have to set these up on purpose. Client-side caching is a nice thing that speeds up lookups. All those caches cause problems only when DNS is changed and the caches get stale.

See Also

  • The documentation for your particular flavors of Windows; a quick Google search on “windows dns cache” should get you all the information you need

4.18. Updating the Time at Boot

Problem

You have one of those newfangled routerboards that doesn’t have a CMOS battery. BIOS settings are written to nonvolatile RAM, but the time and date are lost with every power-cycle. How do you make it set the time correctly at boot?

Solution

With good ole ntpdate. First, edit /etc/default/ntp-servers so that it points to pool.ntp.org:

	# /sbin/rw
	# nano /etc/default/ntp-servers
	NTPSERVERS="pool.ntp.org"

Then create a startup link so it will run at boot:

	# ln /etc/init.d/ntpdate /etc/rc2.d/S90ntpdate

Now every time you boot up your routerboard, it will set the correct time. You can verify this with the date command:

	# date
	Mon Jan 29 20:52:50 UTC 2007

Discussion

If you are familiar with the NTP documentation, you’re aware that the fine NTP folks keep trying to get rid of ntpdate and replace it with the nptd-g command. However, ntpdate still works best for large time corrections.

See Also

  • man 1 ntpdate

  • Chapter 19, “Keeping Time with NTP,” in Linux Cookbook, by Carla Schroder (O’Reilly)

Get Linux Networking Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.