DHCP relay - wrong interface for relayed packet
Paul Thornton
paul at prt.org
Sun Jul 10 10:16:32 UTC 2022
Hi Alan, Matthew (and anyone else following this),
I've been doing some more digging with this over the past couple of
days, but haven't had much success. I think I now understand the
problem though.
On 07/07/2022 20:26, Alan DeKok wrote:
> You can make it use port 67 by the following:
>
> update reply {
> Packet-Dst-Port := 67
> }
>
> It will then send the packets to port 67 instead of 1067.
Firstly, updating the reply port doesn't seem to make any difference.
The debug shows that config being treated as a no-op:
Received DHCP-Offer of Id 90779350 from 217.198.54.101:1067 to
217.198.52.2:1067
DHCP-Opcode = Server-Message
DHCP-Hardware-Type = Ethernet
DHCP-Hardware-Address-Length = 6
DHCP-Hop-Count = 1
DHCP-Transaction-Id = 2423755600
DHCP-Number-of-Seconds = 0
DHCP-Flags = 0
DHCP-Client-IP-Address = 0.0.0.0
DHCP-Your-IP-Address = 217.198.52.10
DHCP-Server-IP-Address = 0.0.0.0
DHCP-Gateway-IP-Address = 217.198.52.2
DHCP-Client-Hardware-Address = 90:e2:ba:86:3c:24
DHCP-Message-Type = DHCP-Offer
DHCP-Subnet-Mask = 255.255.255.0
DHCP-Router-Address = 217.198.52.1
DHCP-Domain-Name-Server = 8.8.8.8
DHCP-Domain-Name-Server = 8.8.4.4
DHCP-Hostname = "lfc223"
DHCP-IP-Address-Lease-Time = 1209823
DHCP-DHCP-Server-Identifier = 217.198.54.101
DHCP-Client-Identifier = 0x0190e2ba863c24
DHCP-Network-Subnet = 217.198.52.2/32
(4) Received code 1026 Id 2423755600 from 217.198.54.101:1067 to
217.198.52.2:1067 length 300
(4) DHCP-Opcode = Server-Message
(4) DHCP-Hardware-Type = Ethernet
(4) DHCP-Hardware-Address-Length = 6
(4) DHCP-Hop-Count = 1
(4) DHCP-Transaction-Id = 2423755600
(4) DHCP-Number-of-Seconds = 0
(4) DHCP-Flags = 0
(4) DHCP-Client-IP-Address = 0.0.0.0
(4) DHCP-Your-IP-Address = 217.198.52.10
(4) DHCP-Server-IP-Address = 0.0.0.0
(4) DHCP-Gateway-IP-Address = 217.198.52.2
(4) DHCP-Client-Hardware-Address = 90:e2:ba:86:3c:24
(4) DHCP-Message-Type = DHCP-Offer
(4) DHCP-Subnet-Mask = 255.255.255.0
(4) DHCP-Router-Address = 217.198.52.1
(4) DHCP-Domain-Name-Server = 8.8.8.8
(4) DHCP-Domain-Name-Server = 8.8.4.4
(4) DHCP-Hostname = "lfc223"
(4) DHCP-IP-Address-Lease-Time = 1209823
(4) DHCP-DHCP-Server-Identifier = 217.198.54.101
(4) DHCP-Client-Identifier = 0x0190e2ba863c24
(4) DHCP-Network-Subnet = 217.198.52.2/32
Trying sub-section dhcp DHCP-Offer {...}
(4) dhcp DHCP-Offer {
(4) update reply {
(4) Packet-Dst-Port := 67
(4) } # update reply = noop
(4) [ok] = ok
(4) } # dhcp DHCP-Offer = ok
(4) DHCP: response will be broadcast
DHCP-Opcode = Server-Message
DHCP-Hardware-Type = Ethernet
DHCP-Hardware-Address-Length = 6
DHCP-Hop-Count = 1
DHCP-Transaction-Id = 2423755600
DHCP-Number-of-Seconds = 0
DHCP-Flags = 0
DHCP-Client-IP-Address = 0.0.0.0
DHCP-Your-IP-Address = 217.198.52.10
DHCP-Server-IP-Address = 0.0.0.0
DHCP-Gateway-IP-Address = 217.198.52.2
DHCP-Client-Hardware-Address = 90:e2:ba:86:3c:24
DHCP-Server-Host-Name = ""
DHCP-Boot-Filename = ""
DHCP-Subnet-Mask = 255.255.255.0
DHCP-Router-Address = 217.198.52.1
DHCP-Domain-Name-Server = 8.8.8.8
DHCP-Domain-Name-Server = 8.8.4.4
DHCP-Hostname = "lfc223"
DHCP-IP-Address-Lease-Time = 1209823
DHCP-DHCP-Server-Identifier = 217.198.54.101
DHCP-Client-Identifier = 0x0190e2ba863c24
Sending DHCP-Offer Id 90779350 from 0.0.0.0:1067 to 255.255.255.255:1067
(4) Not sending reply to client.
(4) Finished request
(4) Cleaning up request packet ID 2423755600 with timestamp +89 due to done
Ready to process requests
The second part of the problem is that the offer that gets broadcasted
on port 1067 goes out of the wrong interface - because the listen
section for port 1067 doesn't have an interface configured by design as
we're using it to receive packets from the upstream server via normal
unicast routing. A quick tcpdump shows that broadcast going out of the
default route interface (which is, I suppose, one stage better than the
kernel just throwing it away with a shrug).
My high level thoughts on "fixing" this is:
If we want to DHCP relay to another port then there needs to be a
listener for that other port. If we are relaying to a server not on the
same LAN (likely) then this port cannot be bound to a particular interface.
In fr_dhcp_send (or its callers) there needs to be a way to switch to
this listener's socket to relay DISCOVER and REQUEST towards the server;
and there needs to be a way to switch from this socket back to the
original interface-bound socket to relay OFFER and ACK/NAK towards the
client.
Does this sound logical or have I missed something glaringly obvious?
I've already tested the upstream with a quick hack to just create a new
socket and send the packet. The downstream replies need some state
saving whilst relaying DISCOVER or REQUEST to know what socket it was
received on, so that when relaying the corresponding OFFER or ACK/NAK it
can use that socket to transmit on.
Any clues as to how I can go about testing the second half of this - any
pointers to how I should find out the socket to send on etc.?
> We should arguably also support RFC 8357, which defines a "Remember Relay-Port" option. If the option exists, the reply should be sent to the UDP source port of the packet.
>
> FreeRADIUS has always done that, because hard-coding port 67 is stupid.
Indeed.
Paul.
More information about the Freeradius-Users
mailing list