A user's rules are loaded into a unique anchor point by authpf. The anchor is named by combining the username and the authpf process-id in the username(PID) format. Each user's anchor is stored within the authpf anchor which is in turn anchored to the main ruleset. The fully qualified anchor path then becomes:
The rules that authpf loads can be configured on a per-user or global basis.main_ruleset/authpf/username(PID)
Example uses of authpf include:
The authpf tool logs the username and IP of each user who authenticates successfully, as well as the start and end times of their login session via syslogd(8). By using this information, an administrator can determine who was logged in when and also make users accountable for their network traffic.
The following configuration directives can be placed in authpf.conf:
Wherever the anchor rule is placed within the ruleset is where PF will branch off from the main ruleset to evaluate the authpf rules.anchor "authpf/*"
The first file contains rules that are only loaded when the user $USER (which is replaced with the user's username) logs in. The per-user rule configuration is used when a specific user, such as an administrator, requires a set of rules that is different than the default set. The second file contains the default rules which are loaded for any user that doesn't have their own authpf.rules file. If the user-specific file exists, it will override the default file. At least one of the files must exist or authpf will not run.
Rules have the same syntax as in any other PF ruleset with one exception: authpf allows for the use of two predefined macros:
It's recommended practice to use the $user_ip macro to only permit traffic through the gateway from the authenticated user's computer.
In addition to the $user_ip macro, authpf will make use of the authpf_users table (if it exists) for storing the IP addresses of all authenticated users. Be sure to define the table before using it:
This table should only be used in rules that are meant to apply to all authenticated users.table <authpf_users> persist pass in on $ext_if proto tcp from <authpf_users> to port smtp
Conversely, it's also possible to allow only specific users access by placing usernames in the /etc/authpf/authpf.allow file. If the /etc/authpf/authpf.allow file does not exist or "*" is entered into the file, then authpf will permit access to any user who successfully logs in via SSH as long as they are not explicitly banned.
If authpf is unable to determine if a username is allowed or denied, it will print a brief message and then disconnect the user. An entry in /etc/authpf/banned/ always overrides an entry in /etc/authpf/authpf.allow.
This message can be supplemented by putting a custom message in /etc/authpf/authpf.message. The contents of this file will be displayed after the default welcome message.Hello charlie. You are authenticated from host "198.51.100.10"
There are a couple ways of assigning authpf as a user's shell:
Login classes are created in the login.conf(5) file. OpenBSD comes with an authpf login class defined as:
Users are assigned to a login class by editing the class field of the user's passwd(5) database entry. One way to do this is with the chsh(1) command.authpf:\ :welcome=/etc/motd.authpf:\ :shell=/usr/sbin/authpf:\ :tc=default:
Here the user charlie is logged in from the machine 192.168.1.3. By sending a SIGTERM signal to the authpf process, the user can be forcefully logged out. Any rules loaded for the user will be removed and any stateful connections the user has open will be killed.# ps -ax | grep authpf 23664 p0 Is+ 0:00.11 -authpf: charlie@192.168.1.3 (authpf)
# kill -TERM 23664
The /etc/authpf/authpf.rules file contains the following rules:
The administrative user charlie needs to be able to access the campus SMTP and POP3 servers in addition to surfing the web and using SSH. The following rules are set up in /etc/authpf/users/charlie/authpf.rules:wifi_if = "wi0" pass in quick on $wifi_if \ proto tcp from $user_ip to any port { ssh, http, https }
The main ruleset -- located in /etc/pf.conf -- is set up as follows:wifi_if = "wi0" smtp_server = "10.0.1.50" pop3_server = "10.0.1.51" pass in quick on $wifi_if \ proto tcp from $user_ip to $smtp_server port smtp pass in quick on $wifi_if \ proto tcp from $user_ip to $pop3_server port pop3 pass in quick on $wifi_if \ proto tcp from $user_ip to port { ssh, http, https }
The ruleset is very simple and does the following:wifi_if = "wi0" ext_if = "fxp0" dns_servers = "{ 10.0.1.56, 10.0.2.56 }" table <authpf_users> persist block drop all pass out quick on $ext_if \ inet proto { tcp, udp, icmp } from { $wifi_if:network, $ext_if } pass in quick on $wifi_if \ inet proto tcp from $wifi_if:network to $wifi_if port ssh pass in quick on $wifi_if \ inet proto { tcp, udp } from <authpf_users> to $dns_servers port domain anchor "authpf/*" in on $wifi_if
The idea behind the main ruleset is to block everything and allow the least amount of traffic through as possible. Traffic is free to flow out on the external interface but is blocked from entering the wireless interface by the default deny policy. Once a user authenticates, their traffic is permitted to pass in on the wireless interface and to then flow through the gateway into the rest of the network. The quick keyword is used throughout so that PF doesn't have to evaluate each named ruleset when a new connection passes through the gateway.