diff --git a/net/dns/direct.go b/net/dns/direct.go index 3344579ea..5742d2d21 100644 --- a/net/dns/direct.go +++ b/net/dns/direct.go @@ -81,11 +81,12 @@ func readResolv(r io.Reader) (config OSConfig, err error) { // configuration in bs - one of "resolvconf", "systemd-resolved" or // "NetworkManager", or "" if no known owner was found. func resolvOwner(bs []byte) string { + likely := "" b := bytes.NewBuffer(bs) for { line, err := b.ReadString('\n') if err != nil { - return "" + return likely } line = strings.TrimSpace(line) if line == "" { @@ -94,15 +95,15 @@ func resolvOwner(bs []byte) string { if line[0] != '#' { // First non-empty, non-comment line. Assume the owner // isn't hiding further down. - return "" + return likely } if strings.Contains(line, "systemd-resolved") { - return "systemd-resolved" + likely = "systemd-resolved" } else if strings.Contains(line, "NetworkManager") { - return "NetworkManager" + likely = "NetworkManager" } else if strings.Contains(line, "resolvconf") { - return "resolvconf" + likely = "resolvconf" } } } diff --git a/net/dns/manager_linux_test.go b/net/dns/manager_linux_test.go index 564a0ace9..985b0a923 100644 --- a/net/dns/manager_linux_test.go +++ b/net/dns/manager_linux_test.go @@ -142,6 +142,36 @@ func TestLinuxDNSMode(t *testing.T) { wantLog: "dns: [rc=resolved nm=no ret=systemd-resolved]", want: "systemd-resolved", }, + { + // More than one user has had resolvconf write a config that points to + // systemd-resolved. We're better off using systemd-resolved. + // regression test for https://github.com/tailscale/tailscale/issues/3026 + name: "allegedly_resolvconf_but_actually_systemd-resolved", + env: env(resolvDotConf( + "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)", + "# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN", + "# 127.0.0.53 is the systemd-resolved stub resolver.", + "# run \"systemd-resolve --status\" to see details about the actual nameservers.", + "nameserver 127.0.0.53"), + resolvedRunning()), + wantLog: "dns: [rc=resolved nm=no ret=systemd-resolved]", + want: "systemd-resolved", + }, + { + // More than one user has had resolvconf write a config that points to + // systemd-resolved. We're better off using systemd-resolved. + // ...but what if systemd-resolved isn't running? + // regression test for https://github.com/tailscale/tailscale/issues/3026 + name: "allegedly_resolvconf_but_actually_systemd-resolved_but_not_really", + env: env(resolvDotConf( + "# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)", + "# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN", + "# 127.0.0.53 is the systemd-resolved stub resolver.", + "# run \"systemd-resolve --status\" to see details about the actual nameservers.", + "nameserver 127.0.0.53")), + wantLog: "dns: [rc=resolved resolved=no ret=direct]", + want: "direct", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {