suggestions for multiple vlans in hundreds of switches
Arran Cudbard-Bell
A.Cudbard-Bell at sussex.ac.uk
Fri Apr 20 23:23:24 CEST 2007
Phil Mayers wrote:
> Matt Ashfield wrote:
>
>> Hi,
>>
>> We'd like to use FR to assign users on our wired network to one of 30
>> different vlans on campus, based on an LDAP field. Currently, we are doing
>> this with huntgroups. Namely, we create a huntgroup for the NAS (in our
>> case, a network switch), and then in the users file, we put the following:
>>
>
> Credit to Alan DeKok for this idea - it was one of the first questions I
> asked on the list.
>
> Use two rlm_passwd modules to add "fake" items to the *request*:
>
> passwd nas2building {
> file = /etc/raddb/nas2building
> format = "*NAS-IP-Address:~MyBuilding"
> hashsize = 100
> }
> passwd user2vlantype {
> file = /etc/raddb/user2vlantype
> format = "*User-Name:~MyVlanType"
> hashsize = 100
> allowmultiplekeys = yes
> }
>
> ...then in the users file you reduce NxM to AxB which is a hopefully
> smaller combination:
>
> DEFAULT MyBuilding == "facility1", MyVlanType == "guests"
> ...
> DEFAULT MyBuilding == "facility1", MyVlanType == "staff"
> ...
>
> Note that if you're caching the files, FreeRadius will need to be HUPed
> to re-read them (boo!). Also, you'll need to add the MyXXX attributes to
> the dictionary like so:
>
> ATTRIBUTE MyBuilding 3000 string
> ATTRIBUTE MyVlanType 3001 string
>
> This could also be done cleaner (but slower) with cleverly designed SQL
> tables or stored procedures
>
Yeah, complex sql really can be quite slow, specially when the queries
are being run multiple times for all the rounds required in eap
authentication.
> -
> List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
>
I use a second instance of preprocess to read a second hints file called
'nas_hints' this uses dynamic sql queries to grab extra nas_attributes
from the server.
I actually use a really quick and dirty way of getting multiple values
from a very simple query. You store multiple bool vars as a binary
string representation of a 6 digit integer... can then use pattern
matching in group check items to select required values and values you
dont care about.
authorization {
nas_hints
}
preprocess nas_hints {
hints = ${confdir}/nas_hints
}
Here is my nas_hints file
#############################################################
# Should speed things up when proxying peap to itself
DEFAULT Packet-Src-IP-Address == localhost
#############################################################
# Set the 'PROXY' flag in the feature set for the JRS proxies
DEFAULT Packet-Src-IP-Address == roaming0.ja.net
NAS-Feature-Set = '00000100100000000000'
DEFAULT Packet-Src-IP-Address == roaming1.ja.net
NAS-Feature-Set = '00000100100000000000'
DEFAULT Packet-Src-IP-Address == roaming2.ja.net
NAS-Feature-Set = '00000100100000000000'
#############################################################
# Debug entry for home testing.
#DEFAULT Packet-Src-IP-Address == arr-land.co.uk
# NAS-Feature-Set = '00000100100000000000'
#############################################################
# Retrieve the feature set for all none recognised clients
# from the NetReg3 Database
# Note: Doing the initial pattern match is a far quicker was of doing things
# rather than concatinating the db columns and comparing with client ip !
DEFAULT Packet-Src-IP-Address =~
"^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$"
NAS-Feature-Set = "SELECT
EXPORT_SET(master.nas_flags,'1','0','',20) FROM `master` WHERE ip1 =
'%{1}' AND ip2 = '%{2}' AND ip3 = '%{3}' AND ip4 = '%{4}' LIMIT 0,1"
Heres some group examples...
SQL result
*Host:* localhost
*Database:* radius
*Generation Time:* Apr 20, 2007 at 10:20 PM
*Generated by:* phpMyAdmin 2.9.2 / MySQL 4.1.10a-standard-log
*SQL query:* SELECT * FROM `radgroupcheck` LIMIT 0, 30 ;
*Rows:* 5
id GroupName Attribute op Value
1 nas_admins Service-Type <= NAS-Prompt-User
2 nas_admins Service-Type >= Administrative-User
3 nas_operators Service-Type == NAS-Prompt-User
20 jrs_offsite_ao Huntgroup-Name == jrs-proxy
19 jrs_offsite_ao NAS-Feature-Set =~ 00000100100000000000
Heres a fun little php script to take a list of features and produce a
bit string or integer value.
#!/usr/local/php/bin/php
<?php
if(isset($argv[1])){
if(!isset($argv[2]) ){$argv[2] = false;}
echo calc_nas_features($argv[1],$argv[2],20)."\n";
}else{
echo "/* Authentication Mediums */
'802.1', # 802.1 (Wired LAN)
'802.11', # 802.11 (Wireless LAN)
'IPSEC', # IPSEC (VPN)
'SSH', # Secure Shell/Nas Prompt Login
'HTTPS', # Captive Portal/Nas Web Interface
'PROXY', # Client Isn't a NAS it's an offsite Proxy
'unused', # For future use
'unused', # For future use
/* Extended Features */
'RADACCT',# NAS Can do RADIUS Accounting
'D802.Q', # NAS Can do Dynamic Vlan Assignment
'MULTIBESSID'); # NAS Can have multiple SSIDs / BSSIDs
";
}
function calc_nas_features($flags,$dec = true,$pad_to = null){
$def = array('802.1', '802.11', 'IPSEC', 'SSH', 'HTTPS',
'PROXY', 'unused', 'unused', 'RADACCT', 'D802.Q','MULTIBESSID');
return
calc_feature_bm(explode(',',strtoupper($flags)),$def,$dec,$pad_to);
}
/**
* Convert feature flags to base10/Little Endian binary representation
*
*
* @param string $flags
* @param string $flags_def
*
* @return string
*/
function calc_feature_bm($flags = array(),$flags_def = array(),$dec_out
= true,$pad_to = null){
$def_flags = array_flip($flags_def); # Use
arrays value as key, and posistion as BIT posistion.
if((!$pad_to) || (count($flags_def) > $pad_to)){
$bit_array = array_fill(0,count($flags_def),0);# Create an
array equal to the maximum amount of possible flgs
}else{
$bit_array = array_fill(0,$pad_to,0);# Create an array equal
to pad value, if created than maximum flags
}
foreach($flags as $value){ # For each of
the flags, see if it's value matches one of the keys
if(key_exists($value,$def_flags)){ # If it does then set
that BIT to true
$bit_array[$def_flags[$value]] = 1;
}else{ # If it
doesn't warn the user
trigger_error('Flag not found in flag
definitions.',E_USER_NOTICE);
}
}
$bin = implode('',array_reverse($bit_array));
if($dec_out == true){
return bindec($bin);
}else{
return implode('',$bit_array);
}
}
?>
If someone actually wants to do it this way, i'll put together some
proper functions for generating the bit strings and stuff...
More information about the Freeradius-Users
mailing list