-
Notifications
You must be signed in to change notification settings - Fork 238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dhcpv6relay plugin. #551
base: master
Are you sure you want to change the base?
dhcpv6relay plugin. #551
Conversation
This relates to #546 I'm hoping that seeing the binding work here explains why I think this is easier "in-pppd" than outside. Turns out here exists an DHCPv6 "option 135" which allows us to specify the target port for return traffic from the server. I suspect KEA isn't going to like us sending from a port other than 546, not sure about dhcpd -6 (yet). So might need to bind two "client" sockets, one for sending from port 546 and one for receiving (on some other port). Will need to play a bit with that. I will say that multicast is a pain in the backside. @paulusmack if this provides you any insight/ideas, or raises questions, please let me know. This is intended for pppd as a dial-in (server) service. Client side is easily manageable already and there are hordes of tools to deal with that side of the equation. |
@jkroonza: Nice :) |
Conceptually perhaps, but not there yet. |
sys-linux uses select(2) to wait for input, sys-solaris uses poll(2). Would it be highly-objectionable to consolidate that into using the same mechanism for both linux and solaris, and into say pppd/event_handler.c which still presents the add_fd(), remove_fd() and wait_input() calls, but also adds the following additional call:
remove_fd can still be used to remove that specific FD. I think we have a very small set of file descriptors overall, and this PR will add maximum three more, so performance of select() vs poll() is probably irrelevant. select will be easier to code against in this case, from the man page on my system it looks like select() should be portable for this use case, but some level of confirmation would be appreciated as this is a significant change to current operation. The "public" API calls would be add_fd_callback() and remove_fd(), as from what I can tell only core code should use add_fd() and wait_input(). |
I wouldn't object, if that would be helpful. I assume the single implementation would use poll(). |
select() would be easier, but I can use poll() too if there's an objection to select? |
This allows non-core modules to add file descriptors to the event loop and have a call-back called when those file descriptors won't block on read(). Signed-off-by: Jaco Kroon <[email protected]>
49cd94c
to
22be579
Compare
We can relay already towards the server already. This was with:
Other variations should work too. If option 135 ends up not working I have two ideas, the simplest of which is to implement a pure proxy that can action the relevant relay on our behalf that does support option 135. This should not be too difficult, and is definitely easier than implementing some "management agent" like previous suggestions. Next up is to get KEA / ISC DHCPd to respond with a PD so that I can get working on:
Is there a maximum length on either of those options or should I consider further complicating the iovec structure? |
Option 37 + 38 added. Note the string values inside the hex dump of the packet makes a lot more sense than the tcpdump decoded values.
|
Tested working up to this point with kea on server side, bound to ::1, and Mikrotik router as client over incoming L2TP connection (via xl2tpd). DHCP itself works, just need to add routing to resolve this section from the RFC: https://datatracker.ietf.org/doc/html/rfc8415#section-19.1.3 For the moment I'm going to stick with the assumption that in the pppd use-case we're looking for a PD, and not an address assignment, as in my mind at least it doesn't make sense to merely request a single address on a ppp link, since the CPE device router will invariably want a prefix to assign to the LAN, I'm going to focus on that use-case. A single address request may make sense in VPN type scenarios where a host dials in from a remote location. That may well end up being better served using RAs though, but a DHCP configuration might make more sense, eg, to serve such requests from a single /64 I have spotted one case (ISC dhcpcd -6) where the client expects to first see an route-advertisement in response to a route-solicitation. This can be dealt with with a tool such as radvd or even frr. That said, it may be useful to have a ipv6ra module added to pppd as well in addition to this dhcpv6relay, just want to look into radvd - the problem is our use case is of such a nature that even if radvd will work with patterns it may well end up being in-discriminant, but frr should do the trick by disabling ra announce for the interface during net-pre-up, and then selectively enabling in ipv6-up. If that'll work for us, I'm obviously not going to dig too much further into this. As an aside, due to the design of ISC dhcpd, it's unlikely going to work well alongside pppd in this configuration on the same host, and not at all on it's own (due to binding specific broadcast ethernet interfaces only during startup, whilst still having a [::]:547 bound unicast socket). KEA is more configurable, but crashes when you try to bind it to a ppp interface, and having tried to engage with upstream, this doesn't seem likely to get fixed. So my recommendation is KEA bound to a specific address, eg ::1 if you're on a single-host, and then use this module to relay to that. |
I think I'm going to pause here for a day or two just to give time for feedback. I suspect we can treat these two commits as:
|
This includes an implementation on Linux, and a placeholder on Solaris (which will need to be implemented to make dhcpv6relay module effective). Signed-off-by: Jaco Kroon <[email protected]>
After the plugin is loaded, it just needs dhcpv6-server option to know where to relay to. dhcpv6-trusted / dhcpv6-untrusted can be used to mark the port as trusted (will further forward relay-fwd messages) or unstrusted (will only accept and forward client originated messages. dhcpv6-metric - metric at which to install IPv6 routes into the kernel routing table for prefix delegations. Server needs to support fwd option 135 (aka relay-port) in order to respond to pppd. KEA (for one) does. Signed-off-by: Jaco Kroon <[email protected]>
My testing pans out:
Possible change: Turns out I don't need to remember until when a route is valid courtesy of the way ppp_(un)timeout() works. So this field can be removed from the relevant structure, leaving just the prefix and length as the effective fields. We do still need to know what all the routes are, since if IPV6CP gets torn down, we do need to clean up all the routes still. Where to add documentation? How are modules documented? And how do people know which man pages to get to? It seems the only plugin that's documented in the pppd man page is pppoe.so ... surely that's something we should improve? Either have a separate man page for each pppd plugin (eg, pppd-dhcpv6relay), or document all of them in the main man page? Everything else (eg, setting DNS servers, NTP servers, or any other information providable by DHCP for that matter) can be handled on KEA side (or ISC dhcpd if you're that way inclined, KEA seems to be more manageable, especially in a clustered environment due to options for shared SQL back-ends - which itself can be clustered again). This module solves a few problems for us:
|
After the plugin is loaded, it just needs dhcpv6relay-server option to know where to relay to.
Server will (current planning) need to support option 135 which tells it to which port to send return responses (it will still send from port 547 typically).