Anand Buddhdev
2017-Dec-13 22:12 UTC
[nsd-users] Wrong source IP for reply if 'ip-address' is not specified
On 13/12/2017 22:26, Paul Wouters wrote: Hi Paul,> We have a different opinion on what is "normal behaviour". I believe the > normal behaviour is to reply using the IP address you received the > packet from, eg using: > > err = setsockopt(s, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)); > > or > > err = setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt));I don't know if these options are available in non-Linux socket implementations, and is probably the reason that NSD doesn't use them. But I'm sure Wouter can comment more definitively. I know the questions will come, so let me try to anticipate them and answer them. Someone might ask why this isn't necessary with BIND. This is because BIND attempts to detect the capability of the OS it's running on, and compensate for the cases where these advanced options are not present. This may make it easier for an operator, but at the expense of more code complexity. I really do prefer NSD's simpler approach. Note also that in nsd.conf, this cause is very clearly noted. From nsd.conf: ip-address: <ip4 or ip6>[@port] NSD will bind to the listed ip-address. Can be give multiple times to bind multiple ip-addresses. Optionally, a port number can be given. If none are given NSD listens to the wildcard interface. Same as commandline option -a. For servers with multiple IP addresses that can be used to send traffic to the internet, list them one by one, or the source address of replies could be wrong. This is because if the udp socket associates a source address of 0.0.0.0 then the kernel picks an ip-address with which to send to the internet, and it picks the wrong one. Typically needed for anycast instances. Use ip-transparent to be able to list addresses that turn on later (typical for certain load-balancing). Regards, Anand
Paul Wouters
2017-Dec-14 05:56 UTC
[nsd-users] Wrong source IP for reply if 'ip-address' is not specified
On Wed, 13 Dec 2017, Anand Buddhdev wrote:>> We have a different opinion on what is "normal behaviour". I believe the >> normal behaviour is to reply using the IP address you received the >> packet from, eg using: >> >> err = setsockopt(s, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)); >> >> or >> >> err = setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)); > > I don't know if these options are available in non-Linux socket > implementations, and is probably the reason that NSD doesn't use them.Yes they are, but apparently for freebsd you use IP_RECVDSTADDR. https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE If the IP_RECVDSTADDR option is enabled on a SOCK_DGRAM socket, the recvmsg(2) call will return the destination IP address for a UDP data- gram. The msg_control field in the msghdr structure points to a buffer that contains a cmsghdr structure followed by the IP address. The cmsghdr fields have the following values: cmsg_len = sizeof(struct in_addr) cmsg_level = IPPROTO_IP cmsg_type = IP_RECVDSTADDR The source address to be used for outgoing UDP datagrams on a socket that is not bound to a specific IP address can be specified as ancillary data with a type code of IP_SENDSRCADDR. The msg_control field in the msghdr structure should point to a buffer that contains a cmsghdr structure fol- lowed by the IP address. The cmsghdr fields should have the following values: [...] There is really no excuse to answer using the wrong IP :P> I know the questions will come, so let me try to anticipate them and > answer them. Someone might ask why this isn't necessary with BIND. This > is because BIND attempts to detect the capability of the OS it's running > on, and compensate for the cases where these advanced options are not > present. This may make it easier for an operator, but at the expense of > more code complexity. I really do prefer NSD's simpler approach.bind, powerdns, unbound and knot use these mechanisms. Someone should really just fix is for nsd as well. Paul