Quarantine Web Frontend

It's all well and good having a full 802.1X deployment and policies and everything, but if you have no way of having the users being tended to by the system to interact with it then you are going to have a lot of work on your hands. The quarantine system is multi-purpose in that it handles fresh registrations, 802.1X supplicant spin-boarding and actual disabled/quarantined users alike. The system also needs to support bare bone box provisioning prior to registration otherwise your helldesk team is going to crucify you if they have to have an OS on the box to register it but cannot image it (using software such as FreeGhost) until its registered, a nasty catch-22.

We shall assume your quarantine box has two uplinks that you can bond together for better throughput/failover and also tag frames using 802.1Q to get from the native 'Intranet' network and the quarantined/unauthorised VLAN from the same link.

Right these destructions are for a Debian box, the one true distro; the idea is to leave room for failover to come into play so if IP addresses and ranges look 'one off' that is quite possibly deliberate...then agains it could be a typo :) The quarantine VLAN ID is 127 ('unauthorised'), the network range for that is 10.0.0.0/24 whilst the 'uplink' subnet for the quarantine1 (IP is 4.3.2.1) box is 4.3.2.0/29.

The Network Configuration

/etc/network/interfaces

# The primary network interface
auto bond0
iface bond0 inet static
        slaves eth0 eth1
        address 4.3.2.2
        netmask 255.255.255.248
        gateway 4.3.2.1

auto vlan0127
iface vlan0127 inet static
        vlan-raw-device bond0
        address 10.0.0.253
        netmask 255.255.255.0

        up modprobe ip_nat_tftp 
        up modprobe ip_conntrack_tftp
        up iptables-restore < /etc/network/iptables.active
        up ip6tables-restore < /etc/network/ip6tables.active
        up ip addr add 10.0.0.1/24 dev vlan0127
        up sysctl -q -w net.ipv4.ip_forward=1
        up sysctl -q -w net.ipv4.conf.bond0.proxy_arp=1
        post-up /etc/init.d/maradns start
        post-up /etc/init.d/dhcp3-relay start
        post-up /etc/init.d/pimd start

        down /etc/init.d/pimd stop
        down /etc/init.d/dhcp3-relay stop
        down /etc/init.d/maradns stop
        down sysctl -q -w net.ipv4.conf.bond0.proxy_arp=0
        down sysctl -q -w net.ipv4.ip_forward=0
        down ip addr del 10.0.0.1/24 dev vlan0127
        down ip6tables-restore < /etc/network/ip6tables.inactive
        down iptables-restore < /etc/network/iptables.inactive

To get the bonding kicking in your need to pass some module parameters to the 'bonding' module:

quarantine1:/home/user# cat /etc/modprobe.d/local 
alias bond0 bonding  
options bond0 mode=802.3ad miimon=100 xmit_hash_policy=layer3+4

/etc/network/ip(6)tables.(in)active

Here is a typical IPv4 'active' ruleset:

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

-A POSTROUTING -o bond0 -s 10.0.0.0/24 -j SNAT --to-source 4.3.2.2
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:filter-unauth-input - [0:0]
:multicast - [0:0]

-A INPUT -i vlan0127 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i vlan0127 -m state --state NEW -j filter-unauth-input
## optional multicast related lines
# outgoing PIM packets appear on the INPUT chain for some reason :-/
-A INPUT -i vlan0127 -p pim -d 224.0.0.13 -j ACCEPT
-A INPUT -i vlan0127 -m state --state NEW -j multicast
# optional logging line
#-A INPUT -i vlan0127 -m limit --limit 3/minute --limit-burst 2 -j LOG
-A INPUT -i vlan0127 -j REJECT --reject-with icmp-admin-prohibited

-A OUTPUT -o vlan0127 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -o vlan0127 -m state --state NEW -j multicast
#-A OUTPUT -o vlan0127 -m limit --limit 3/minute --limit-burst 2 -j LOG
-A OUTPUT -o vlan0127 -j REJECT --reject-with icmp-admin-prohibited

## so what are we going to permit on this VLAN?
# ping
-A filter-unauth-input -p icmp -m icmp --icmp-type echo-request -j ACCEPT
# web
-A filter-unauth-input -p tcp -m multiport --dports 80,443 -j ACCEPT
# dhcp
-A filter-unauth-input -p udp -m udp --dport 67 -j ACCEPT
# dns
-A filter-unauth-input -p udp -m udp --dport 53 -j ACCEPT

-A filter-unauth-input -j RETURN

## multicast related
-A multicast -p igmp -d 224.0.0.0/23 -j ACCEPT
-A multicast -p udp -d 239.232.0.0/16 -j DROP
-A multicast -p udp -d 239.0.0.0/8 -j ACCEPT
-A multicast -j RETURN

####### FORWARD ########
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

# tftp (pxe booting) - imaging-boxen.it.example.com
-A FORWARD -i vlan0127 -o bond0 -s 10.0.0.0/24 -d 1.2.3.4 -p udp -m udp --dport 69 -m state --state NEW -j ACCEPT

-A FORWARD -j REJECT --reject-with icmp-admin-prohibited

COMMIT

No support on our network for IPv6 (yet) so watch this space, the following is for the 'active' case

*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

-A INPUT -s ::/0 -d ::/0 -j REJECT --reject-with icmp6-adm-prohibited 
-A FORWARD -s ::/0 -d ::/0 -j REJECT --reject-with icmp6-adm-prohibited 
-A OUTPUT -s ::/0 -d ::/0 -j REJECT --reject-with icmp6-adm-prohibited 

COMMIT

From the 'inactive' cases in box examples all the rules themselves have just been trimmed, although the policy's for the core chains remain (ie. DROP on FORWARD).

Switch Configuration

The following is the relevant port snippets on the switch (a Cisco 3750 in this case):

343-1#show run int Gi1/0/15
Building configuration...

Current configuration : 243 bytes
!
interface GigabitEthernet1/0/15
 description quarantine1
 switchport trunk encapsulation dot1q
 switchport trunk native vlan <vlan-for-4.3.2.0/29>
 switchport trunk allowed vlan 127,<vlan-for-4.3.2.0/29>
 switchport mode trunk
 no cdp enable
 channel-group 14 mode active
end

343-1#show run int Gi2/0/15
Building configuration...

Current configuration : 243 bytes
!
interface GigabitEthernet2/0/15
 description quarantine1
 switchport trunk encapsulation dot1q
 switchport trunk native vlan <vlan-for-4.3.2.0/29>
 switchport trunk allowed vlan 127,<vlan-for-4.3.2.0/29>
 switchport mode trunk
 no cdp enable
 channel-group 14 mode active
end

343-1#show run int po14    
Building configuration...

Current configuration : 191 bytes
!
interface Port-channel14
 description quarantine1
 switchport trunk encapsulation dot1q
 switchport trunk native vlan <vlan-for-4.3.2.0/29>
 switchport trunk allowed vlan 127,<vlan-for-4.3.2.0/29>
 switchport mode trunk
end

DHCP Relay

The /etc/default/dhcp3-relay (provided by the package 'dhcp3-relay') file contains:

# What servers should the DHCP relay forward requests to?
SERVERS="12.13.14.15"

# On what interfaces should the DHCP relay (dhrelay) serve DHCP requests?
INTERFACES="bond0 vlan0127"

# Additional options that are passed to the DHCP relay daemon?
OPTIONS="-m discard -D -A 1400"

You should stop it from automatically loading at start by rm'ing /etc/rc2.d/S20dhcp3-relay. Annoyingly for the DHCP responses to get back to 10.0.0.0/24 the network must know how to route to the address otherwise the DHCP offers get dropped at the first hop from the DHCP server(s). You should put something like the following into your routing table (if you are using Cisco IOS in the core):

ip route 10.0.0.0 255.255.255.0 Vlan<vlan-for-4.3.2.0/29>

DNS Server

We use 'maradns' as it is far more lightweight than ISC's BIND9. You might be pondering why you would not simply forward requests to your DNS server and have them recursively handled there? The reason is that it is rather trivial for the user to create a DNS tunnel to escape such awkward situations, this type of tunnelling is very difficult to detect and deal with other than simply running an DNS server in an authoritive state that pretends to be the authority for the whole of DNS space.

Edit the configuration file /etc/maradns/mararc as shown:

csv2 = {}
csv2_default_zonefile = "db.unauthorised"

bind_address = "10.0.0.1"

Your 'db.unauthorised' file should look like:

*                     SOA     example.com. email@example.com. 1 7200 3600 604800 1800
*                     NS      ns.example.com.

ns.example.com.       A       10.0.0.1

*                     A       10.0.0.1

You should rm /etc/rc2.d/S19maradns as maradns will be started by the ifup/down scripts.