DHCP relay - wrong interface for relayed packet

Alan DeKok aland at deployingradius.com
Sun Jul 10 13:08:26 UTC 2022


On Jul 10, 2022, at 6:16 AM, Paul Thornton <paul at prt.org> wrote:ackets 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:

  OK.  The rest of the server respects that, so that's likely an easy fix.

> 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.

  Yes.

> 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;

  Yes.

> 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.

  Well, there needs to be a way for packets received on that socket to find the original socket to use.

> Does this sound logical or have I missed something glaringly obvious?

  It seems OK.

> 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.

  You don't need to create the new socket on every packet.  Just create it when the server starts, and leave it open.

> 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.?

 It will involve looking at yiaddr from the received packet, and then using that to find the matching socket.  i.e. "which socket is listening on a network that matches this IP".

  That's a bit more involved.  listener_find_byipaddr() does the basic work, but there may be multiple subnets on the same network.  That will require a bit more work.

  Alan DeKok.



More information about the Freeradius-Users mailing list