Hack 35 Create an Authenticated Gateway

figs/moderate.gif figs/hack35.gif

Use PF to keep unauthorized users off the network.

Firewalling gateways have traditionally been used to block traffic from specific services or machines. Instead of watching IP addresses and port numbers, an authenticated gateway allows you to regulate traffic to or from machines based on a user's credentials. With an authenticated gateway, a user will have to log in and authenticate himself to the gateway in order to gain access to the protected network. This can be useful in many situations, such as restricting Internet access or restricting a wireless segment to be used only by authorized users.

With the release of OpenBSD 3.1, you can implement this functionality through the use of PF and the authpf shell. Using authpf also provides an audit trail by logging usernames, originating IP addresses, and the time that they authenticated with the gateway, as well as when they logged off the network.

To set up authentication with authpf, you'll first need to create an account on the gateway for each user. Specify /usr/sbin/authpf as the shell, and be sure to add authpf as a valid shell to /etc/shells. When a user logs in through SSH, authpf will obtain the user's name and IP address through the environment. After doing this, a template file containing NAT and filter rules is read in, and the username and IP address are applied to it. The resulting rules are then added to the running configuration. When the user logs out (i.e., types ^C), the rules that were created are unloaded from the current ruleset. For user-specific rule templates, authpf looks in /etc/authpf/users/$USER/authpf.rules. Global rule templates are stored in /etc/authpf/authpf.rules. Similarly, NAT entries are stored in authpf.nat, in either of these two directories. When a user-specific template is present for the user who has just authenticated, the template completely replaces the global rules, instead of just adding to them. When loading the templates, authpf will expand the $user_ip macro to the user's current IP address.

For example:

pass in quick on wi0 proto { tcp, udp } from $user_ip to any \

  keep state flags S/SA

This particular rule will pass in all traffic on the wireless interface from the newly authenticated user's IP address. This works particularly well with a default deny policy, where only the initial SSH connection to the gateway and DNS have been allowed from the authenticating IP address.

You could be much more restrictive and allow only HTTP-, DNS-, and email-related traffic through the gateway:

pass in quick on wi0 proto tcp from $user_ip to any \

  port { smtp, www, https, pop3, pop3s, imap, imaps } \

  keep state flags S/SA

pass in quick on wi0 proto udp from $user_ip to any port domain

After the template files have been created, you must then provide an entry point into pf.conf for the rules that authpf will create for evaluation by PF. These entry points are added to your pf.conf with the various anchor keywords:

nat-anchor authpf

rdr-anchor authpf

binat-anchor authpf

anchor authpf

Note that each anchor point needs to be added to the section it applies to?you cannot just put them all at the end or beginning of your pf.conf. Thus the nat-anchor, rdr-anchor, and binat-anchor entries must go into the address translation section of the pf.conf. Likewise, the anchor entry, which applies only to filtering rules, should be added to the filtering section.

When a user logs into the gateway, he should now be presented with a message like this:

Hello andrew, You are authenticated from host ""

The user will also see the contents of /etc/authpf/authpf.message if it exists and is readable.

If you examine /var/log/daemon, you should also see log messages similar to these for when a user logs in and out:

Dec  3 22:36:31 zul authpf[15058]: allowing, \

  user andrew

Dec  3 22:47:21 zul authpf[15058]: removed, \

  user andrew- duration 650 seconds

Note that since it is present in /etc/shells, any user that has a local account is capable of changing his shell to authpf. If you want to ensure that the user cannot do this, you can create a file named after his username and put it in the /etc/authpf/banned directory. The contents of this file will be displayed when he logs into the gateway. On the other hand, you can also explicitly allow users by listing their usernames, one per line, in /etc/authpf/authpf.allow. However, any bans that have been specified in /etc/authpf/banned take precedence over entries in authpf.allow.

Since authpf relies on the SSH session to determine when the rules pertaining to a particular user are to be unloaded, care should be taken in configuring your SSH daemon to time out connections. Timeouts should happen fairly quickly, to revoke access as soon as possible once a connection has gone stale. This also helps prevent connections to systems outside the gateway from being held open by those conducting ARP spoof attacks.

You can set up OpenSSH to guard against this by adding these to lines to your sshd_config:

ClientAliveInterval 15

ClientAliveCountMax 3

This will ensure that the SSH daemon will send a request for a client response 15 seconds after it has received no data from the client. The ClientAliveCountMax option specifies that this can happen three times without a response before the client is disconnected. Thus, after a client has become unresponsive, it will be disconnected after 45 seconds. These keepalive packets are sent automatically by the SSH client software and don't require any intervention on the part of the user.

Authpf is very powerful in its flexibility and integration with PF, OpenBSD's native firewalling system. It is easy to set up and has very little performance overhead, since it relies on SSH and the operating system to do authentication and manage sessions.