PacketFence Revisited

by Regis Balzard

In our initial PacketFence article in the April 2007 issue of LJ, we introduced the great network access control (NAC) solution that rivals the best ones on the market. On that occasion, we covered ARP-based isolation, which works relatively well for small networks.

Unfortunately, ARP-based isolation can't really scale to many thousands of nodes and is relatively easy to bypass with a simple static ARP table. Thus, we, at Inverse, decided to improve PacketFence by adding a VLAN-based isolation mode. This addition, combined with other enhancements, makes the solution suitable for large-scale networks.

Introduction to VLAN Isolation

The purpose of PacketFence's VLAN isolation is to assign any device connected to the network to an appropriate VLAN based on its MAC, registration and violation status. A simple scenario would be that every new device belongs to a registration VLAN, a registered and violation-free device belongs to a “normal” VLAN and a device with open violations belongs to an isolation VLAN. If the isolation and registration VLANs are not routed to the “normal” VLAN, PacketFence fully isolates the new device, and any device that violates network policy, from the regular network, efficiently preventing any attack or virus propagation. Of course, real networks are a bit more complicated, and VoIP phones may not end up in the same VLAN as regular computers or servers. But, whatever your network's VLAN design, PacketFence is up to the task.

In order for the VLAN isolation code to work properly, you must use manageable switches. In particular, the switches must provide a means to change a port's VLAN remotely and must be able to send SNMP (Simple Network Management Protocol) traps to PacketFence. SNMP traps include the switch's IP address; the port number and, depending on the trap type, could include the port status (for example, “up” when a device has been connected and “down” when disconnected); the MAC address of the device (mostly for MAC notification and security violation traps); the number of MACs connected to the switch port and so on.

Figure 1. PacketFence's Handling of SNMP Traps

When a switch sends an SNMP trap to PacketFence, the snmptrapd dæmon receives it and writes it to the log file /usr/local/pf/contrib/log/snmptrapd.log. PacketFence's setVlanOnTrapd dæmon continuously reads this log file and, for every new trap, determines whether it needs to change a port's VLAN. If this is the case, it sends the appropriate SNMP commands to the switch.

A crucial part of VLAN isolation is knowing when a device connects to or disconnects from the network. In early 2006, we started the development of the VLAN isolation code by supporting two very basic SNMP traps: linkup and linkdown traps. The vast majority of switch vendors support these two traps, which made our implementation immediately usable on a wide variety of networking hardware. Unfortunately, simply relying on linkup and linkdown traps has its downsides, from both a performance and a functional perspective, including:

  • Because a switch needs to see some network traffic on a port to determine the MAC address of the connecting device, linkup traps cannot include any MAC address. PacketFence's setVlanOnTrapd must, therefore, repeatedly query the switch after every linkup trap in order to determine the MAC address of the newly connected device, which introduces some overhead.

  • Most VoIP phones contain a built-in switch to connect a PC. The switch sends the linkup trap when you connect the phone; when you connect the PC to the phone, the switch won't send a second linkup trap. Therefore, in this deployment scenario, relying solely on linkup and linkdown traps does not provide enough information to setVlanOnTrapd to work correctly.

One possible solution to address these issues is MAC notification traps. Every time a switch learns a MAC address on a port, it sends a “MAC learned” trap that includes the MAC address. And, of course, PacketFence now also supports MAC notification traps.

In addition to assigning an appropriate VLAN to devices when they connect to the network, PacketFence also isolates devices already connected to the network when they violate the network policy. Two different options are available:

  • PacketFence can briefly disconnect a device from the network by administratively shutting down the switch port and re-opening it soon after. In this case, the switch sends a linkdown, followed by a linkup trap. When PacketFence receives the linkup trap, it determines that the device has an open violation and switches the port to the isolation VLAN. On the computer side, the network adapter notices that the network link went down and automatically renews its IP address—this time in the isolation VLAN. PacketFence's captive portal then informs the user that he or she has been isolated.

  • Administratively shutting down a switch port can be problematic when using VoIP phones, as doing so might end a call. If PacketFence has access to the isolation VLAN, you don't actually need to shut down the port. Changing the port's VLAN and doing some ARP spoofing generally are sufficient to make the captive portal available to the user.

So far, we've mentioned only the registration and isolation VLANs, but PacketFence uses a third VLAN, the MAC detection VLAN. This VLAN, which is the default one of every port, must not contain access to any DHCP server and could be seen as an “empty” VLAN. It exists to allow the switch to learn the MAC address of a newly connected device before it obtains an answer from a DHCP server.

Example Installation

Install PacketFence 1.7 from www.packetfence.org. If you are using Red Hat EL5 or CentOS5, the easiest way to do so is to install the official RPM.

In this example, we set up VLAN isolation on a Cisco Catalyst 2960 switch (IP address 192.168.0.3). The PacketFence server's IP address is 192.168.0.10. Let's further assume that you are using the following VLANs and that these already have been created on your switch:

  1. “normal” VLAN

  2. isolation VLAN

  3. registration VLAN

  4. MAC detection VLAN

Enable the SNMP traps globally on the switch with the following commands:

snmp-server enable traps snmp authentication linkdown linkup
snmp-server enable traps mac-notification
snmp-server host 192.168.0.10 version 2c public mac-notification snmp
mac-address-table notification interval 0
mac-address-table notification
mac-address-table aging-time 300

Then, configure every access port PacketFence should be handling with the following:

switchport access vlan 4
switchport mode access
snmp trap mac-notification added
spanning-tree portfast

Edit the VLAN isolation configuration file /usr/local/pf/conf/switches.conf, so that it contains the correct SNMP community strings. Then, adjust the VLAN definition as follows:

vlans = 1,2,3,4
normalVlan = 1
isolationVlan = 2
registrationVlan = 3
macDetectionVlan = 4

And, finally, add a new section for your switch:

[192.168.0.3]
ip = 192.168.0.3
type = Cisco::Catalyst_2960
mode = production
uplink = 23,24

Next, you can do a communication test between PacketFence and the switch:

/usr/local/pf/bin/pfcmd_vlan -getVlan -switch 192.168.0.3 -ifIndex 10001

The next test is to determine whether the switch can send SNMP traps to PacketFence. Start snmptrapd:

service snmptrapd start

and observe the log file:

tail -f /usr/local/pf/logs/snmptrapd.log

Every time a device connects to and disconnects from the network, you should see a new line in the log file.

Now, configure PacketFence's access to VLAN 1, 2 and 3. Set the configuration of the switch port that PacketFence plugs into to “trunk mode”, and allow packets in VLAN 1 to pass through the switch without tagging. On the PacketFence server, add two new NICs that read and write 802.1q tagged packets for VLAN 2 and 3. Don't forget to add these new NICs to your configuration file /usr/local/pf/conf/pf.conf.

To simplify the installation, configure a DHCP service on the PacketFence box for VLANs 2 and 3. The DHCP server should return its own (VLAN-specific) IP address as both the gateway and the DNS server. Last but not least, set up a “fake” DNS service for VLANs 2 and 3 that responds to all queries with its own IP address. Now, verify that a host connected to the registration VLAN is able to obtain an IP address and that whatever DNS query it sends, PacketFence answers with its own IP.

If all these tests work fine, you can start setVlanOnTrapd:

service setVlanOnTrapd start

and look at the log file to verify that your devices, upon connection to the switch, are assigned to the correct VLAN:

tail -f /usr/local/pf/logs/setvlanontrapd.log

This setup should be transparent for already-registered devices, because they end up in the “normal” VLAN; unregistered devices will be assigned to the registration VLAN where all they can access is the PacketFence server that will show the captive portal with the registration screen.

Introduction to Isolation in Wireless Networks

PacketFence also integrates very well with wireless networks. As for its wired counterpart, the switch, a wireless Access Point (AP) needs to implement some specific features in order for the integration to work perfectly. In particular, the AP needs to support the following:

  • Several SSIDs with several VLANs inside each SSID.

  • Authentication against a RADIUS server.

  • Dynamic VLAN assignment (through RADIUS attributes).

  • SNMP deauthentication traps.

  • The deauthentication of an associated station.

Figure 2. How PacketFence Integrates with Wireless Networks

We then can configure two SSIDs on the AP, the first one reserved for visitors and unregistered clients. In this SSID, communications will not be encrypted, and users will connect either to the registration VLAN or the visitor's VLAN (depending on their registration status). The second SSID will allow encrypted communications for registered users. The VLANs here are the “normal” VLAN and the isolation VLAN (if ever there are open violations for the MAC).

Example Installation

In this example, we configure a Cisco 1242 AP (IP address 192.168.0.4). Configuration of other vendors' APs is similar. First, define the normal, isolation, registration and visitor VLANs on the AP, together with the appropriate wired and wireless interfaces as shown for the isolation VLAN:

dot11 vlan-name isolation vlan 2

interface FastEthernet0.2
 encapsulation dot1Q 2
 no ip route-cache
 bridge-group 253
 no bridge-group 253 source-learning
 bridge-group 253 spanning-disabled

interface Dot11Radio0.2
 encapsulation dot1Q 2
 no ip route-cache
 bridge-group 253
 bridge-group 253 subscriber-loop-control
 bridge-group 253 block-unknown-source
 no bridge-group 253 source-learning
 no bridge-group 253 unicast-flooding
 bridge-group 253 spanning-disabled

Then, create the two SSIDs:

dot11 ssid WPA2
   vlan 2 backup normal
   authentication open eap eap_methods
   authentication key-management wpa
   accounting acct-methods
   mbssid guest-mode

dot11 ssid MACauth
   vlan 3 backup visitor
   authentication open mac-address mac_methods
   accounting acct_methods
   mbssid guest-mode

Configure the RADIUS server (we assume here that the FreeRADIUS server and the PacketFence server are located on the same box):

radius-server host 192.168.0.10 auth-port 1812 
 ↪acct-port 1813 key secretKey

aaa group server radius rad_eap
 server 192.168.0.10 auth-port 1812 acct-port 1813
aaa authentication login eap_methods group rad_eap

aaa group server radius rad_mac
 server 192.168.0.10 auth-port 1812 acct-port 1813
aaa authentication login mac_methods group rad_mac

Enable the SNMP deauthentication traps:

snmp-server enable traps deauthenticate
snmp-server host 192.168.0.10 public deauthenticate

Finally, activate the SSIDs on the radio:

interface Dot11Radio0
 encryption vlan 1 mode ciphers aes-ccm
 encryption vlan 2 mode ciphers aes-ccm
 ssid WPA2
 ssid MACauth

Now, check with a Wi-Fi card that you actually can see the two new SSIDs. You can't connect to them yet because the RADIUS server is not up and running.

Start configuring the FreeRADIUS server by adding the following lines at the end of /etc/raddb/clients.conf:

client 192.168.0.3 {
  secret = secretKey
  shortname = AP1242
}

In /etc/raddb/eap.conf, set the default eap type to peap at the beginning of the eap {} section:

default_eap_type = peap

And, set up your cryptographic keys in the tls {} section.

Then, update /etc/raddb/radiusd.conf, first by adding the following lines to the modules {} section:

perl {
    module = ${confdir}/rlm_perl_packetfence.pl
}

Then, add “perl” at the end of the authorize {} section. The script /etc/raddb/rlm_perl_packetfence.pl uses the Calling-Station-Id RADIUS request attribute, containing the MAC of the wireless station to determine its registration and violation status. Based on this information, it sets the Tunnel-Medium-Type, Tunnel-Type and Tunnel-Private-Group-ID RADIUS reply attributes. The AP, upon reception of these three attributes, then confines the wireless station into the specified VLAN.

The last file to edit is /etc/raddb/users to define that non-EAP messages should, by default, lead to an authentication acceptance:

DEFAULT EAP-Message !* "", Auth-Type := Accept

Then, add a local test user with:

testUser User-Password == "testPwd"

Now, start FreeRADIUS in debug mode:

radiusd -x

Try to connect to one of the two new SSIDs with your Wi-Fi card, and you'll see the packets received by FreeRADIUS with the generated responses.

It also is noteworthy that the concepts you've learned here on using PacketFence with wireless networks are identical to using 802.1x on a wired network, which of course, is supported by PacketFence.

Extending to New Switches and APs

We designed the VLAN isolation feature from the beginning with extensibility in mind. All supported switches are represented through Perl objects, and we make extensive use of inheritance. For example:

  • At the highest level, you have the pf::SNMP object that defines general functions, such as SNMP session creation and deletion, database connections and some standardized SNMP queries.

  • At the next level are the vendor-specific objects, such as pf::SNMP::Cisco and pf::SNMP::Nortel. They include the necessary functions to parse SNMP traps and, most of the time, to read and write a port's VLAN assignment.

  • Finally, at the lowest level, are the model-specific objects, containing only the model-specific code.

This architecture simplifies adding the support for a new product from an already-supported vendor; it comes down to redefining only a very limited number of methods and can be done in a matter of hours.

Conclusion

As you've seen in this article, PacketFence secures both wired and wireless networks in an efficient way. Offering the same level of security and using the same NAC solution on both networks make PacketFence one of the most essential security tools to have.

Resources

“PacketFence” by Ludovic Marcotte and Dominik Gehl, LJ, April 2007: www.linuxjournal.com/article/9551

PacketFence: www.packetfence.org

Inverse—PacketFence VLAN-Based Isolation Mode: www.inverse.ca/contributions/packetfence.html

Net-SNMP—snmptrapd Dæmon: www.net-snmp.org

The FreeRADIUS Project: www.freeradius.org

Regis Balzard (rbalzard@inverse.ca) holds a Computer Engineering degree from the Ecole Superieure d'Ingenieurs en Genie Electrique (ESIGELEC) in Rouen, France. He is currently a systems architect for Inverse, Inc., an IT consulting company located in downtown Montréal that specializes in the deployment of infrastructures based on free and open-source components like PacketFence and SOGo.

Dominik Gehl (dgehl@inverse.ca) holds a Master's degree in Computer Science from the University of Montréal. He is currently a systems architect for Inverse, Inc., an IT consulting company located in downtown Montréal that specializes in the deployment of infrastructures based on free and open-source components like PacketFence and SOGo.

Load Disqus comments