How to use rewrite.called_station_id IN dynamic clients authorize section
Hi, We use dynamic clients + sql for our authentication of NAS devices. We also use rlm_raw because we cannot auth on the IP Address (because of not knowing all the dynamic IP's clients are coming from), so we auth on the Called-Station-Id value. In normal circumstances this works beautifully, but when we have a NAS that sends the Called-Station-Id value as AABBCCDDEEFF with no colon or hyphen, auth fails, because in our SQL database we store the MAC like AA-BB-CC-DD-EE-FF. I already use SQL to replace colon with hyphen, but I am struggling with if it has no delimiter at all. For this particular NAS client, there is no way to change the format of the Called-Station-Id value it is sending so I need something on the FreeRadius side. I tried using the rewrite.called_station_id module from policy.conf and whilst it does not error it doesn't rewrite the incoming Called-Station-Id to the format I require. Here is my dynamic clients file: client dymamic { ... } server dynamic_client_server { authorize { #Test to see if our required raw attribute exists if("%{raw:Called-Station-Id}"){ rewrite.called_station_id #Test to see if it is in the DB if ("%{sql: select count(*) from nas where community=REPLACE(SUBSTRING(\"%{Called-Station-Id}\",1,17),\":\",\"-\")}" == 1) { update control { ... } ok } } } } I suspect it's a problem because we are using raw:Called-Station-Id because before auth Called-Station-Id itself is not accessible. Is it possible to just have a rewrite block in the authorize section of dynamic clients so it can rewrite the raw value there? Thank you, James
On 26-03-15 09:35, James Wood wrote:
Hi,
We use dynamic clients + sql for our authentication of NAS devices. We also use rlm_raw because we cannot auth on the IP Address (because of not knowing all the dynamic IP's clients are coming from), so we auth on the Called-Station-Id value.
In normal circumstances this works beautifully, but when we have a NAS that sends the Called-Station-Id value as AABBCCDDEEFF with no colon or hyphen, auth fails, because in our SQL database we store the MAC like AA-BB-CC-DD-EE-FF. I already use SQL to replace colon with hyphen, but I am struggling with if it has no delimiter at all. For this particular NAS client, there is no way to change the format of the Called-Station-Id value it is sending so I need something on the FreeRadius side.
I don't know what database you're using, but postgresql has a macaddr datatype, which fixes these kind of issues. -- Herwin Weststrate
Thanks, I will take a look. I am able to do this via SQL purely: if ("%{sql: select count(*) from nas where REPLACE(REPLACE(community, \"-\", \"\"), \":\", \"\") = REPLACE(REPLACE(SUBSTRING(\"%{raw:Called-Station-Id}\",1,17),\"-\", \"\"), \":\", \"\")}" == 1) { But it's messy and just masks the issue. Also, when we insert in to radpostauth and radacct etc the MAC format is still wrong. I am sure there is a way to format the incoming raw Called-Station-Id in dynamic clients? Thanks James
On 26-03-15 10:09, James Wood wrote:
Thanks, I will take a look. I am able to do this via SQL purely:
if ("%{sql: select count(*) from nas where REPLACE(REPLACE(community, \"-\", \"\"), \":\", \"\") = REPLACE(REPLACE(SUBSTRING(\"%{raw:Called-Station-Id}\",1,17),\"-\", \"\"), \":\", \"\")}" == 1) {
But it's messy and just masks the issue. Also, when we insert in to radpostauth and radacct etc the MAC format is still wrong.
I am sure there is a way to format the incoming raw Called-Station-Id in dynamic clients?
There is, check the policy rewrite_called_station_id. Keep in mind that if you use this data to send a Packet of Disconnect to the NAS, it might get rejected because the data is formatted differently than the NAS send it (but this might differ between NAS implementations) -- Herwin Weststrate
Hi Herwin In my original post I mentioned that in the dynamic clents authorize section it does't work as I've tried using rewrite.called_station_id. I assume its because before auth, it cannot access Called-Station-Id, only raw:Called-Station-Id Thanks James
On 26 Mar 2015, at 05:38, James Wood <james.wood@purplewifi.com> wrote:
Hi Herwin
In my original post I mentioned that in the dynamic clents authorize section it does't work as I've tried using rewrite.called_station_id. I assume its because before auth, it cannot access Called-Station-Id, only raw:Called-Station-Id
You could try running your network in a responsible and sane way, instead of relying on 3rd party hacks? -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
Adam, I would love to, but it is not under our control. As a hotspot provider, that supplies tens of thousands of customers around the world, all using different IP addresses (that change), we simply cannot use the normal way of auth via the source IP. We do not own the customers (NAS) equipment, or have control over it, so we can't make them VPN all traffic to us or other way. This is why we're having to auth on Called-Station-Id instead of IP Address. If you can think of a better way, please advise. My original question remains, how can the module rewrite.called_station_id be used with a dynamic client setup? At the moment it does not work, so is that a bug, problem with my code, or something else? I appreciate your time and thank you for your advice. Thanks James
On Mar 26, 2015, at 8:36 AM, James Wood <james.wood@purplewifi.com> wrote:
I would love to, but it is not under our control. As a hotspot provider, that supplies tens of thousands of customers around the world, all using different IP addresses (that change), we simply cannot use the normal way of auth via the source IP. We do not own the customers (NAS) equipment, or have control over it, so we can't make them VPN all traffic to us or other way. This is why we're having to auth on Called-Station-Id instead of IP Address.
I’m always surprised at just how *terrible* networks are. There is simply no reason for WiFi access points to talk directly to your RADIUS server. They should instead talk to to a local RADIUS server. That RADIUS server should deal with local IP changes. It should have a static IP to talk to your RADIUS server.
If you can think of a better way, please advise.
TBH, I’m not sure there is one. I have serious issues with butchering the FreeRADIUS source to deal with broken networks.
My original question remains, how can the module rewrite.called_station_id be used with a dynamic client setup? At the moment it does not work, so is that a bug, problem with my code, or something else?
In v3, you can manually unpack binary attributes. But rlm_raw won’t work there. You’ll have to write your own module for v2. Alan DeKok.
On 26 Mar 2015, at 09:49, Alan DeKok <aland@deployingradius.com> wrote:
On Mar 26, 2015, at 8:36 AM, James Wood <james.wood@purplewifi.com> wrote:
I would love to, but it is not under our control. As a hotspot provider, that supplies tens of thousands of customers around the world, all using different IP addresses (that change), we simply cannot use the normal way of auth via the source IP. We do not own the customers (NAS) equipment, or have control over it, so we can't make them VPN all traffic to us or other way.
When you can get sub $30 linux boxes that can act as RADIUS to RADSEC gateways you have options. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
You are describing about a perfect scenario where customers will do as you ask. When you are not supplying the kit to customers, and they are big enterprise level customers, they will not install anything 3rd party in their existing network. You try getting them to install an extra piece of kit they don't know anything about ;) They won't do it. So we have two options, work with what they have, or drop them as a customer. As I said, there is no choice when we do not control/own their network, we have to (sadly) work with what they have. No two systems are the same and we try to cater for them all. Thanks James
2015-03-26 14:49 GMT+01:00 James Wood <james.wood@purplewifi.com>:
Hi Ben
I use the rewrite.called_station_id in the sites-enabled/default file in the relevant places and that works fine, but this particular question is regarding the sites-enabled/dynamic-clients file authorize section.
Yes, sorry, my fault. Wasn't aware about the special behaviour of the "dynamic-clients" server name before. Can you please post your sites-enabled/dynamic-clients file as well as the structure of an entry in the nas table filled with example data? 2015-03-26 15:32 GMT+01:00 James Wood <james.wood@purplewifi.com>:
You are describing about a perfect scenario where customers will do as you ask.
When you are not supplying the kit to customers, and they are big enterprise level customers, they will not install anything 3rd party in their existing network. You try getting them to install an extra piece of kit they don't know anything about ;) They won't do it.
That's true for big enterprises but those already have the hardware and software to do VPN or use services like DynDNS or already have hardware that submits the data in the correct format. Small customers does not but are more likely willed to install a kit. Regardless of the size of your customers you really should have "minimum requirements" they have to meet. They then can decide if they want to install a kit you've provided or if they want to buy hardware which meets these requirements themselves.
So we have two options, work with what they have, or drop them as a customer.
As I said, there is no choice when we do not control/own their network, we have to (sadly) work with what they have. No two systems are the same and we try to cater for them all.
I know that and understand your problem. However with that behaviour you're just weakening your service security. Soon you maybe have to allow Radius clients from 0.0.0.0 because of the diversity of NAS submitted data and that means a huge vulnerability. In case the Radius gets DDoSed your customers either wouldn't get their consumers data updated or their hotspot would be offline. And in case the Radius gets hacked your customers data could get modified or extracted and published / abused. The result is always the same: very angry customers and you'll make the news. I guess you are aware of that but your boss - who made the decision to "allow everybody" - is not. Whatsoever, if being more secure isn't a solution at all I'll wait for your reply with the requested data and think about the most secure solution to get your problem solved.
On Mar 26, 2015, at 9:32 AM, James Wood <james.wood@purplewifi.com> wrote:
When you are not supplying the kit to customers, and they are big enterprise level customers, they will not install anything 3rd party in their existing network. You try getting them to install an extra piece of kit they don't know anything about ;) They won't do it.
If they’re running a WiFi network with RADIUS, they should understand RADIUS. And use it properly. Heck, if they’re running *your* captive portal, your captive portal should be able to do IPSec to your central system. I just don’t see any reason for allowing random IPs to talk to a central RADIUS server. It’s a terrible design. It’s insecure, unstable, and hard to maintain. Alan DeKok.
I just saw that your customers have install a customized Purple WiFi firmware on their router. The easiest solution would be to implement a DynDNS like client. Then you could move away from dynamic-clients and use FQDN names for the clients instead and the problems are solved. You also could implement VPN (PPTP would be enough) so you could assign IPs of an internal network to your clients. You could move away from dynamic-clients too since each client has it's static internal IP. You even could sync that with Radius & LDAP. However, VPN would require you to keep a VPN server running on your side and it may cause troubles with routing of internet traffic so I would go with the DynDNS solution. 2015-03-26 15:32 GMT+01:00 James Wood <james.wood@purplewifi.com>:
You are describing about a perfect scenario where customers will do as you ask.
When you are not supplying the kit to customers, and they are big enterprise level customers, they will not install anything 3rd party in their existing network. You try getting them to install an extra piece of kit they don't know anything about ;) They won't do it.
So we have two options, work with what they have, or drop them as a customer.
As I said, there is no choice when we do not control/own their network, we have to (sadly) work with what they have. No two systems are the same and we try to cater for them all.
Thanks
James
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Hi Ben Our routers are not an issue, we already vpn traffic back. Thats for our small customers and it works great. I'm talking about the enterprise market where we can't get a VPN or tunnel as much as we would like. We are revisiting our approach and solution but at this time we have what we have. I know it's not great. Dynamic clients file: client dymamic { ... } server dynamic_client_server { authorize { #Test to see if our required raw attribute exists if("%{raw:Called-Station-Id}"){ rewrite.called_station_id #Test to see if it is in the DB if ("%{sql: select count(*) from nas where community=REPLACE(SUBSTRING(\"%{Called-Station-Id}\",1,17),\":\",\"-\")}" == 1) { update control { ... } ok } } } } NAS client example below from our DB. Columns --------------- nasname shortname type ports secret server community description router_type Values ----------------- 00-18-0A-33-0C-5E other NULL xxxxxxxxxxx NULL 00-18-0A-33-0C-5E RADIUS Client Meraki AP Thanks again, James
hi, use unlang and a regex check to convert the CSI into format needed (or use the macaddress subclass native to postgres if thats your DB...then it doesnt really care I'd advise using google as a good starting point eg start with this and adapt: if ( "%{request:Calling-Station-Id}" =~ /^([0-9a-f]{2}).?([0-9a-f]{2}).?([0-9a-f]{2}).?([0-9a-f]{2}).?([0-9a-f]{2}).?([0-9a-f]{2})$/i ) { update request { Calling-Station-Id := "%{1}-%{2}-%{3}-%{4}-%{5}-%{6}" } } alan
2015-03-26 14:36 GMT+01:00 James Wood <james.wood@purplewifi.com>:
Adam,
I would love to, but it is not under our control. As a hotspot provider, that supplies tens of thousands of customers around the world, all using different IP addresses (that change), we simply cannot use the normal way of auth via the source IP. We do not own the customers (NAS) equipment, or have control over it, so we can't make them VPN all traffic to us or other way. This is why we're having to auth on Called-Station-Id instead of IP Address.
Does that mean that you neither supply nor enforce a list of accepted devices but that customers can use any wifi AP they want? What if one of these devices doesn't send a Called-Station-Id at all or uses the MAC of the supplicant (which should be Calling-Station-Id) for the Called-Station-Id? Do you then disallow the usage of that NAS or do you try to modify your Radius to also accept these NAS data too? My NAS all have static IPs, all supplicants have dynamic IPs, however (yet) my Radius doesn't check for IPs but only for Called-Station-Id, Called-Station-Ssid and Calling-Station-Id so it would work in a complete dynamic ip setup too.
If you can think of a better way, please advise.
1) Don't use unlang (if () {} ...) in the server configurations. Instead simply call a policy (eg. policy.sanitize_called-station-id) and do all the if then else stuff in that policy itself. It keeps your server config clean and you can easily disable a policy without having to comment out or delete plenty of lines. 2) Sanitize all informations you get as soon as possible so that you don't have to tweak over and over again for subsequent checks you may be doing in the future.
My original question remains, how can the module rewrite.called_station_id be used with a dynamic client setup? At the moment it does not work, so is that a bug, problem with my code, or something else?
# sites-enabled/something server something { ... authorize { policy.sanitize_called-station-id ... } ... } # policy.conf mac-addr-regexp = '([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})' policy.sanitize_called-station-id { if (&Called-Station-Id && (&Called-Station-Id =~ /^${policy.mac-addr-regexp}([^0-9a-f](.+))?$/i)) { update request { &Called-Station-Id := "%{toupper:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}" } updated } else { noop } } That's it. As I wrote in my previous email that regex is the standard in the freeradius source 3.0.7 and as well in the old 2.1.12 debian package and it matches variants of the following: 00-11-22-33-44-55 00-11-22-33-44-55:SSID Also the delimiter can be anything except 0-9 or a-f so even 00Z11=22$33(44)55 (and for sure 001122334455) would be sanitized to 00-11-22-33-44-55. In my setup I also use Called-Station-Ssid but you don't use it in your setup I just removed the lines. Regardless of if a customers NAS sends the SSID suffixed to the mac address or not, the Called-Station-Id will always gets rewritten to 00-11-22-33-44-55 and the maybe attched SSID gets dropped. If you want to know why your current setup is not working, send your policy.conf to me (not the list). Maybe someone "improved" your regex and that's why it's not matching and thus not rewriting :) Best regards, Ben
Hi Ben On our back end, we have a list of allowed MACs (Called-Station-Id's). When the radius auth requst comes in, only ones that match are dynamically allowed, else we just do not reply and ignore the request. We only support a certain list of approved wifi equipment that we've tested to work with our solution, Cisco, Ruckus, Aerohive, HP etc etc. The MAC that we check against is the MAC that we know their kit will be sending the request with. We do not try to modify our Radius to accept all types, only ones we know work correctly and send the correct fields. This issue has arisen because one piece of kit we're trying to support works perfectly apart from the fact it is sending the Called-Station-Id value without any delimiters, so I was simply asking what's the best way to handle this in FreeRadius, because everything else we support sends in the AA-BB-CC-DD-EE-FF format, which matches the format we store in our DB. Hope that clarifies it. I still have the same problem though. In the dynamic-clients file, I am trying to use rewrite.called_station_id straight after authorize { but it's not working. Is this because I am having to use raw:Called-Station-Id instead of just Called-Station-Id ? Thanks James
2015-03-26 9:35 GMT+01:00 James Wood <james.wood@purplewifi.com>:
I tried using the rewrite.called_station_id module from policy.conf and whilst it does not error it doesn't rewrite the incoming Called-Station-Id to the format I require.
My NAS always send in the correct format, however I have set rewrite.called_station_id at the very first in authorize {} because it should be the first thing to be done. I could sanitize it just when sending it to LDAP but then Radius would always use the wrong format. That is why you don't want to sanitize it just in the SQL query. What you should do is modifying the regex used in the rewrite.called_station_id policy to also match 001122334455 formats. In authorize at least &Called-Station-Id is available, probably also %{Called-Station-Id}. There is a nice regex tester at http://www.freeformatter.com/regex-tester.html The default regex used is ^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$ and this matches 00-11-22-33-44-55 and 00:11:22:33:44:55 and 001122334455 as well as other formats.
Hi Ben I use the rewrite.called_station_id in the sites-enabled/default file in the relevant places and that works fine, but this particular question is regarding the sites-enabled/dynamic-clients file authorize section. As mentioned before I think it's having trouble because at this stage, Called-Station-Id is not available, only raw:Called-Station-Id. The normal attributes don't become available until FreeRadius has authed the NAS and explodes the packet. That's my understanding anyway, could be wrong! Thanks James
Hi,
As mentioned before I think it's having trouble because at this stage, Called-Station-Id is not available, only raw:Called-Station-Id. The normal attributes don't become available until FreeRadius has authed the NAS and explodes the packet.
then use raw:Called-Station-Id - assign it to a variable if need be... if its there, it can be used (and changed) alan
In normal circumstances this works beautifully, but when we have a NAS that sends the Called-Station-Id value as AABBCCDDEEFF with no colon or hyphen, auth fails, because in our SQL database we store the MAC like AA- BB-CC-DD-EE-FF. I already use SQL to replace colon with hyphen, but I am struggling with if it has no delimiter at all. For this particular NAS client, there is no way to change the format of the Called-Station-Id value it is sending so I need something on the FreeRadius side.
You could create view on your database table that gives two result columns one with dashes and one without. Then build your freeradius check with an OR statement in it... But personally I would normalise down to the lowest format, i.e. no delimieters at all, all the time. Then add a view to your database that removes the dashes when selecting the MAC fields. Then strip dashes, colons, spaces or whatever from the select that freeradius uses so you are only ever comparing at the lowest common format. Kev/.
participants (7)
-
A.L.M.Buxey@lboro.ac.uk -
Alan DeKok -
Arran Cudbard-Bell -
Ben Humpert -
Herwin Weststrate -
James Wood -
Kev Pearce