Hack 65 Secure a Wireless Network Using PF

figs/expert.gif figs/hack65.gif

Protect your private wireless network from unauthorized use.

The abundance of 802.11 wireless networks has raised an important question. How can you secure a wireless network so that only recognized systems can use it?

Wireless Encryption Protocol (WEP) and MAC access lists offer some protection against unauthorized users; however, they can be difficult to maintain. With OpenBSD's PF, we can maintain tables of recognized clients and update those tables with a single shell command. Known clients can access the Internet; unknown clients will only ever see a web page informing them that this is a private network.

For this hack, we will use dhcpd, PF, and Apache.

6.13.1 DHCP Configuration

We'll use a simple DHCP configuration in /etc/dhcpd.conf like this:

shared-network GUEST-NET {         max-lease-time 300;         default-lease-time 120;         option     domain-name-servers;         option     routers;    subnet netmask {           range;      } }

In this case, we're using the subnet Our firewall and NAT gateway is, and it's also configured as the DNS server for our network.

We've allocated a range of IP addresses ( to for distribution on a first-come, first-served basis to any host that requests an address via DHCP. Anybody that connects to our network will be able to request a valid IP address in that range. The security will come from our PF configuration.

6.13.2 PF Configuration

OpenBSD has an excellent FAQ on PF, along with an example of how to write a ruleset for a home or small office network. We'll use this example as a template.

We'll start with the sample PF configuration that allows any host on the internal interface (represented by the macro $int_if) full access to the Internet. Then, we will modify the rules in /etc/pf.conf so that only authorized hosts have access and set up a web server to respond to requests from unauthorized hosts. We will also allow unauthorized hosts direct access to our DNS server, to simplify our rules and to avoid more complex split-horizon DNS configuration.

First, let's create the table for authorized hosts and macros for the web server and the DNS server:

auth_server = " port 8080" dns_server  = "" table <authorized_hosts> {, };

These lines go near the top of /etc/pf.conf, before any queue, NAT, or filter rules.

We've initialized the table to contain the addresses of our NAT gateway and one other host,, a statically configured box we'd like to have access to as well. While PF has a ruleset loaded, we can add a host to the table on the fly:

# pfctl -t authorized_hosts -Tadd

We can also delete a host:

# pfctl -t authorized_hosts -Tdelete

and list all the authorized hosts:

# pfctl -t authorized_hosts -Tshow

Now we need to modify the filter rules so only our authorized hosts have access. These rules allow any host on our network to have access:

pass in  on $int_if from $int_if:network to any             keep state pass out on $int_if from any             to $int_if:network keep state

We'll change them like this to use our table:

pass in  on $int_if from <authorized_hosts> to any keep state pass out on $int_if from any to <authorized_hosts> keep state

Right after those rules, we'll add the following rules to allow unauthorized hosts to access our web server and DNS server:

pass in  on $int_if proto tcp from !<authorized_hosts> to $auth_server pass in  on $int_if proto {tcp, udp} from any to $dns_server port domain \     keep state

Now any host in the authorized_hosts table will have full access to the Internet. Any other hosts will only be able to lookup names and reach the web server. We'll add some simple rules so unauthorized users will see a rejection page if they try to go to any web site.

In the NAT section, we'll add this rule:

rdr on $int_if proto tcp from !<authorized_hosts> to any port www -> \     $auth_server

This rule redirects any unknown host attempting to access a remote machine on the www port to the web server that will return the rejection page. We could install a web server on the firewall box or on some separate machine. In my case, I'll run Apache on the firewall, listening at and port 8080, so it won't be confused with any other web servers I'm running.

6.13.3 Apache Configuration

Apache is installed by default with OpenBSD, so we'll reconfigure it to listen on port 8080 of the gateway (with IP address and return the same page for every URL requested. (Apache is also available in the FreeBSD ports collection and NetBSD packages collection.)

First, we'll enable Apache with the httpd_flags parameter in /etc/rc.conf. Next, we need to edit Apache's configuration file, /var/www/conf/httpd.conf. Find the Listen directive and add Next, create a VirtualHost entry like this:

<VirtualHost>   ServerAdmin none   DocumentRoot /var/www/auth   ErrorDocument 404 /index.html </VirtualHost>

This tells Apache to listen to the appropriate port and IP address. For every incoming request, Apache will try to serve a page beneath the given directory. Any time it can't find a page, it will serve the index.html page instead.

We don't have either yet, so create the directory /var/www/auth and place an index.html like this in it:

<html>   <head>     <title>Unauthorized -- This is a private network</title>   </head>   <body>     <h1>Unauthorized</h1>     <p>This is a private network and you are not authorized to use          it.</p>   </body> </html>

6.13.4 Putting it All Together

Start or restart dhcpd, pf, and Apache like this, where [interfaces] is the list of interfaces on which you provide DHCP:

# kill `cat /var/run/dhcpd.pid`; dhcpd -q  [interfaces] # pfctl -f /etc/pf.conf # apachectl stop && apachectl start

Congratulations! When a new host connects to your network, it should request an address with DHCP. If so, it will receive an address in the range of to If the assigned address is not already in the authorized_hosts table, any time that host attempts to load a web page it will receive your Unauthorized page. The firewall will silently discard any packets destined for any other ports outside of your network.

If you want to allow a new host to use your network, just use pfctl to add it to the table. To make the change permanent, add the address or a range of addresses to the table definition in /etc/pf.conf, or even create an external file listing allowed addresses. See the PF FAQ section on tables for more.

6.13.5 Security Concerns

This technique only controls the ability of hosts on your network to route packets through your firewall. It will not protect other hosts on the same subnet from unauthorized access, so they should have reasonable local firewall rules. A wise approach might be to build a firewall with three interfaces: one external and two internal. One internal subnet would host your regular machines, and the other subnet would allow guest access with this technique, separating the subnets with additional PF rules.

6.13.6 Hacking the Hack

Running the web server on the firewall is a simple approach. However, you can redirect to another host, such as a dedicated authentication server. For simplicity, this server should not be on the $int_if:network subnet; if it is, the redirection becomes more complicated. The PF FAQ has a section devoted to port forwarding in this manner.

I used Apache because it is installed by default with OpenBSD and because its configuration is trivial in this case. Almost any HTTP server will do the job, though.

6.13.7 See Also

  • OpenBSD's PF FAQ (http://www.openbsd.org/faq/pf/)

  • NoCat.net's NoCatAuth, authentication software for open wireless nodes (http://nocat.net/)

BSD Hacks
BSD Hacks
ISBN: 0596006799
EAN: 2147483647
Year: 2006
Pages: 160
Authors: Lavigne

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net