DHCP NAT (and Relay) and Static Addressing based on Option82/Circuit ID
Hi, I'm working through setting up FreeRADIUS to behave as a DHCP Server so that it can read and respond to DHCP Packets (including Option 82 info). I'm making progress - however I am facing a few roadblocks that I would like some guidance on if possible. *Packets forwarded from an internal network which are translated out to us and carry a DHCP-Relay-IP-Address* DHCP Requests that are being sent to us include a Relay-IP-Address - and implicitly the DHCP module seems to use this as an authority and attempts to return the packet to the Relay IP, not the source of the packet. I was able to comment out in the source (3.0.12) - "modules/proto_dhcp/dhcpd.c" on line 497 (where it sets a new destination IP address) - and the packet was returned to the originator. Obviously this is not the way I should be doing this - so any suggestions are welcome. *DHCP IP Addressing from SQLIPool* I have the radippool (via dhcp_sqlippool) process able to extract an IP address based on the Circuit ID (Option 82) contained within the DHCP Packet. The challenge I have, is the IP addresses I am allocating (for the same provider, but we will also have multiple providers who use our system) - has different gateways based on the location of the service and the IP allocated. From what I can ascertain looking at the source code, the DHCP Pool functionality presently only deals with the returning of the Framed-IP-Address. Looking at "modules/rlm_sqlippool/rlm_sqlippool.c" (line 580) - there is an object called 'inst' with a property called framed_ip_address. This is used to build a 'vp' and adds it to the reply. How would one go about providing database driven gateway/dns settings? Is there a way? Or is the only option to add support for additional properties in the code for this? (I would need to isolate where the framed_ip_address is mapped to Framed-IP-Address to follow the similar behaviour. Hope you can help! Thanks Martin. Martin Edge Chief Technical Officer [Description: Description: Emersion Logo] Emersion saves you time and money, by providing an easy to use, secure and scalable billing, provisioning & operational support system delivered as a service in the cloud. Emersion Software Systems Pty Ltd Twitter: .......... @EmersionBilling ________________________________ This communication may contain CONFIDENTIAL or copyright information of Emersion Software Systems Pty Ltd (ABN 28 119 061 791). If you are not an intended recipient, you MUST NOT read, print, keep, forward, copy, use, save, retransmit or rely on this communication or any attachments, and any such action is unauthorised and prohibited. If you have received this communication in error, please reply to this e-mail to notify the sender of its incorrect delivery, and then delete both it and your reply. Emersion does not guarantee the integrity of any emails or any attached files. The views or opinions expressed are the author's own and may not reflect the views or opinions of Emersion. Thank you. ________________________________
Hi, I can't comment on the IP address the response should be returned to - we convinced our BNGs to source all the DHCP-relay packets from a single loopback. When it comes to extracting more data from the db we skipped the sqlippool module completely and use unlang only. Roughly the setup looks like this (some details relevant to our internal config are stripped here), the same setup inside DHCP-Discover and DHCP-request: update { &control:Tmp-String-1 := "%{%{string:request:DHCP-Relay-Remote-Id}:-%{string:request:DHCP-Relay-Circuit-Id}}" } update { &control:Tmp-String-0 := "%{frontend_sql:SELECT host(ipaddress) || '#' || host(defaultgateway) || '#' || host(netmask(('0.0.0.0/' || subnetmask)::inet)) FROM ip, ippool WHERE ip.username='%{control:Tmp-String-1}' AND ip.poolname = ippool.poolname LIMIT 1}" } } if (control:Tmp-String-0 =~ /([0-9\.]+)#([0-9\.]+)#([0-9\.]+)/) { update { &reply:DHCP-Your-IP-Address := "%{1}" &reply:DHCP-Gateway-IP-Address := "%{DHCP-Gateway-IP-Address}" &reply:DHCP-Router-Address := "%{2}" &reply:DHCP-Subnet-Mask := "%{3}" &reply:DHCP-DHCP-Server-Identifier := X.X.X.X } } This works since we pre-allocate the IP during the radius phase, when the session is created, this way the DHCP only has to select an existing IP. We de-allocate based on radius information (Accounting-Stop) and not on DHCP-Release (which we quietly ignore). I don't see any reason why you couldn't do the allocation and de-allocation in the DHCP server. kind regards Pshem On Tue, 22 Nov 2016 at 19:28 Martin Edge <medge@emersion.com> wrote:
Hi,
I'm working through setting up FreeRADIUS to behave as a DHCP Server so that it can read and respond to DHCP Packets (including Option 82 info).
I'm making progress - however I am facing a few roadblocks that I would like some guidance on if possible.
*Packets forwarded from an internal network which are translated out to us and carry a DHCP-Relay-IP-Address* DHCP Requests that are being sent to us include a Relay-IP-Address - and implicitly the DHCP module seems to use this as an authority and attempts to return the packet to the Relay IP, not the source of the packet. I was able to comment out in the source (3.0.12) - "modules/proto_dhcp/dhcpd.c" on line 497 (where it sets a new destination IP address) - and the packet was returned to the originator. Obviously this is not the way I should be doing this - so any suggestions are welcome.
*DHCP IP Addressing from SQLIPool* I have the radippool (via dhcp_sqlippool) process able to extract an IP address based on the Circuit ID (Option 82) contained within the DHCP Packet.
The challenge I have, is the IP addresses I am allocating (for the same provider, but we will also have multiple providers who use our system) - has different gateways based on the location of the service and the IP allocated. From what I can ascertain looking at the source code, the DHCP Pool functionality presently only deals with the returning of the Framed-IP-Address.
Looking at "modules/rlm_sqlippool/rlm_sqlippool.c" (line 580) - there is an object called 'inst' with a property called framed_ip_address. This is used to build a 'vp' and adds it to the reply.
How would one go about providing database driven gateway/dns settings?
Is there a way? Or is the only option to add support for additional properties in the code for this? (I would need to isolate where the framed_ip_address is mapped to Framed-IP-Address to follow the similar behaviour.
Hope you can help! Thanks Martin.
Martin Edge Chief Technical Officer
[Description: Description: Emersion Logo] Emersion saves you time and money, by providing an easy to use, secure and scalable billing, provisioning & operational support system delivered as a service in the cloud.
Emersion Software Systems Pty Ltd Twitter: .......... @EmersionBilling
________________________________ This communication may contain CONFIDENTIAL or copyright information of Emersion Software Systems Pty Ltd (ABN 28 119 061 791). If you are not an intended recipient, you MUST NOT read, print, keep, forward, copy, use, save, retransmit or rely on this communication or any attachments, and any such action is unauthorised and prohibited. If you have received this communication in error, please reply to this e-mail to notify the sender of its incorrect delivery, and then delete both it and your reply. Emersion does not guarantee the integrity of any emails or any attached files. The views or opinions expressed are the author's own and may not reflect the views or opinions of Emersion. Thank you. ________________________________
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On Nov 22, 2016, at 1:23 AM, Martin Edge <medge@emersion.com> wrote:
I'm making progress - however I am facing a few roadblocks that I would like some guidance on if possible.
*Packets forwarded from an internal network which are translated out to us and carry a DHCP-Relay-IP-Address* DHCP Requests that are being sent to us include a Relay-IP-Address - and implicitly the DHCP module seems to use this as an authority and attempts to return the packet to the Relay IP, not the source of the packet. I was able to comment out in the source (3.0.12) - "modules/proto_dhcp/dhcpd.c" on line 497 (where it sets a new destination IP address) - and the packet was returned to the originator. Obviously this is not the way I should be doing this - so any suggestions are welcome.
That may work for you, but it's wrong. https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_relay... DHCP servers MUST respond to the relay IP address (giaddr). NOT to the source IP of the packet. If you want to change this behaviour, don't edit the server source. Just do: if (&DHCP-Relay-IP-Address) { update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } }
*DHCP IP Addressing from SQLIPool* I have the radippool (via dhcp_sqlippool) process able to extract an IP address based on the Circuit ID (Option 82) contained within the DHCP Packet.
The challenge I have, is the IP addresses I am allocating (for the same provider, but we will also have multiple providers who use our system) - has different gateways based on the location of the service and the IP allocated. From what I can ascertain looking at the source code, the DHCP Pool functionality presently only deals with the returning of the Framed-IP-Address.
Yes. If you're allocating multiple sets of IPs, you should set up multiple IP pools. Then, return service, options, etc. based on the DHCP pool. Not on the IP allocated.
Looking at "modules/rlm_sqlippool/rlm_sqlippool.c" (line 580) - there is an object called 'inst' with a property called framed_ip_address. This is used to build a 'vp' and adds it to the reply.
How would one go about providing database driven gateway/dns settings?
Put them into a database. First, create the schema. Probably columns of Pool-Name, followed by columns of other DHCP settings. Then, set that. You could probably tweak the main "sql" module to do this. Alan DeKok.
Hi Alan, Thanks for your reply. -DHCP Relay issue- Totally agree against modifying the source! It was a temporary path of desperation to fit inside restrictive timelines :) The change you have suggested - where in the many configuration files would that go? I have attempted to put it in sites-enabled/dhcp and in mods-enabled/preprocess - which parses fine, but essentially seems to do nothing. I've removed the if condition in case something was going weird there. update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } What's the difference between the ampersand at the front and not? And using ':=' versus '='? Best case scenario I would probably want to put something specific for this customer versus breaking the rules all the time, for instance If (&DHCP-Relay-IP-Address && "%{Packet-Src-IP-Address}" == "x.x.x.x") { update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } } -DHCP Settings- OK. When you say 'sql' module, can I have you elaborate a little on that? As in modify the SQL module itself or is there something I should be able to do leveraging existing functionality? Is there some documentation or reference that would be worth me reading to figure this out? I see the definition of a table 'usergroup_table' for instance, but I'm unable to see how it all stitches together. Also not sure if this suggests I might be taking the wrong path - presently the 'Pool' I'm using is actually not really a pool, it's a 1:1 between Circuit ID (Service) and the IP address. Thanks again, Martin. On Nov 22, 2016, at 1:23 AM, Martin Edge <medge@emersion.com> wrote:
I'm making progress - however I am facing a few roadblocks that I would like some guidance on if possible.
*Packets forwarded from an internal network which are translated out to us and carry a DHCP-Relay-IP-Address* DHCP Requests that are being sent to us include a Relay-IP-Address - and implicitly the DHCP module seems to use this as an authority and attempts to return the packet to the Relay IP, not the source of the packet. I was able to comment out in the source (3.0.12) - "modules/proto_dhcp/dhcpd.c" on line 497 (where it sets a new destination IP address) - and the packet was returned to the originator. Obviously this is not the way I should be doing this - so any suggestions are welcome.
That may work for you, but it's wrong. https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_relay... DHCP servers MUST respond to the relay IP address (giaddr). NOT to the source IP of the packet. If you want to change this behaviour, don't edit the server source. Just do: if (&DHCP-Relay-IP-Address) { update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } }
*DHCP IP Addressing from SQLIPool* I have the radippool (via dhcp_sqlippool) process able to extract an IP address based on the Circuit ID (Option 82) contained within the DHCP Packet.
The challenge I have, is the IP addresses I am allocating (for the same provider, but we will also have multiple providers who use our system) - has different gateways based on the location of the service and the IP allocated. From what I can ascertain looking at the source code, the DHCP Pool functionality presently only deals with the returning of the Framed-IP-Address.
Yes. If you're allocating multiple sets of IPs, you should set up multiple IP pools. Then, return service, options, etc. based on the DHCP pool. Not on the IP allocated.
Looking at "modules/rlm_sqlippool/rlm_sqlippool.c" (line 580) - there is an object called 'inst' with a property called framed_ip_address. This is used to build a 'vp' and adds it to the reply.
How would one go about providing database driven gateway/dns settings?
Put them into a database. First, create the schema. Probably columns of Pool-Name, followed by columns of other DHCP settings. Then, set that. You could probably tweak the main "sql" module to do this. Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
The change you have suggested - where in the many configuration files would that go?
sites-enabled/dhcp
I have attempted to put it in sites-enabled/dhcp and in mods-enabled/preprocess - which parses fine, but essentially seems to do nothing. I've removed the if condition in case something was going weird there.
Run the server in debug mode (-X) and paste the whole of the output into and email to this list What's the difference between the ampersand at the front and not? And using
':=' versus '='?
See man unlang. The ampersand was introduced in version 3.0
OK. When you say 'sql' module, can I have you elaborate a little on that? As in modify the SQL module itself or is there something I should be able to do leveraging existing functionality?
The main SQL module is normally used for RADIUS authentication. But you can probably tweak the SQL statements and/or add some unlang to do what you want. You don't need to edit source code. However you can also run any random SQL statement and put the output into an attribute like this: update control { &Tmp-String-0 := "%{sql:SELECT some_value FROM some_table WHERE mac = '%{DHCP-Client-Hardware-Address}'}" }
On Nov 22, 2016, at 7:47 PM, Martin Edge <medge@emersion.com> wrote
-DHCP Relay issue- Totally agree against modifying the source! It was a temporary path of desperation to fit inside restrictive timelines :)
The change you have suggested - where in the many configuration files would that go?
In raddb/sites-enabled/dhcp. Please *read* it. It helps.
I have attempted to put it in sites-enabled/dhcp and in mods-enabled/preprocess - which parses fine, but essentially seems to do nothing. I've removed the if condition in case something was going weird there.
Don't put run-time statements into module configurations. You can't just add random things to random files and expect it to work. The configuration is documented. There are hundreds of examples.
Best case scenario I would probably want to put something specific for this customer versus breaking the rules all the time, for instance
If (&DHCP-Relay-IP-Address && "%{Packet-Src-IP-Address}" == "x.x.x.x") { update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } }
Yes, that works.
-DHCP Settings- OK. When you say 'sql' module, can I have you elaborate a little on that? As in modify the SQL module itself or is there something I should be able to do leveraging existing functionality?
Is there some documentation or reference that would be worth me reading to figure this out?
It's not that hard to find the documentation.
I see the definition of a table 'usergroup_table' for instance, but I'm unable to see how it all stitches together.
http://wiki.freeradius.org Type "sql" into the search bar. Read the documentation. It is *extensively* documented.
Also not sure if this suggests I might be taking the wrong path - presently the 'Pool' I'm using is actually not really a pool, it's a 1:1 between Circuit ID (Service) and the IP address.
Then it's static IP assignment, and not pools. Alan DeKok.
Alan, I read your DHCP File over and over, I am unclear which part should be glaringly obvious to me. Anyway, I have solved the issue. Now I can better follow the debug output - There isn't a DHCP-Relay attribute, rather a DHCP-Gateway address, which seems to *create* the DHCP-Relay attribute - so my condition was never going to work. It would seem the updated Relay-IP-Address needs to go in the 'reply' not the 'request'. I have now done this and it seems to be working. if (&DHCP-Gateway-IP-Address && "%{Packet-Src-IP-Address}" == "43.x.x.65") { update reply { &DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } } -Pools- (static) Yes, finding the documentation is easy when you understand the context of what you're being told. I'm sure I'll figure it out. Regards Martin. -----Original Message----- From: Freeradius-Users [mailto:freeradius-users-bounces+medge=emersion.com@lists.freeradius.org] On Behalf Of Alan DeKok Sent: Thursday, 24 November 2016 1:50 AM To: FreeRadius users mailing list <freeradius-users@lists.freeradius.org> Subject: Re: DHCP NAT (and Relay) and Static Addressing based on Option82/Circuit ID On Nov 22, 2016, at 7:47 PM, Martin Edge <medge@emersion.com> wrote
-DHCP Relay issue- Totally agree against modifying the source! It was a temporary path of desperation to fit inside restrictive timelines :)
The change you have suggested - where in the many configuration files would that go?
In raddb/sites-enabled/dhcp. Please *read* it. It helps.
I have attempted to put it in sites-enabled/dhcp and in mods-enabled/preprocess - which parses fine, but essentially seems to do nothing. I've removed the if condition in case something was going weird there.
Don't put run-time statements into module configurations. You can't just add random things to random files and expect it to work. The configuration is documented. There are hundreds of examples.
Best case scenario I would probably want to put something specific for this customer versus breaking the rules all the time, for instance
If (&DHCP-Relay-IP-Address && "%{Packet-Src-IP-Address}" == "x.x.x.x") { update request { DHCP-Relay-IP-Address := "%{Packet-Src-IP-Address}" } }
Yes, that works.
-DHCP Settings- OK. When you say 'sql' module, can I have you elaborate a little on that? As in modify the SQL module itself or is there something I should be able to do leveraging existing functionality?
Is there some documentation or reference that would be worth me reading to figure this out?
It's not that hard to find the documentation.
I see the definition of a table 'usergroup_table' for instance, but I'm unable to see how it all stitches together.
http://wiki.freeradius.org Type "sql" into the search bar. Read the documentation. It is *extensively* documented.
Also not sure if this suggests I might be taking the wrong path - presently the 'Pool' I'm using is actually not really a pool, it's a 1:1 between Circuit ID (Service) and the IP address.
Then it's static IP assignment, and not pools. Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
participants (4)
-
Alan DeKok -
Martin Edge -
Pshem Kowalczyk -
Бен Томпсон