DHCP relay IP and gateway IP, possible bad logic?
In case when freeradius is talking to a DHCP relay it should *always* send answears to a initiating relay IP. But, it doesn't. Cisco CMTS is using 10.10.10.1 as his giaddr for all requests made by CM's, MTA's and CPE's. All replies should go to 10.10.10.1. But, currently, if CPE gets public IP 200.200.200.2 with gateway 200.200.200.1, freeradius tries to send reply to 200.200.200.1 instead of 10.10.10.1. This is my opinion, maybe i am wrong...
Igor Smitran wrote:
In case when freeradius is talking to a DHCP relay it should *always* send answears to a initiating relay IP. But, it doesn't.
Can you supply the debug output?
Cisco CMTS is using 10.10.10.1 as his giaddr for all requests made by CM's, MTA's and CPE's. All replies should go to 10.10.10.1.
Usually... there is are some weird requirements on how DHCP operates.
But, currently, if CPE gets public IP 200.200.200.2 with gateway 200.200.200.1, freeradius tries to send reply to 200.200.200.1 instead of 10.10.10.1.
The DHCP code ignores the *routing* gateway address. It instead uses the DHCP giaddr field to send responses. Again, debug output would help here. Alan DeKok.
On 03/01/2013 04:12 PM, Alan DeKok wrote:
Can you supply the debug output? When set that freeradius sends IP, NETMASK, DNS... *WITHOUT DEFAULT GATEWAY*:
*This packet is sent to RELAY_IP* *$RAD_REPLY{'DHCP-Gateway-IP-Address'} NOT SENT* --------------------------------------------------------------------------- TIME: 09:46:24.886544 OP: 2 (BOOTPREPLY) HTYPE: 1 (Ethernet) HLEN: 6 HOPS: 1 SECS: 0 FLAGS: 0 CIADDR: 0.0.0.0 YIADDR: CPE_PUBLIC_IP SIADDR: RADIUS_IP *GIADDR: PRIVATE_RELAY_IP* CHADDR: **:**:**:**:**:**:00:00:00:00:00:00:00:00:00:00 SNAME: . FNAME: . OPTION: 53 ( 1) DHCP message type 2 (DHCPOFFER) OPTION: 1 ( 4) Subnet mask 255.255.255.240 OPTION: 2 ( 4) Time offset 7200 (2h) OPTION: 3 ( 4) Routers RELAY_PRIVATE_IP OPTION: 6 ( 4) DNS server DNS_IP OPTION: 12 ( 17) Host name HOST_MAC_ADDRESS OPTION: 15 ( 8) Domainname DOMAIN OPTION: 51 ( 4) IP address leasetime 7200 (2h) OPTION: 54 ( 4) Server identifier RADIUS_IP OPTION: 57 ( 2) Maximum DHCP message size 1500 #################################################### When set that freeradius sends IP, NETMASK, DNS... *WITH DEFAULT GATEWAY*: *This packet is sent to GIADDR**, whis is wrong**!!!* *$RAD_REPLY{'DHCP-Gateway-IP-Address'} SENT* --------------------------------------------------------------------------- TIME: 09:46:24.886544 OP: 2 (BOOTPREPLY) HTYPE: 1 (Ethernet) HLEN: 6 HOPS: 1 SECS: 0 FLAGS: 0 CIADDR: 0.0.0.0 YIADDR: CPE_PUBLIC_IP SIADDR: RADIUS_IP *GIADDR: **$RAD_REPLY{'DHCP-Gateway-IP-Address'}* CHADDR: **:**:**:**:**:**:00:00:00:00:00:00:00:00:00:00 SNAME: . FNAME: . OPTION: 53 ( 1) DHCP message type 2 (DHCPOFFER) OPTION: 1 ( 4) Subnet mask 255.255.255.240 OPTION: 2 ( 4) Time offset 7200 (2h) OPTION: 3 ( 4) Routers RELAY_PRIVATE_IP OPTION: 6 ( 4) DNS server DNS_IP OPTION: 12 ( 17) Host name HOST_MAC_ADDRESS OPTION: 15 ( 8) Domainname DOMAIN OPTION: 51 ( 4) IP address leasetime 7200 (2h) OPTION: 54 ( 4) Server identifier RADIUS_IP OPTION: 57 ( 2) Maximum DHCP message size 1500 So, when freeradius sees *DHCP-Gateway-IP-Address *inside reply offer he uses it as destination where to send reply which is wrong. He should use RELAY IP instead no matter what's inside BOOTREPLY.* *
Igor Smitran wrote:
On 03/01/2013 04:12 PM, Alan DeKok wrote:
Can you supply the debug output? When set that freeradius sends IP, NETMASK, DNS... *WITHOUT DEFAULT GATEWAY*:
The point of asking for debug output is to see what the server is doing. I'm not sure what the rest of your message means. The server defaults to copying the giaddr from the request to the reply. This is so that the reply can use the giaddr as the destination IP. If you use Perl to update the giaddr to something else... then the reply will be sent there. i.e. if you want to use the correct giaddr, don't change it.
*This packet is sent to RELAY_IP*
The point of me asking for debug output is to see *why* this is happening. When you only look at the packets, you ignore the one piece of information which will help you solve the problem.
So, when freeradius sees *DHCP-Gateway-IP-Address *inside reply offer he uses it as destination where to send reply which is wrong. He should use RELAY IP instead no matter what's inside BOOTREPLY.*
Where is the server getting the updated DHCP-Gateway-IP-Address from? Not the source code. It doesn't change it. Not the default config. It doesn't change it. So... until you show debug output, this largely looks like you edited the configuration and broke it. Don't do that. The only real bug I can see is that the offer has a non-zero giaddr field. This is wrong, as the packet is already unicast to the giaddr. The DHCP specs say that the giaddr in reply packets (offer, etc.) should be zero. I'll go fix that. Please also try with the v2.x.x branch from git. It contains some minor updates to the debug output which clarify what it's doing. Alan DeKok.
On 03/04/2013 04:54 PM, Alan DeKok wrote:
The point of asking for debug output is to see what the server is doing.
I'm not sure what the rest of your message means. The server defaults to copying the giaddr from the request to the reply. This is so that the reply can use the giaddr as the destination IP. If you use Perl to update the giaddr to something else... then the reply will be sent there.
I have to do that, this is cable IP network that i am talking about. Real life example. I am using Cisco CMTS and his primary interface IP as cable-helper/relay IP. This is by desing. I am sorry for my bad english but i will try to explain, please bare with me... This is CM/CPE bundle interface: interface Bundle1.150 vrf forwarding vrf_name ip address public_ip 255.255.255.240 secondary ip address private_ip 255.255.192.0 no ip unreachables no cable arp cable source-verify dhcp cable helper-address radius_ip end As you can see CMTS will relay all requests from CM's and CPE's over primary interface address (private_ip/255.255.192.0) radius will get all requests from that IP. all offers need to go back to that same ip, no matter what giaddr is sent to client. *i have it already working that way with another dhcp server, in production.** **also, couple of commercial products that i was testing had exactly the same logic implemented, all offers were sent to relay ip, no matter what was set as giaddr.* Let us say that i have two pools for CPE devices, imaginary: 200.200.200.0/28 200.200.100.0/28 In that case i will have two lines in bundle interface setup: ip address 200.200.200.1 255.255.255.240 secondary ip address 200.200.100.1 255.255.255.240 secondary and this is relay_ip (primary ip address of bundle interface) ip address 10.10.10.1 255.255.192.0 If dhcp finds free address from first pool (200.200.200.10/28) offer will be somethink like this: giaddr: 200.200.200.1 yiadd: 200.200.200.10 OPTION: 1 ( 4) Subnet mask 255.255.255.240 ... *but offer still needs to be sent to 10.10.10.1*, where requests came from in the first place. I didn't break anything, i have to do it that way. As far as dhcp server goes, it would be logical for him to return the offer to relay ip. relay will forward it to a client and client will get correct data. If offer goes to any other address Cisco ASA will drop that packet because it doesn't have it in initiated/established chains... Next time CPE tries to renew/release address request will come from 10.10.10.1 again... That is why i said that relay_ip shouldn't be replaced with giaddr. FR i am using is 2.2.0, latest stable version. i will try to send debug info tomorrow AM CET...
Igor Smitran wrote:
As you can see CMTS will relay all requests from CM's and CPE's over primary interface address (private_ip/255.255.192.0) radius will get all requests from that IP. all offers need to go back to that same ip, no matter what giaddr is sent to client.
Ah, OK. As always: $ git pull :) I've put some changes in to add a DHCP-Relay-IP-Address. It's visible in the reply, and is copied from the original packet giaddr. The send logic is: - if relay-ip-addr, unicast to it - if giaddr, unicast to it - if NAK or broadcast flag or no ciaddr, send broadcast - if yiaddr, unicast to it - otherwise unicast to ciaddr.
*i have it already working that way with another dhcp server, in production.** **also, couple of commercial products that i was testing had exactly the same logic implemented, all offers were sent to relay ip, no matter what was set as giaddr.*
OK. The above changes should fix that.
I didn't break anything, i have to do it that way.
OK.
As far as dhcp server goes, it would be logical for him to return the offer to relay ip. relay will forward it to a client and client will get correct data.
Yes.
i will try to send debug info tomorrow AM CET...
Please grab a copy of the v2.x.x branch from git. It should have all fixes in it, and it should work. Alan DeKok.
On 03/04/2013 07:05 PM, Igor Smitran wrote:
As you can see CMTS will relay all requests from CM's and CPE's over primary interface address (private_ip/255.255.192.0) radius will get all requests from that IP. all offers need to go back to that same ip, no matter what giaddr is sent to client.
I'm confused. First, it shouldn't matter which IP you reply to; both are on the same device, and both are routeable. Second, "reply to giaddr" is mandated in the DHCP spec; are you *sure* you have "other DHCP servers" which "reply to source ip"? Which servers?
Phil Mayers wrote:
Second, "reply to giaddr" is mandated in the DHCP spec; are you *sure* you have "other DHCP servers" which "reply to source ip"? Which servers?
The issue is that giaddr serves two purposes. In the request, it indicates that the server MUST send the reply to that IP. In the reply, it means that the client sends the NEXT request to the giaddr. ASCII art helps: client --> 1 NAS 2 ---> server The client sends broadcast packets to the NAS, using a private network The NAS unicasts them FROM NAS address "2" to the server, using giaddr = 2. NAS address "2" and the server are on a public network. The server knows that the NAS has a private address. So it sends the unicast answer back to NAS address 2", with giaddr = NAS address "1". The NAS broadcasts (or unicasts) this response back to the client. On a renew, the client unicasts the packet to NAS address "1", which forwards it to the server using address "2", and giaddr ==2. And the whole process starts again. I think I know have a handle on DHCP and RADIUS. My head is getting full... Alan DeKok.
On 03/04/2013 08:59 PM, Alan DeKok wrote:
Phil Mayers wrote:
Second, "reply to giaddr" is mandated in the DHCP spec; are you *sure* you have "other DHCP servers" which "reply to source ip"? Which servers?
The issue is that giaddr serves two purposes. In the request, it indicates that the server MUST send the reply to that IP.
In the reply, it means that the client sends the NEXT request to the giaddr.
ASCII art helps:
client --> 1 NAS 2 ---> server
The client sends broadcast packets to the NAS, using a private network The NAS unicasts them FROM NAS address "2" to the server, using giaddr = 2. NAS address "2" and the server are on a public network.
The server knows that the NAS has a private address. So it sends the unicast answer back to NAS address 2", with giaddr = NAS address "1".
The NAS broadcasts (or unicasts) this response back to the client.
On a renew, the client unicasts the packet to NAS address "1", which forwards it to the server using address "2", and giaddr ==2.
Perhaps I've misunderstood, but this doesn't reflect the DHCP behaviour I've seen on "normal" clients. As far as I know, it goes (starting from INIT, as opposed to INIT-REBOOT which effectively starts from step 4): 1. Client sends DISCOVER to broadcast 2. NAS forwards to server; giaddr==1, srcip==2 3. Server sends DHCPOFFER; dstip==giaddr, server_id=$SERVER 4. Repeat 1-3 with DHCPREQUEST/ACK 5. Client comes to t1 - unicast DHCPREQUEST dstip=$SERVER 6. If no reply, at t2 - broadcast DHCPREQUEST i.e. AFAIK, the client *always* sends packets to broadcast or to the server ident (DHCP option 54). Note the latter is mandatory in all DHCP replies. There are a bunch of subtleties in this whole area - some devices offer knobs to control giaddr in the case of multinettings, and some devices offer knobs to control srcip - but, in my experience, you are asking for trouble if giaddr is not valid for accepting relayed replies. We've had significant problems with setups where this is difficult or impossible to achieve as a result. Multinetting a private and public range onto the same interface falls into exactly that category.
Phil Mayers wrote:
Perhaps I've misunderstood, but this doesn't reflect the DHCP behaviour I've seen on "normal" clients.
It's possible.
As far as I know, it goes (starting from INIT, as opposed to INIT-REBOOT which effectively starts from step 4):
1. Client sends DISCOVER to broadcast 2. NAS forwards to server; giaddr==1, srcip==2 3. Server sends DHCPOFFER; dstip==giaddr, server_id=$SERVER 4. Repeat 1-3 with DHCPREQUEST/ACK 5. Client comes to t1 - unicast DHCPREQUEST dstip=$SERVER 6. If no reply, at t2 - broadcast DHCPREQUEST
Yes.
i.e. AFAIK, the client *always* sends packets to broadcast or to the server ident (DHCP option 54). Note the latter is mandatory in all DHCP replies.
That's the usual practice... but some clients may be weird.
There are a bunch of subtleties in this whole area - some devices offer knobs to control giaddr in the case of multinettings, and some devices offer knobs to control srcip - but, in my experience, you are asking for trouble if giaddr is not valid for accepting relayed replies. We've had significant problems with setups where this is difficult or impossible to achieve as a result. Multinetting a private and public range onto the same interface falls into exactly that category.
Yes. Maybe I got parts of the explanation wrong, but the DHCP handling of giaddr is just weird. Alan DeKok.
On 03/04/2013 11:03 PM, Phil Mayers wrote:
There are a bunch of subtleties in this whole area - some devices offer knobs to control giaddr in the case of multinettings, and some devices offer knobs to control srcip - but, in my experience, you are asking for trouble if giaddr is not valid for accepting relayed replies. We've had significant problems with setups where this is difficult or impossible to achieve as a result. Multinetting a private and public range onto the same interface falls into exactly that category. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Yes, i aggree. But, CM's are in private network. CPE's are behind CM's, in public network. CPE's are connected to CMTS through CM's. Because of that you have public and private network on one interface.
participants (3)
-
Alan DeKok -
Igor Smitran -
Phil Mayers