[Dnsmasq-discuss] relay packets black hole

oss.group at omnilan.de oss.group at omnilan.de
Wed Dec 4 09:10:33 UTC 2024


On 2024-12-03 22:26, Simon Kelley wrote:
> You know when something keeps nagging in the back of your mind......
>
>
> https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commitdiff;h=5a1f2c577db58ea47727f1b6900c0be25e6db205 
>


This is awesome, sir.

If any of the commercial vendors would/could perform close to this...

Thanks a lot!  I spent an hour yesterday and I completely oversaw this 
spot, despite reading it and explicitly looking for missing #ifdef 
HAVE_SOCKADDR_SA_LEN (based more on character recognition than logic 
analysis).
My guess yesterday was that I need to check if I have to care about 
binding to IN_ANY for setting the UDP source address...  but I needed to 
consult sendmsg(2) and even write(2) - nothing more to say about my C 
skills.

Hereby I happily confirm that 5a1f2c577d fixes --dhcp-relay=<local 
address>,<server address> problem with dnsmasq 2.90 on FreeBSD 14.2.
Also --dhcp-proxy seems to work as designed, a very brief check showed 
expected results with the following dnsmasq.conf
no-resolv
no-hosts
domain=ab.cd.example.com
dhcp-range=172.17.147.0,172.17.147.254,255.255.240.0,15m
dhcp-proxy=172.17.146.10
dhcp-authoritative
log-dhcp

Again, kudos and thank you very much!

P.S.: I'd like to make sure this fix makes it into the FreeBSD ports 
asap (ports/dns/dnsmasq, which originates from 
https://cgit.freebsd.org/ports/tree/dns/dnsmasq).  Do you plan to 
release 2.91 in the near future (for christmas gift ;-)?  Then port 
maintainer will most likely update soon anyways.  Otherwise I can file a 
problem report with a ports specific fix.

P.P.S. OT: The reason why I demote dnsmasq(8) acting as a DHCP relay 
agent and proxy is that I'm missing support for either zone transfers 
capability in the DNS part of dnsmasq(8) and/or zone updates capability 
in the DHCP part of dnsmasq(8) (rfc2136, to avoid misleading DDNS term) 
using TSIG (rfc2845).
My currently reworked LAN design implies one authoritative DNS 
instance/cluster per site (which is completely _isolated_ form all LAN 
segments (and the internet)), covering all subdomains in use on that 
specific site (each ethernet segment has a corresponding subdomain, 
which usually corresponds to a delegated zone).  So currently, I have 
chroot(8)ed DNS and DHCP service instances on one host, providing a 
netgraph(4) based SDN to connect to jail(8)s running dnsmasq(8) for DNS 
forwarding and DHCP proxying.  Each jail connects directly to one LAN 
segment only (and no traffic must traverse any router).
The underlying DHCP/DNS daemons are mainly needed to record/register the 
parameters distributed by DHCP leases in my current design.
If I could AXFR 172.in-addr.arpa. (and all other zones involved of 
course), the jails running dnsmasq(8) would be sufficient, because 
dnsmasq(8) does provide the corresponding RRs automatically.  I just 
need the accumulated zones on different DNS server(s) (additionally).  
If someone ever plans to implement zone transfer, please also allow 
moderated and arbitrary adjustable notifies ;-)
But having only one centralized DHCP server per site does have 
advantages too OTOH...  So I'm completely happy at the moment with 
dnsmasq(8) acting as proxy for both, DNS and DHCP.

...
>>>> On the interface with the <local address> (172.17.146.10), I can 
>>>> only see this initial broadcast frame:
>>>> 09:45:08.646733 ee:8c:ea:aa:1b:31 > ff:ff:ff:ff:ff:ff, ethertype 
>>>> IPv4 (0x0800), length 342: 0.0.0.0.68 > 255.255.255.255.67: 
>>>> BOOTP/DHCP, Request from ee:8c:ea:aa:1b:31, length 300
>>>>
>>>> Absolutely no DHCP-related frames are traveling on the <server> 
>>>> (172.17.128.253) interface (ngeth14).
>>>> This doesn't change if I alter the dhcp-relay line to "dhcp- 
>>>> relay=172.17.146.10,ngeth14".
>>>> The log shows
>>>> runninglog dnsmasq-dhcp[13148]: DHCP relay 172.17.146.10 -> 
>>>> 172.17.128.253
>>>> but no frames materialize.
>>>> ...
>>>
>>> poll({ 4/POLLIN 7/POLLIN 8/POLLIN 9/POLLIN 10/POLLIN 11/POLLIN 12/ 
>>> POLLIN },7,-1) = 1 (0x1)
>>> recvmsg(4,{{ AF_INET 0.0.0.0:68 },16,[{"\^A\^A\^F\0z)]\M- 
>>> V\0\0\0\0\0\0\0"...,548}],1, 
>>> {{level=IPPROTO_IP,type=IP_RECVIF,data={0x38,0x12,0x09,0x00,0x06,0x07,0x06,0x00,0x65,0x70,0x61,0x69,0x72,0x32,0x62,0xee,0x8c,0xea,0xaa,0x1b,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}},72,MSG_PEEK},MSG_PEEK|MSG_TRUNC) 
>>> = 300 (0x12c)
>>> recvmsg(4,{{ AF_INET 0.0.0.0:68 },16,[{"\^A\^A\^F\0z)]\M- 
>>> V\0\0\0\0\0\0\0"...,548}],1, 
>>> {{level=IPPROTO_IP,type=IP_RECVIF,data={0x38,0x12,0x09,0x00,0x06,0x07,0x06,0x00,0x65,0x70,0x61,0x69,0x72,0x32
>>> ,0x62,0xee,0x8c,0xea,0xaa,0x1b,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}},72,0},0) 
>>> = 300 (0x12c)
>>> __sysctl("net.routetable.0.0.5.0",6,0x0,0x820cb6ce8,0x0,0) = 0 (0x0)
>>> __sysctl("net.routetable.0.0.5.0",6,0xc2b4a05e000,0x820cb6ce8,0x0,0) 
>>> = 0 (0x0)
>>> ioctl(4,SIOCGIFFLAGS,0x820cb6e90)                = 0 (0x0)
>>> ioctl(4,SIOCGIFADDR,0x820cb6e90)                 = 0 (0x0)
>>> __sysctl("net.routetable.0.0.5.0",6,0x0,0x820cb6b98,0x0,0) = 0 (0x0)
>>> __sysctl("net.routetable.0.0.5.0",6,0xc2b4a05e000,0x820cb6b98,0x0,0) 
>>> = 0 (0x0)
>>> socket(PF_INET,SOCK_DGRAM|SOCK_CLOEXEC,0)        = 15 (0xf)
>>> ioctl(15,SIOCGIFINDEX,0x820cb6ba0)               = 0 (0x0)
>>> close(15)                                        = 0 (0x0)
>>> socket(PF_INET,SOCK_DGRAM|SOCK_CLOEXEC,0)        = 15 (0xf)
>>> ioctl(15,SIOCGIFINDEX,0x820cb6ba0)               = 0 (0x0)
>>> close(15)                                        = 0 (0x0)
>>> socket(PF_INET,SOCK_DGRAM|SOCK_CLOEXEC,0)        = 15 (0xf)
>>> ioctl(15,SIOCGIFINDEX,0x820cb6ba0)               = 0 (0x0)
>>> close(15)                                        = 0 (0x0)
>>> sendmsg(4,{{ AF_INET 172.17.128.253:67 },43,[{"\^A\^A\^F\^Az)]\M- 
>>> V\0\0\0\0\0\0"...,300}],1, 
>>> {{level=IPPROTO_IP,type=IP_RECVDSTADDR,data={0xac,0x11,0x92,0x0a}}},20,0},0) 
>>> ERR#22 'Invalid argument'
>>>
>>>
>>
>> Well, there's your problem :)
>>
>> Actually, I can't see the problem. The incoming packet is received 
>> OK, and it's arrival interface is determined and associated with the 
>> relay configuration. (That's all the SIOCGIFINDEX, ioctls, looking at 
>> the addresses of the local interfaces.
>>
>> Finally, the code tries to send the packet on to 172.17.128.253 port 
>> 67 - tick, with a source address of 172.17.146.10 - tick.
>>
>> Why that provokes EINVAL, I have very little idea.
>>
>> Some pointers to help your debugging.
>>
>> You're looking at relay_upstream4() in src/dhcp.c which calls 
>> send_from() in src/forward.c
>>
>> As far as I can tell the sockopts IP_RECVDSTADDR and IP_SENDSRCADDR 
>> have the same numerical value in the headers, so the dtrace 
>> IP_RECVDSTADDR in a sendmsg() argument is not unexpected. It may be 
>> worth looking at /usr/ include/netinet/in.h on the machine you're 
>> building on and the machine you're running on. Just in case that 
>> changed at some point and broke the ABI.
>>
>>
>> If you set the second argument of the send_from() call in 
>> relay_upstream4() to 1, that will suppress the attempt to set the 
>> source address of the transmitted packet. If the EINVAL error then 
>> goes away, that's a clue.
>>
>> I have a very ancient, very faint, memory that some BSD flavours 
>> support IP_RECVDSTADDR but NOT IP_SENDSRCADDR but I'm pretty sure 
>> FreeBSD is OK in this respect. https://man.freebsd.org/cgi/man.cgi? 
>> query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE
>>
>>
>> The send_from() function is also used to send DNS packets, so a quick 
>> test/dtrace of dnsmasq forwarding DNS to the same place it's supposed 
>> to be relaying DHCP to might be informative.
>>
>> Good luck!
>>
>> I don't have a functional FreeBSD VM at the moment, but I can create 
>> a new one if needs be.
>>
>> Cheers,
>>
>> Simon.
>> ...





More information about the Dnsmasq-discuss mailing list