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...