systemd resolves own hostname to link local ipv6 address
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
systemd (Ubuntu) |
Expired
|
Undecided
|
Unassigned |
Bug Description
I've got an ethernet-device that only has a configured ipv4 address, and some auto-generated link-local (aka "scope link") ipv6 address.
Any tool doing a DNS query (and /lib/systemd/
Unlike on ipv4, it is possible for the same ipv6-address to be assigned to multiple devices, and therefore the address is only valid in the context of the eth-device.
Now, if "ifconfig" shows "inet6 fe80::4687:
then "fe80::
To make it a valid address, it needs to be suffixed with a "%" and the device name, like:
fe80::4687:
Either the resolver can return the link name attached to the address separated with a "%" char, or it needs to ignore link-local inet6 addresses.
Andreas L (avl42) wrote : | #1 |
Andreas L (avl42) wrote : | #2 |
Most of the times, the first hit (namely the ipv4 address) is all that is used from the DNS query.
In my case, it is essentially a testcase for Tcl's socket, which tries to establish a connection to an unlistened port, and expects a "connection refused" error. But Tcl in this case(namely that the connection gets refused) attempts the connect on the next address-result, which is then the bad ipv6-address. That one then caused an "EINVAL" from the connect() syscall, which it reported up, so the testcase expecting "connection refused" failed.
I'm aware that the impact is not very big, but that just explains, why it wasn't already noticed long before.
Conclusion is, that DNS should either not return an inet6 link-local address at all, as this cannot be used that way (namely without the name of the network-device), or it should only provide it together with the network-device, if that is possible in the DNS protocol.
Dan Streetman (ddstreet) wrote : | #3 |
I can't reproduce this, can you provide specific cmdline steps to reproduce please.
Changed in systemd (Ubuntu): | |
status: | New → Incomplete |
Andreas L (avl42) wrote : | #4 |
The premis is that you have a network device with a "link local" (aka: "scopeid 0x20<link>") inet6 address.
In my case, "ifconfig enp4s0" shows a line like this:
inet6 fe80::4687:
If your machine does NOT have such a line, then I must admit, I don't know how to produce one. Mine had it from default setup.
If your machine DOES have an inet6 link local address, then (in a shell) run "host $(hostname)" and it is likely to return an inet (ipv4) address (that's just fine) AND the link local inet6 address.
If your "host $(hostname)" doesn't give you any inet6 address, or gives you one with %network-name appended, then you might have a different version of "systemd" than 237-3ubuntu10.33 (as included in 18.04)
Andreas L (avl42) wrote : | #5 |
If you see the bare inet6 link local address, but just can't see a problem with it,
then try:
$ telnet $(hostname) # some port that isn't listened on.
Trying 192.168.0.1...
Trying fe80::4687:
telnet: Unable to connect to remote host: Invalid argument
The symptom being here that you get "Invalid argument" instead of "Connection refused".
Dan Streetman (ddstreet) wrote : | #6 |
> In my case, "ifconfig enp4s0" shows a line like this:
> inet6 fe80::4687:
this is normal, when ipv6 is enabled; all interfaces get a link-local address.
> run "host $(hostname)" and it is likely to return...the link local inet6 address.
Your assumption that systemd-resolved will perform $(hostname) resolution to the system's ipv6 link local addresses is wrong; it doesn't do that, unless you've configured things that way. If your system does do that, something else is going on. Can you provide a *specific* example of what you are seeing on your system, instead of trying to generalize your problem.
Andreas L (avl42) wrote : | #7 |
It was no "assumption", but an "observation".
$ nslookup $(hostname) # a blank name without any domain
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: xxx # my "$(hostname)"
Address: 192.168.0.1
Name: xxx
Address: fe80::4687:
$ sudo fuser -n udp 53
53/udp: 22620
$ ps uww 22620
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
systemd+ 22620 0.0 0.0 52368 2220 ? Ss Nov29 1:50 /lib/systemd/
$ dpkg -S /lib/systemd/
systemd: /lib/systemd/
$ dpkg -l systemd | cat # (no UUOC, but prevent dpkg from fitting output to terminal)
Desired=
| Status=
|/ Err?=(none)
||/ Name Version Architecture Description
+++-===
ii systemd 237-3ubuntu10.33 amd64 system and service manager
$
At which points does your output differ?
Andreas L (avl42) wrote : | #8 |
If your (same-version?) systemd does not return the link local address to nslookup, then I'd appreciate a hint for what kind of config would make it do so, so I could check the particular files.
I just recently upgraded my machine from 16.04 (with dnsmasq) to 18.04 -- if I had changed any systemd-config I'd pretty surely remember. If systemd uses some of dnsmasq's config, there is a chance of customizations so long ago, that I might have forgotten about them.
Andreas L (avl42) wrote : | #9 |
PS: re "assumption"
Dan Streetman (ddstreet) wrote : | #10 |
> It was no "assumption", but an "observation".
no, you are assuming that systemd-resolved is the authoritative nameserver providing the $(hostname) addresses, which is wrong. systemd-resolved is a stub nameserver that does no authoritative resolution itself; it gets its answers from other nameservers.
> Name: xxx # my "$(hostname)"
why are you obfuscating your hostname? It could be relevant, for example if you're choosing to use the 'local' domain.
Let's try this instead; do this:
$ sudo systemctl --runtime edit systemd-resolved
in the editor that opens, put this:
[Service]
Environment=
then, save it and exit the editor. Then do:
$ sudo systemctl restart systemd-resolved
and now lookup your name:
$ nslookup $(hostname)
and then do this and paste/attach the results:
$ journalctl -b -u systemd-resolved --no-pager
Andreas L (avl42) wrote : | #11 |
Well, ok, here is the real data: my hostname is "fpc" and really has IPv4 10.2.2.1, the next upstream nameserver is another machine in my home network, 10.2.2.3 which is configured to also use its /etc/hosts (so I only need to maintain it on one machine). Doing the nslookup directly on 10.2.2.3 ONLY gives the ipv4 address (as I had already checked before opening this ticket, and which also made me very positive that the local resolver was to blame).
Unfortunately, the log doesn't really show much about where it gets what data from...
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
Dez 06 09:02:14 fpc systemd-
At that minute&second I did a "host fpc". The log entries before and after had sufficiently separate timings. (I repeated it a few times, until other requests from other applications didn't mix in.)
This is what I get from asking "upstream" DNS directly:
$ nslookup fpc 10.2.2.3
Server: 10.2.2.3
Address: 10.2.2.3#53
Name: fpc
Address: 10.2.2.1
$
That machine 10.2.2.3 is still running Ubuntu 16.04 and dnsmasq.
Andreas L (avl42) wrote : | #12 |
It occurred to me, that the actual query might be cached at that time, so I did a fresh restart of systemd-resolved and query, and then follows the log for these times: I don't see much relevant details in it, except that it also tries to find MX-records but fails till <attempts-
avl@fpc:~$ date; sudo systemctl restart systemd-resolved
Fr Dez 6 09:27:34 CET 2019
avl@fpc:~$ date; host fpc
Fr Dez 6 09:27:39 CET 2019
fpc has address 10.2.2.1
fpc has address 10.2.2.250
fpc has IPv6 address fe80::4687:
avl@fpc:~$
Note: the 10.2.2.250 is a remainder from a recent experiment, adding a second IP address to the same network device. It is not in 10.2.2.3's /etc/hosts . The problem of bad inet6 returned predates my addition of the second ip-address.
Here the log:
Dez 06 09:27:34 fpc systemd[1]: Stopping Network Name Resolution...
Dez 06 09:27:34 fpc systemd-
Dez 06 09:27:34 fpc systemd[1]: Stopped Network Name Resolution.
Dez 06 09:27:34 fpc systemd[1]: Starting Network Name Resolution...
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-
Dez 06 09:27:35 fpc systemd-resolved...
Andreas L (avl42) wrote : | #13 |
Here is some more info, namely an "strace" of the systemd-resolved program.
(An "lsof"-excerpt with the open channels follows the trace-log, to make sense of filedescriptors)
In a nutshell: at some point, it receives the inet6 address "fe80::
"systemd-r 4966 systemd-resolve 9u netlink 0t0 15693998 ROUTE"
I don't understand what lsof tries to tell me here, but naively I'd assume that systemd-resolved also queries the routing table, and for that I also attach the output of "route -n -6" at the end of this message.
strace: Process 4966 attached
epoll_wait(4, [{EPOLLIN, {u32=3769468528, u64=94647668803
clock_gettime(
recvfrom(12, NULL, 0, MSG_PEEK|MSG_TRUNC, NULL, NULL) = 21
recvmsg(12, {msg_name=
stat("/etc/hosts", {st_mode=
stat("/
clock_gettime(
sendto(9, {{len=24, type=RTM_GETADDR, flags=NLM_
recvmsg(9, {msg_name=
recvmsg(9, {msg_name=
Dan Streetman (ddstreet) wrote : | #14 |
> I don't understand what lsof tries to tell me here, but naively I'd assume that systemd-resolved also queries the routing table, and for that I also attach the output of "route -n -6" at the end of this message.
that's not correct.
What's the contents of your /etc/hosts file? Contents of /etc/resolv.conf?
What do these show:
$ systemd-resolve --status
$ systemd-resolve fpc
$ systemd-resolve -t A fpc
$ systemd-resolve -t AAAA fpc
$ dig @10.2.2.3 -t A fpc
$ dig @10.2.2.3 -t AAAA fpc
$ dig @127.0.0.53 -t A fpc
$ dig @127.0.0.53 -t AAAA fpc
Andreas L (avl42) wrote : | #15 |
/etc/hosts:
127.0.0.1 localhost
127.0.1.1 kato i7
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
$ systemd-resolve --status
Global
DNS Servers: 10.2.2.3
DNSSEC NTA: 10.in-addr.arpa
Link 2 (enp4s0)
Current Scopes: none
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
Remark: I have no idea where these ##.172.in-addr.arpa come from.
$ systemd-resolve fpc
fpc: 10.2.2.1%enp4s0
10.
fe80:
-- Information acquired via protocol DNS in 1.6ms.
-- Data is authenticated: yes
Remark: ah, here it still has the network-name along with the ipv6
$ systemd-resolve -t A fpc
fpc IN A 10.2.2.1 # interface enp4s0
fpc IN A 10.2.2.250 # interface enp4s0
-- Information acquired via protocol DNS in 2.2ms.
-- Data is authenticated: yes
$ systemd-resolve -t AAAA fpc
fpc IN AAAA fe80::4687:
-- Information acquired via protocol DNS in 2.1ms.
-- Data is authenticated: yes
Remark: ah, here it also has the network-name along with the ipv6
$ dig @10.2.2.3 -t A fpc
; <<>> DiG 9.11.3-
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57577
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1280
;; QUESTION SECTION:
;fpc. IN A
;; ANSWER SECTION:
fpc. 0 IN A 10.2.2.1
;; Query time: 0 msec
;; SERVER: 10.2.2.
;; WHEN: Fri Dec 06 17:11:19 CET 2019
;; MSG SIZE rcvd: 48
Remark: As I said, upstream DNS 10.2.2.3 doesn't know about the second 10.2.2.250 address.
$ dig @10.2.2.3 -t AAAA fpc
; <<>> DiG 9.11.3-
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 924
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;fpc. IN AAAA
;; Query time: 0 msec
;; SERVER: 10.2.2.
Dan Streetman (ddstreet) wrote : | #16 |
You missed contents of /etc/resolv.conf
Also paste contents of /etc/systemd/
Andreas L (avl42) wrote : | #17 |
Apologies...
I'll leave out the comment-headers and just paste the relevant contents:
/etc/resolv.conf:
nameserver 127.0.0.53
nameserver 10.2.2.3
/etc/systemd/
[Resolve]
#DNS=
#FallbackDNS=
#Domains=
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#Cache=yes
#DNSStubListene
Dan Streetman (ddstreet) wrote : | #18 |
> /etc/resolv.conf:
> nameserver 127.0.0.53
> nameserver 10.2.2.3
You shouldn't hand-edit your resolv.conf file; don't put the upstream nameserver in there.
Anyway, assuming you haven't edited out the search domain because you thought it wasn't relevant, you're using single-label hostnames, which shouldn't be used. resolved refuses to perform upstream lookups for single-label domains, and you don't have your hostname defined in your /etc/hosts file, so resolved has nobody to ask to lookup your hostname.
You should set up your network using a dns domain.
For reference:
https:/
Changed in systemd (Ubuntu): | |
status: | Incomplete → Invalid |
Andreas L (avl42) wrote : | #19 |
Ok, just to check, I changed /etc/resolv.conf to remove second
nameserver, added "domain .hm" and "search hm", added "fpc.hm"
to the respective entry in 10.2.2.3's /etc/hosts.
Result is, that localhost's systemd-resolved now no longer
knows about upstream dns 10.2.2.3 -- where else am I supposed
to configure that?
So, I re-added "nameserver 10.2.2.3" to /etc/resolv.conf, and
it really seems like it would once again take the second
nameserver-entry as that for upstream-dns.
Apparently, with "domain" and "search" in place, systemd-resolved
no longer makes any attempt to obtain information from routing
table, thus appears to work.
Nevertheless, apparently systemd-resolved DOES have a feature
where it queries local information about network devices to
get a list of ip-addresses whenever there is no domain/search
defined and a bare name queried. What is the reason behind
that feature, if the suggested solution to this ticket is just:
"don't use bare hostnames"?
Changed in systemd (Ubuntu): | |
status: | Invalid → Confirmed |
Andreas L (avl42) wrote : | #20 |
I do agree that it is correct(TM) behaviour to not ask upstream DNS for bare ("single label") names. But this is not what this bugreport was about.
The point is what systemd-resolved does in such a case, where it cannot consult upstream DNS, and also doesn't find the name in local /etc/hosts:
It consults the routing table, and, when doing so, it deals wrongly with link-local inet6 addresses. That's what this bugreport was about.
Dan Streetman (ddstreet) wrote : | #21 |
> Result is, that localhost's systemd-resolved now no longer
> knows about upstream dns 10.2.2.3 -- where else am I supposed
> to configure that?
If you use systemd-networkd to configure your network (or, netplan, which will indirectly configure networkd or network-manager for you), then systemd-resolved will be updated to know what your actual upstream nameserver(s) are; you can query what current upstream nameservers resolved is using with the 'systemd-resolve --status' command.
If you use ifupdown, there is a dhclient hook that tells resolved (or resolvconf) about your upstream nameservers.
If you manually configure your network, it's up to you to also manually configure your /etc/resolv.conf file, or manually tell resolved about your upstream nameservers, which you can do with the systemd-resolved command (see its man page).
> It consults the routing table, and, when doing so, it deals wrongly with link-local
> inet6 addresses. That's what this bugreport was about.
Why is it wrong? All the ipv6 addresses it resolves for its own hostname are reachable locally.
Changed in systemd (Ubuntu): | |
status: | Confirmed → Incomplete |
Andreas L (avl42) wrote : | #22 |
> If you manually configure your network, ...
Ok, so adding it to /etc/resolv.conf is actually one of the supported ways.
Thanks (for info). I'll stick to that.
> Why is it wrong?
try connecting to that address:
avl@fpc:~$ telnet fe80::4687:
Trying fe80::4687:
telnet: Unable to connect to remote host: Invalid argument
The link local inet6 address alone is useless information,...
avl@fpc:~$ telnet fe80::4687:
Trying fe80::4687:
Connected to fe80::4687:
Escape character is '^]'.
SSH-2.0-
... unless the network device name (enp4s0 on my machine) is
attached to the inet6 address.
Andreas L (avl42) wrote : | #23 |
PS: I also appreciate all the other mechanisms for having upstream dns set up from dhcp or other dynamic connections. Just that one machine is set up statically.
Andreas L (avl42) wrote : | #24 |
Is the factual incorrectness of "All the ipv6 addresses it resolves for its own hostname are reachable locally" understood? They are *only* reachable, if the interface is provided along with the link local inet6-address, but that extra condition isn't met.
Dan Streetman (ddstreet) wrote : | #25 |
> Ok, so adding it to /etc/resolv.conf is actually one of the supported ways.
well, I wouldn't call it 'supported' as you're then responsible for managing the resolv.conf file, but it will bypass resolved completely (assuming you don't put 127.0.0.53 in the file, and you only use your upstream nameserver(s)).
The normal glibc getaddrinfo() that uses the resolv.conf entries to find nameserver(s) to query is of course supported no matter what you have in the resolv.conf file, but that rarely has bugs.
> try connecting to that address:
>
> avl@fpc:~$ telnet fe80::4687:
> Trying fe80::4687:
> telnet: Unable to connect to remote host: Invalid argument
you want to telnet to your local host?
anyway, Ubuntu isn't the right place to take this up - you should open an upstream bug to systemd if this is an issue for you.
Andreas L (avl42) wrote : | #26 |
> but it will bypass resolved completely
In my resolv.conf I have now both 127.0.0.53 and the upstream dns each in their own "nameserver"-line. Just as in comment #17, but in the meantime I added domain and search lines.
> you want to telnet to your local host?
I really wanted to demonstrate what happens if I attempt to connect to a bare link local inet6 address as returned by systemd-resolved in the situation where it falls back to resolving $(hostname) using info from local network devices. "telnet" is just a simple tool to connect to tcp/ip endpoints, in case you didn't know, a bit like netcat, but more generally available ;-)
> anyway, Ubuntu isn't the right place to take this up
Good to know so early in the thread...
Dan Streetman (ddstreet) wrote : | #27 |
> In my resolv.conf I have now both 127.0.0.53 and the upstream dns each in their own "nameserver"-line.
if you haven't told resolved about any upstream nameservers, there is no point in pointing resolv.conf to it.
> "telnet" is just a simple tool to connect to tcp/ip endpoints, in case you didn't know, a bit like netcat, but more generally available ;-)
lol, yes we're all aware of what telnet is :)
> Good to know so early in the thread...
If you do open an upstream bug, I'll be happy to follow it and backport any fix if appropriate, but I really do suggest you just fix your network to use a domain name.
Andreas L (avl42) wrote : | #28 |
> you haven't told resolved about any upstream nameservers ...
As I said, my original resolv.conf just had two nameserver entries, the local one (127.0.0.53) and the upstream one.
From that, all the diagnose-calls we did during this thread seemed to show that systemd-resolved DID know the upstream DNS. It really looks like as if systemd-resolved looked for the configured nameservers, recognized itself and took the other one as upstream. See for example comment #15: "DNS Servers: 10.2.2.3" in "Global" section.
Will look for where to create ticket for upstream systemd tomorrow. or when I next have time for it...
Dan Streetman (ddstreet) wrote : | #29 |
> It really looks like as if systemd-resolved looked for the configured nameservers, recognized itself and took the other one as upstream.
it may, it depends entirely on your network configuration, which I don't know.
> Will look for where to create ticket for upstream systemd tomorrow. or when I next have time for it...
https:/
if you do open a bug, please note it here; it's quite possible upstream will agree and fix it.
I'll switch this back to 'confirmed' while waiting to hear an opinion from upstream.
Changed in systemd (Ubuntu): | |
status: | Incomplete → Confirmed |
tags: | added: ddstreet |
Changed in systemd (Ubuntu): | |
status: | Confirmed → Incomplete |
Launchpad Janitor (janitor) wrote : | #30 |
[Expired for systemd (Ubuntu) because there has been no activity for 60 days.]
Changed in systemd (Ubuntu): | |
status: | Incomplete → Expired |
Afternotes: I only noticed the bug shortly after upgrading from Ubuntu 16.04 to Ubuntu 18.04
Seems like 16.04 didn't yet use systemd-resolved, but dnsmasq, which only returned ipv4 addresses.