SMUS Wireless Configuration: Difference between revisions
Line 330: | Line 330: | ||
sudo vi /etc/freeradius/sites-enabled/staff | sudo vi /etc/freeradius/sites-enabled/staff | ||
* Wrap the entire config file into a block. At the top of the file, add "server staff {" and at the bottom, add "}" | * Wrap the entire config file into a block. At the top of the file, add "server staff {" and at the bottom, add "}". For ease of readability, you can indent the contents of the block one tab so that you can tell it's part of the "server staff {" block. | ||
* Add a listen block immediately under "server staff {" | * Add a listen block immediately under "server staff {" | ||
** The port is set to 0 as that makes it the default (1812 for radius and 1813 for accounting) | ** The port is set to 0 as that makes it the default (1812 for radius and 1813 for accounting) |
Revision as of 12:21, 30 December 2011
Introduction
This page will discuss the backend for the SMUS wireless configuration.
This document is made available under the Creative Commons Attribution ShareAlike 2.5 Canada license.
Prerequisites
Our requirements for wireless on campus are fairly complex. We decided on several prerequisites, for a variety of reasons.
802.1x
We wanted staff and students to be able to sign into the wireless system themselves without any help from the MIS department. Several implementations use a captive portal mechanism to do this, but that results in an SSID with no encryption. By using 802.1x, we can use WPA2-Enterprise encryption on the SSIDs, and staff and students can still configure the connection themselves.
Active Directory Integration
Wherever possible, we have staff and students use their active directory credentials to log into whatever they're trying to access. We wanted this system to also use the active directory credentials. The AD server had preexisting groups we wanted to take advantage of as well, and we added more groups later to further separate out our users.
Different Student and Staff IP addresses
Students on our campus are subject to bandwidth limitations and packet shaping. We do not want to apply these restrictions to staff members. Our packet shaper uses a simple IP range to track which machines to apply restrictions to, so we needed our students to be assigned a different set of IP addresses than our staff.
VLANs for mobile labs
Our mobile laptop labs also need different IP ranges. As we have a senior and middle school, we apply different web filtering to each set of computers. We achieved this using VLAN assignments in freeradius after the machines logged in, based on a regular expression check on the computer name.
Single simultaneous login for students
Our students are limited to one simultaneous wireless connection. This is to discourage password sharing (one student using another student's account will then stop the original student from being able to log in). As different grades have different access times, we didn't want grade 12 students sharing their credentials to students in lower grades. This is also potentially a bandwidth saving measure, as a single student can't have their iPod, iPhone, computer, etc. clogging up the same access point simultaneously. Again, these restrictions do not apply to staff.
Login times by grade
We apply different login hours by grade. Grade 12s can use the wireless longer into the evening than grade 11s, which can use it longer than grade 10s, etc.
Guest logins
As there are frequently parents and other guests on campus, we wanted it to be fairly simple for them to get their wireless device onto our network. These devices are sometimes not as secure as other devices, so they are separated out onto their own network, and we check their computers for up-to-date antivirus protection through a captive portal before allowing them to login. Antivirus protection is not checked on smartphones and similar devices, only full computers.
Software Used
We use a combination of Freeradius (to do radius authentication and accounting), and Samba (for active directory integration) on the backend. The wireless access points are configured using the Meraki cloud controller, although other wifi systems can also tap into the same radius configuration (we tested with Dlink access points as well). Whatever wifi system is selected must support 802.1x authentication through WPA2-Enterprise encryption, as well as radius accounting packets (to track simultaneous logins).
Simultaneous logins are tracked using a MySQL database, although it should also be possible to use Postgres as Freeradius supports it. The automated scripts we run would need to be modified slightly to support Postgres.
Bug-free support for the functions we're using arrived recently to Samba and Freeradius, and older versions definitely don't work properly. We are running Debian 6 with the stock versions of all packages. We were previously running Ubuntu 10.04 and the versions included there did not work. Freeradius 2.1.10 and Samba 3.5.6 are included with Debian 6, so those are the recommended versions.
Our VLANs are routed through a PFSense 2.0.0 virtual machine. This VM can apply firewalls to any combination of subnet connections, and has good performance for the throughput we need. Routing and firewalling can also be done through a dedicated router.
Hardware Used
Our radius server runs as a VMWare ESXi 5.0 virtual machine. It has a single virtual processor (2.53 GHz) with 256 MB of ram. This is more than sufficient to handle our incoming connections. Our MySQL database server, which handles many other databases as well, has 4 virtual processors and 3 GB of ram.
We use Meraki MR16 access points.
Clients we have successfully authenticated on this network include Windows XP, Vista, and 7; Mac OS X; Android, Blackberry, and iOS smartphones; etc. Through MAC address whitelisting, we have also put other devices onto the guest network.
Samba Configuration
Samba must be installed and the Linux machine must be joined to the active directory domain before radius can do NTLM authentication.
sudo apt-get install samba winbind smbclient krb5-user sudo vi /etc/krb5.conf
- Ensure default realm is set to your active directory DNS name (ours is SMUS.LOCAL)
- Under realms, add a section:
SMUS.LOCAL = { kdc = <domain controller DNS name> kdc = <backup domain controller DNS name> admin_server = <domain controller DNS name> }
- Now test that your Kerberos settings are correct
sudo kinit Administrator
- Enter your domain administrator password, and if it comes back without any errors you've set up Kerberos correctly
- Now configure Samba
sudo vi /etc/samba/smb.conf
- Change workgroup to your active directory short name (Ours is "SMUSLOCAL")
- Add a new line underneath with your Kerberos realm/Active Directory DNS name:
realm = <AD DNS name>
- Uncomment "security = user" and change to "security = ads"
- Immediately underneath, add the following lines:
password server = <domain controller DNS name>
Now join the Active Directory domain:
sudo net ads join -U Administrator
Then restart Samba and Winbind so that you can authenticate against the AD domain:
sudo /etc/init.d/samba stop; sudo /etc/init.d/winbind stop sudo /etc/init.d/samba start; sudo /etc/init.d/winbind start
Freeradius Configuration
Installation
sudo apt-get install freeradius freeradius-ldap freeradius-mysql
- Allow the freerad user access to query winbind
sudo adduser freerad winbindd_priv
Clients
We must set up clients that are allowed to authenticate via radius. We have set up one client definition for senior/middle school Meraki access points, another definition for junior school Meraki access points, and a several definitions for the Meraki cloud controller, which does the guest authentication.
client <ip range>/24 { secret = <radius secret> shortname = meraki_ap nastype = other } client <ip range>/24 { secret = <radius secret> shortname = meraki_jr_ap nastype = other } client 64.156.192.220/32 { secret = <radius secret> shortname = meraki_cloud1 nastype = other } client 64.156.192.245/32 { secret = <radius secret> shortname = meraki_cloud2 nastype = other } client 74.50.51.16/32 { secret = <radius secret> shortname = meraki_cloud3 nastype = other } client 74.50.53.101/32 { secret = <radius secret> shortname = meraki_cloud4 nastype = other }
Policies
Add each of these policies under /etc/freeradius/policy.conf
Require_staff Policy
This ensures that the Huntgroup-Name variable is set when we actually authenticate the user later.
require_staff { update request { Huntgroup-Name := "<staff group name>" } }
Require_student Policy
This ensures that the Huntgroup-Name variable is set when we actually authenticate the user later. We also update any replies to indicate that the student's session timeout is 5 minutes to force them to reauthenticate every 5 minutes.
require_student { update request { Huntgroup-Name := "<student group name>" } update reply { Session-Timeout = 300 } }
Require_guest Policy
Guests are authenticated differently because they are not doing 802.1x EAP/MSCHAP authentication. Instead, they use NTLM authentication (a username and cleartext password). As these passwords are transmitted cleartext over the Internet, it is wise to rotate the passwords often, and also to not use privileged accounts. The accounts we set up for guest wireless access are not allowed to log into school computers, or access any resources other than wireless.
We will set up the actual auth module later.
require_guest { update request { Huntgroup-Name := "<guest group name>" } update control { Auth-Type := "ntlm_auth_guest" } }
Single_login Policy
This just adds a check to ensure that the user only has one device on at a time. We haven't configured how to check that yet, but we must have a policy in place before the next steps.
single_login { update control { Simultaneous-Use := 1 } }
Logintime Policy
In the require_student policy, we also place an LDAP group check to see what times the user should be allowed to log in. Here is the full require_student policy after adding the LDAP group checks. Note that the Huntgroup-Name group check is done through the active directory login, and so supports recursive group checking, but the LDAP group checks do not support recursive group checking.
require_student { update request { Huntgroup-Name := "<student group name>" } if (Ldap-Group == "Grade 12 Board") { # special group, 6 AM - 12 AM Su - Th, 6 AM - 1 AM (next day) Fr - Sa update control { Login-Time := "Su0600-0100,Mo0600-0000,Tu0600-0000,We0600-0000,Th0600-0000,Fr0600-0000,Sa0600-0100" } } elsif (Ldap-Group == "Grade 11 Board") { # special group, 6 AM - 11 PM Su - Th, 6 AM - 12 AM Fr - Sa update control { Login-Time := "Su0600-2300,Mo0600-2300,Tu0600-2300,We0600-2300,Th0600-2300,Fr0600-0000,Sa0600-0000" } } elsif (Ldap-Group == "Grade 10 Board") { # special group, 6 AM - 10:30 PM Su - Th, 6 AM - 11:30 PM Fr - Sa update control { Login-Time := "Su0600-2230,Mo0600-2230,Tu0600-2230,We0600-2230,Th0600-2230,Fr0600-2330,Sa0600-2330" } } else { # default group, 6 AM - 10 PM daily update control { Login-Time := "All0600-2200" } } update reply { Session-Timeout = 300 } }
Special_vlan Policy
When we authenticate computers, we also check to see if the machine should go onto a special VLAN. We check computer names for the computer lab VLANs, and we also check which access point they're binding to to check for Junior School machines, which are assigned different VLANs as they are a separate campus.
check_special_vlan { if ("%{User-Name}" =~ /N7-MIDD-205-/i) { update reply { Tunnel-Private-Group-ID = 50 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } if ("%{User-Name}" =~ /N7-MIDD-CAR-/i) { update reply { Tunnel-Private-Group-ID = 50 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } if ("%{User-Name}" =~ /N7-SCHO-CAR-/i) { update reply { Tunnel-Private-Group-ID = 51 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } if ("%{User-Name}" =~ /N7-SCHO-LIB-/i) { update reply { Tunnel-Private-Group-ID = 51 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } if ("%{Client-Shortname}" == "meraki_jr_ap") { # authenticating from JR school, change up the VLAN numbers if ("%{Huntgroup-Name}" == "<student group name>") { # was going to be on student VLAN, put on JR student VLAN update reply { Tunnel-Private-Group-ID = 204 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } else { # otherwise put on JR staff VLAN update reply { Tunnel-Private-Group-ID = 200 Tunnel-Type = "VLAN" Tunnel-Medium-Type = "IEEE-802" } } } }
Virtual Hosts
We use virtual hosts so that there are different radius servers available to authenticate staff, students, and guests.
sudo vi /etc/freeradius/radiusd.conf
- Comment out all of the listen blocks, as we will be setting these up for each virtualhost
- Now set up your virtualhosts
cd /etc/freeradius/sites-available cp default staff cp default student cp default guest cd /etc/freeradius/sites-enabled rm default ln -s ../sites-available/staff . ln -s ../sites-available/student . ln -s ../sites-available/guest .
Staff Virtual Host
sudo vi /etc/freeradius/sites-enabled/staff
- Wrap the entire config file into a block. At the top of the file, add "server staff {" and at the bottom, add "}". For ease of readability, you can indent the contents of the block one tab so that you can tell it's part of the "server staff {" block.
- Add a listen block immediately under "server staff {"
- The port is set to 0 as that makes it the default (1812 for radius and 1813 for accounting)
- Note that the staff server handles the radius accounting for all IP addresses, but you can configure them separately if desired
listen { port = 0 type = auth ipaddr = <ip address> } listen { port = 0 type = acct ipaddr = * }
- Update the authorize block so that it has the following items:
preprocess require_staff suffix eap { ok = return } files
- Update the authentication block so that it has the following items:
eap
- Update the preacct block so that it has the following items:
preprocess acct_unique suffix
- Update the accounting block so that it has the following items:
sql attr_filter.accounting_response
- Update the session block so that it has the following items:
sql
- Update the post-auth block so that it has the following items:
check_special_vlan exec Post-Auth-Type REJECT { attr_filter.access_reject }
- Update the post-proxy block so that it has the following items:
eap
Student Virtual Host
sudo vi /etc/freeradius/sites-enabled/student
- Set the server alias to "server student" rather than "server default"
- Add a listen block immediately under "server student {"
- The port is set to 0 as that makes it the default (1812 for radius and 1813 for accounting)
listen { port = 0 type = auth ipaddr = <ip address> }
- Update the authorize block so that it has the following items:
preprocess ldap require_student single_login suffix eap { ok = return } files expiration logintime
- Update the authentication block so that it has the following items:
eap
- Comment out the preacct and accounting blocks, as they are not used
- Update the session block so that it has the following items:
sql
- Update the post-auth block so that it has the following items:
check_special_vlan exec Post-Auth-Type REJECT { attr_filter.access_reject }
- Update the post-proxy block so that it has the following items:
eap
Guest Virtual Host
sudo vi /etc/freeradius/sites-enabled/guest
- Set the server alias to "server guest" rather than "server default"
- Add a listen block immediately under "server guest {"
- The port is set to 0 as that makes it the default (1812 for radius and 1813 for accounting)
listen { port = 0 type = auth ipaddr = <ip address> }
- Update the authorize block so that it has the following items:
preprocess require_guest suffix eap { ok = return } files
- Update the authentication block so that it has the following items:
ntlm_auth_guest
- Comment out the preacct and accounting blocks as they are not used
- Update the session block so that it has the following items:
sql
- Update the post-auth block so that it has the following items:
check_special_vlan exec Post-Auth-Type REJECT { attr_filter.access_reject }
- Update the post-proxy block so that it has the following items:
eap
Inner-Tunnel Virtual Host
The inner-tunnel vhost should already be mostly set up, as it's generally included with Freeradius' default configuration. If it's not, symlink it from the sites-available:
sudo ln -s /etc/freeradius/sites-available/inner-tunnel /etc/freeradius/sites-enabled
Now start editing:
sudo vi /etc/freeradius/sites-enabled/inner-tunnel
- Update the authorize block so that it has the following items:
chap mschap suffix update control { Proxy-To-Realm := LOCAL } eap { ok = return } files expiration logintime pap
- Update the authentication block so that it has the following items. Note that if mschap authentication fails (this means that the user isn't a member of the huntgroup we set earlier), we also check whether mschap_computers authenticates the user correctly.
Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap { reject = 2 } if (reject) { mschap_computers } } unix eap
- Comment out the accounting, preacct, and session blocks, as they are not used
- Update the post-auth block so that it has the following items:
Post-Auth-Type REJECT { attr_filter.access_reject }
- Update the post-proxy block so that it has the following items:
eap
Certificates
We need to generate a CSR and get a real certificate for this server. Here are the steps from memory, so they may not be 100% correct.
cd /etc/freeradius/certs openssl req -out <server_name>.csr -new -newkey rsa:2048 -nodes -keyout <server_name>.key
Now send the CSR to a certificate authority and get it signed. If the CA uses a certificate chain, you need to put all of the certificates into one file, with the server's certificate at the top, then the CA that signed that cert, then the next CA up the chain, etc. Upload the resulting certificate file as <server_name>.crt .
EAP
Now configure EAP to use the certificate along with other parameters.
sudo vi /etc/freeradius/eap.conf
Inside the eap block, set the following:
default_eap_type = peap
Inside the eap/tls block, set the following:
private_key_password = private_key_file = ${certdir}/<server_name>.key certificate_file = ${certdir}/<server_name>.crt
Inside the eap/tls/cache block, set the following:
enable = yes lifetime = 4 # hours max_entries = 1000
Radius accounting/SQL Connection
cp /etc/freeradius/sql.conf /etc/freeradius/sql sudo vi /etc/freeradius/modules/sql
- Set the following values under the SQL block
server = "<database ip address>" login = "<db user>" password = "<db password>"
- If you have a lot of radius clients, you may also need to boost the num_sql_socks to 10 or higher
- Now edit the simultaneous count query
sudo vi /etc/freeradius/sql/mysql/dialup.conf
- Uncomment the simul_count_query SQL statement
- Change the statement to:
SELECT COUNT(*) \ FROM ${acct_table1} \ WHERE username LIKE '%{SQL-User-Name}' \ AND callingstationid NOT LIKE '%{Calling-Station-Id}' \ AND acctstoptime IS NULL
This ensures that users are allowed to reauthenticate if their MAC address hasn't changed. This allows roaming between access points without triggering the simultaneous use restriction.
LDAP Connection
sudo vi /etc/freeradius/modules/ldap
- Configure TLS if desired under the ldap/tls block
- Set the following values in the ldap block:
server = "<domain controller>:3268" identity = "<domain query user, for example cn=ldap_user,cn=users,dc=...>" password = "<domain query user AD password>" basedn = "<AD base DN>" filter = "(samAccountName=%{%{mschap:User-Name}:-%{User-Name}})" groupname_attribute = cn groupmembership_filter = "(&(objectClass=group)(member=%{control:Ldap-UserDn}))" groupmembership_attribute = memberOf chase_referrals = yes rebind = yes
MSCHAP module
sudo vi /etc/freeradius/modules/mschap
- Set the following values under the mschap block:
with_ntdomain_hack = yes ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00} --domain=<Domain short name> --username=%{Stripped-User-Name:-%{mschap:User-Name}} --require-membership-of=<Domain short name>\\\\%{outer.request:Huntgroup-Name}"
MSCHAP_Computers module
sudo cp /etc/freeradius/modules/mschap /etc/freeradius/modules/mschap_computers
- Change the block from "mschap {" to "mschap mschap_computers {"
- Change the following values under the mschap mschap_computers block:
ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00} --domain=<Domain short name> --username=%{Stripped-User-Name:-%{mschap:User-Name}} --require-membership-of=<Domain short name>\\\\Domain\\ Computers"
NTLM_Auth_Guest module
sudo cp /etc/freeradius/modules/ntlm_auth /etc/freeradius/modules/ntlm_auth_guest
- Change the block from "exec ntlm_auth {" to "exec ntlm_auth_guest {"
- Change the following values under the exec ntlm_auth_guest block:
program = "/usr/bin/ntlm_auth --request-nt-key --domain=<AD domain> --username=%{mschap:User-Name} --password=%{User-Password} --require-membership-of=<AD domain>\\\\%{request:Huntgroup-Name}"
Set up MySQL database
- Download the freeradius distribution on your database server:
wget ftp://ftp.freeradius.org/pub/freeradius/freeradius-server-2.1.10.tar.bz2 tar -jxvf freeradius-server-2.1.10.tar.bz2
- Set up a database for freeradius
mysql -u root -p CREATE DATABASE radius; GRANT ALL PRIVILEGES ON radius.* to '<radius_user>'@'<radius_ip>'; exit; cd freeradius-server-2.1.10 mysql -u root -p radius < raddb/sql/mysql/schema.sql
Restart freeradius and pray
This starts Freeradius in debug mode. You should watch this fly by and verify that all of the configuration you have done above worked properly. If it didn't, Freeradius will complain and then exit. Then, try to get something to actually authenticate (follow the Meraki configuration in the next step to get it using your radius server).
sudo /etc/init.d/freeradius stop sudo freeradius -X
To start radius for real, CTRL+C your debug session, then run:
sudo /etc/init.d/freeradius start
Accounting Expiration Script
We noticed that our Meraki APs were very good at sending radius authentication packets, but not so good at sending radius unauthentication packets when the clients left. So, we wrote a script that expires accounting records automatically if they have been active for > 7 minutes, and run the script every 2 minutes. This effectively means that if the Meraki AP doesn't send a logout accounting message, the student can still switch to a different device within 10 minutes.
This script also deletes all radius accounting information older than 14 days. Even still we have 430,000 records in our table at the moment.
vi /root/cleanup_radius.sh
#!/bin/bash # trash auth records from > 14 days ago mysql -u <radius_db_user> -p<radius_password> -h <db_ip> radius -e "DELETE FROM radacct WHERE acctstarttime < DATE_SUB(NOW(), INTERVAL 14 DAY)" # expire student auth records from > 7 minutes ago (script is run every 2 minutes so it takes less than 10 minutes to expire old records) mysql -u <radius_db_user> -p<radius_password> -h <db_ip> radius -e "UPDATE radacct SET acctstoptime = NOW() WHERE acctstarttime < DATE_SUB(NOW(), INTERVAL 7 MINUTE) AND acctstoptime IS NULL AND calledstationid LIKE '%AirSMUS-student'"
Now add this to the crontab:
chmod +x /root/cleanup_radius.sh crontab -e
*/2 * * * * /root/cleanup_radius.sh
Meraki configuration to use radius server
Note that while this configuration is specific to the Meraki cloud controller, it is also possible to set up 802.1x authentication through radius with other wireless systems.
Staff SSID
- Go to Configure -> Overview and enable a new SSID. We named ours AirSMUS-staff.
- Go to Configure -> Access control, and set up the following details:
Network Access, Association Requirements -> WPA2-Enterprise with 802.1x authentication Network Access, Network sign-on method -> Direct access Network Access, Authentication server -> Use my radius server, host <ip>, port 1812, secret <radius_secret>, radius accounting: enabled, server: same as radius server Addressing and traffic, Client IP assignment -> Bridge mode VLAN setup, VLAN tagging: Use VLAN Tagging VLAN setup, VLAN ID: JR tag -> 200, all other APs -> 112 VLAN setup, Radius override -> radius response can override VLAN tag Wireless options, Band selection -> dual band operation (2.4 GHz and 5 GHz) Wireless options, Legacy 11b operation -> Disable legacy 11b bitrates (1, 2, & 5.5 Mbps)
We noticed on our network that if "Dual band operation with Band Steering" was selected, some older wireless cards did not see the SSID at all. We resolved the issue by just using Dual Band with no Band Steering.
Student SSID
- Go to Configure -> Overview and enable a new SSID. We named ours AirSMUS-student.
- Go to Configure -> Access control, and set up the following details:
Network Access, Association Requirements -> WPA2-Enterprise with 802.1x authentication Network Access, Network sign-on method -> Direct access Network Access, Authentication server -> Use my radius server, host <ip2>, port 1812, secret <radius_secret>, radius accounting: enabled, server: same as radius server Addressing and traffic, Client IP assignment -> Bridge mode VLAN setup, VLAN tagging: Use VLAN Tagging VLAN setup, VLAN ID: JR tag -> 204, all other APs -> 104 VLAN setup, Radius override -> radius response can override VLAN tag Wireless options, Band selection -> dual band operation (2.4 GHz and 5 GHz) Wireless options, Legacy 11b operation -> Disable legacy 11b bitrates (1, 2, & 5.5 Mbps)
Guest SSID
- Go to Configure -> Overview and enable a new SSID. We named ours AirSMUS-guest.
- Go to Configure -> Access control, and set up the following details:
Network Access, Association Requirements -> Open (no encryption) Network Access, Network sign-on method -> Sign-on splash page Network access, Network access control -> Enabled: check clients for antivirus software Network access, Remediation -> Send users to the standard remediation site Network Access, Captive portal strength -> Block all access until sign-on is complete Network Access, Walled garden -> Walled garden is disabled Network Access, Authentication server -> Use my radius server, host <external_ip_address>, port 1812, secret <radius_secret> Network Access, Failover policy -> Deny access Network Access, Simultaneous logins -> Allow simultaneous devices per user Addressing and traffic, Client IP assignment -> Bridge mode VLAN setup, VLAN tagging: Use VLAN Tagging VLAN setup, VLAN ID: JR tag -> 200, all other APs -> 100 Wireless options, Band selection -> dual band operation (2.4 GHz and 5 GHz) Wireless options, Legacy 11b operation -> Disable legacy 11b bitrates (1, 2, & 5.5 Mbps)
Note: make sure you have set up firewall exceptions and IP forwarding through to the external IP address you have configured here.
Additional Information
P2P blocking through Meraki
On our guest wifi network, we block P2P traffic.
Under Configure -> Firewall & Traffic Shaping, we added a Layer 7 firewall rule denying P2P traffic.
Packetshaper Integration
We use an application called Penaltybox: http://sourceforge.net/projects/penaltybox/ in combination with our packet shaper in order to restrict students to 7 GB of traffic per week. After this amount of traffic, the student is restricted to 32 Kbit/sec down and 32 Kbit/sec up for 7 days.
In order to get this to work, you must set up port mirroring to a physical server that listens to the traffic in promiscuous mode. It then records how much bandwidth is used by each IP address in the eligible range and applies restrictions when thresholds are met.
In order to compile the penaltybox application on our Debian 6 server and have it support our (newer) packetshaper, we had to apply the following patch:
diff -ur penaltybox/src/benconfig/configexception.h penaltybox.new/src/benconfig/configexception.h --- penaltybox/src/benconfig/configexception.h 2006-08-23 10:29:54.000000000 -0700 +++ penaltybox.new/src/benconfig/configexception.h 2010-12-23 11:09:18.000000000 -0800 @@ -10,6 +10,7 @@ #ifndef __CONFIGEXCEPTION_H #define __CONFIGEXCEPTION_H #include <string> +#include <cstdio> #include "configtypes.h" using namespace std; diff -ur penaltybox/src/benconfig/configloader.cpp penaltybox.new/src/benconfig/configloader.cpp --- penaltybox/src/benconfig/configloader.cpp 2007-01-17 12:07:13.000000000 -0800 +++ penaltybox.new/src/benconfig/configloader.cpp 2010-12-23 11:10:06.000000000 -0800 @@ -25,6 +25,8 @@ #include "configloader.h" #include <iostream> #include <cmath> +#include <stdio.h> +#include <stdlib.h> #include <assert.h> #include "trimstring.h" using namespace std; diff -ur penaltybox/src/capture/Capture.cpp penaltybox.new/src/capture/Capture.cpp --- penaltybox/src/capture/Capture.cpp 2006-12-13 00:53:56.000000000 -0800 +++ penaltybox.new/src/capture/Capture.cpp 2010-12-23 11:11:27.000000000 -0800 @@ -21,6 +21,10 @@ *************************************************************************/ #include "Capture.h" #include <pbconfigloader.h> +#include <string> +#include <sstream> +#include <cstring> + #include <iostream> using namespace std; diff -ur penaltybox/src/host/DayTotal.cpp penaltybox.new/src/host/DayTotal.cpp --- penaltybox/src/host/DayTotal.cpp 2006-12-11 00:20:51.000000000 -0800 +++ penaltybox.new/src/host/DayTotal.cpp 2010-12-23 11:12:53.000000000 -0800 @@ -24,6 +24,7 @@ #include <stdio.h> #include <time.h> #include <stdlib.h> +#include <strings.h> #include <string> using namespace std; diff -ur penaltybox/src/host/HostList.cpp penaltybox.new/src/host/HostList.cpp --- penaltybox/src/host/HostList.cpp 2006-12-13 01:13:37.000000000 -0800 +++ penaltybox.new/src/host/HostList.cpp 2010-12-23 11:12:25.000000000 -0800 @@ -31,6 +31,8 @@ #include "../pbconfigloader.h" #include <errno.h> #include <time.h> +#include <cstring> +#include <strings.h> using namespace std; using namespace Config; diff -ur penaltybox/src/host/HostNode.cpp penaltybox.new/src/host/HostNode.cpp --- penaltybox/src/host/HostNode.cpp 2006-08-22 15:45:19.000000000 -0700 +++ penaltybox.new/src/host/HostNode.cpp 2010-12-23 11:12:40.000000000 -0800 @@ -22,6 +22,7 @@ #include "HostNode.h" #include <iostream> +#include <strings.h> using namespace std; #include <stdio.h> #include <assert.h> diff -ur penaltybox/src/limiter/Packeteer.cpp penaltybox.new/src/limiter/Packeteer.cpp --- penaltybox/src/limiter/Packeteer.cpp 2006-12-15 18:59:04.000000000 -0800 +++ penaltybox.new/src/limiter/Packeteer.cpp 2010-12-23 11:14:01.000000000 -0800 @@ -26,6 +26,9 @@ #include "../benconfig/trimstring.h" #include "../pbconfigloader.h" #include <assert.h> +#include <string> +#include <cstring> +#include <sstream> #include <openssl/md5.h> #include <fstream> @@ -35,6 +38,7 @@ const int Inbound = 0; const int Outbound = 1; +long int ClassID = 1234567; const char * folder[] = { "Inbound/students", "Outbound/students" }; @@ -201,11 +205,17 @@ string entryStartTagEnd = "/pb-" + h->GetIp().toString() + "\">\n"; string entryFootTag = " </entry>\n</add-delete-schema-objects>\n"; - string data = " <objectclass><oc-value>iqosTrafficClass</oc-value></objectclass>\n"; + string s; + stringstream st; + + string data = " <objectclass><oc-value>iqosTrafficClass</oc-value></objectclass>\n"; data += " <attr name=\"iqosInsideHost\"><value>" + h->GetIp().toString() + "</value></attr>\n"; data += xmlpartition; data += " <attr name=\"iqosProtocolName\"><value>IP</value></attr>\n"; - + ClassID += 1; + st << ClassID; + data += " <attr name=\"iqosClassID\"><value>" + st.str() + "</value></attr>\n"; + return entryStartTagBegin + entryStartTagEnd + data + entryFootTag ; } @@ -259,12 +269,12 @@ xml = xmlhead; xml += this->DeleteXml(*r, folder[x]); xml += xmlfoot; - - sprintf(message, "+Adding Class: %s/pb-%s\n", + + sprintf(message, "+Adding Class: %s/pb-%s\n", folder[x], (*r).c_str()); - pb_log_debug(message); + pb_log_debug(message); SendRequest(xml); } r++; @@ -378,11 +388,12 @@ void Packeteer::UploadNotify() { list<string>::iterator p = hostsToNotify.begin(); - string xml = xmlhead + "<add-delete-schema-objects>\n<entry dn=\"" + HostListName + "\">\n"; + // string xml = xmlhead + "<add-delete-schema-objects>\n<entry dn=\"" + HostListName + "\">\n"; + string xml = xmlhead + "<add-delete-schema-objects>\n<entry dn=\"" + "penaltybox" + "\">\n"; xml += "<objectclass><oc-value>iqosHostList</oc-value></objectclass>\n"; while (p != hostsToNotify.end()) { - pb_log_debug("Adding " + *p + " to redirect\n"); + pb_log_debug("Adding R2 " + *p + " to redirect\n"); xml += "<attr name=\"iqosHostListNames\"><value>" + *p + "</value></attr>\n"; p++; } diff -ur penaltybox/src/pb.cpp penaltybox.new/src/pb.cpp --- penaltybox/src/pb.cpp 2007-01-11 16:24:48.000000000 -0800 +++ penaltybox.new/src/pb.cpp 2010-12-23 11:17:48.000000000 -0800 @@ -23,6 +23,10 @@ #include <iostream> #include <fstream> #include <string> +#include <cstring> +#include <strings.h> +#include <stdlib.h> +#include <stdio.h> #include <pbconfigloader.h> #include <pbversion.h> diff -ur penaltybox/src/socket/http.cpp penaltybox.new/src/socket/http.cpp --- penaltybox/src/socket/http.cpp 2006-06-30 19:39:54.000000000 -0700 +++ penaltybox.new/src/socket/http.cpp 2010-12-23 11:14:26.000000000 -0800 @@ -20,6 +20,7 @@ * Written By Benjamin Wilder <mrcawfee@sfsu.edu> *************************************************************************/ #include "http.h" +#include <strings.h> #include <iostream> using namespace std; diff -ur penaltybox/src/socket/url.cpp penaltybox.new/src/socket/url.cpp --- penaltybox/src/socket/url.cpp 2006-06-30 19:39:54.000000000 -0700 +++ penaltybox.new/src/socket/url.cpp 2010-12-23 11:14:58.000000000 -0800 @@ -21,6 +21,7 @@ *************************************************************************/ #include "url.h" #include <stdio.h> +#include <cstring> string urlencode(string s) { string result;