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.