Skip to content
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

UDP queries are responded to from a different IP than the client used #1026

Open
farnoy opened this issue Mar 9, 2024 · 1 comment
Open
Assignees

Comments

@farnoy
Copy link

farnoy commented Mar 9, 2024

Describe the bug
When using interface: 0.0.0.0, replies to queries from clients sometimes originate from a different address than the client used to connect. This breaks the response flow and the client experiences a timeout, not getting the reply back from its perspective.

To reproduce
Steps to reproduce the behavior:

  1. interface: 0.0.0.0
  2. # ip addr add 10.0.0.1/32 dev lo
  3. On a client (Windows in this example): nslookup amazon.com 10.0.0.1

Doesn't happen with nslookup set vc and then executing the query (to run in TCP mode)

Expected behavior
A clear and concise description of what you expected to happen.

System:

  • Unbound version: 1.19.1
  • OS: NixOS 6.7.7
  • unbound -V output:
   Version 1.19.1

Configure line: --disable-static --prefix=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1 --bindir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/bin --sbindir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/sbin --includedir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/include --oldincludedir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/include --mandir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1-man/share/man --infodir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/share/info --docdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1/share/doc/unbound --libdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1-lib/lib --libexecdir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1-lib/libexec --localedir=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-unbound-1.19.1-lib/share/locale --with-ssl=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-openssl-3.0.13-dev --with-libexpat=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-expat-2.5.0-dev --with-libevent=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-libevent-2.1.12-dev --localstatedir=/var --sysconfdir=/etc --sbindir=${out}/bin --with-rootkey-file=/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-dns-root-data-2023-11-27/root.key --enable-pie --enable-relro-now --enable-systemd
Linked libs: libevent 2.1.12-stable (it uses epoll), OpenSSL 3.0.13 30 Jan 2024
Linked modules: dns64 respip validator iterator

Additional information
tcpdump fragment:

01:41:52.522801 IP (tos 0x0, ttl 128, id 35896, offset 0, flags [none], proto UDP (17), length 56)
    192.168.101.2.58571 > 10.0.0.1.53: 2+ A? amazon.com. (28)
01:41:52.555773 IP (tos 0x0, ttl 64, id 48231, offset 0, flags [none], proto UDP (17), length 104)
    192.168.101.1.53 > 192.168.101.2.58571: 2 3/0/0 amazon.com. A 54.239.28.85, amazon.com. A 205.251.242.103, amazon.com. A 52.94.236.248 (76)

unbound/util/netevent.c

Lines 650 to 656 in 7b62767

#elif defined(IP_SENDSRCADDR)
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_SENDSRCADDR;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
sizeof(struct in_addr));

Seems like the reply src address is already being set.

The workaround was to set interfaces: 10.0.0.1 and others explicitly. When there are multiple sockets bound, one for each interface address, it works just fine.

@gthess gthess self-assigned this Mar 11, 2024
@gthess
Copy link
Member

gthess commented Mar 11, 2024

I believe interface-automatic: yes would help in your case. Can you give it a go?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants