diff --git a/src/resolve/resolv.conf b/src/resolve/resolv.conf index b8034d6829..34a6b9257f 100644 --- a/src/resolve/resolv.conf +++ b/src/resolve/resolv.conf @@ -1,11 +1,17 @@ -# This is a static resolv.conf file for connecting local clients to -# systemd-resolved via its DNS stub listener on 127.0.0.53. +# This file belongs to man:systemd-resolved(8). Do not edit. +# +# This is a static resolv.conf file for connecting local clients to the +# internal DNS stub resolver of systemd-resolved. This file lists no search +# domains. +# +# Run "systemd-resolve --status" to see details about the uplink DNS servers +# currently in use. # # Third party programs must not access this file directly, but only through the -# symlink at /etc/resolv.conf. To manage resolv.conf(5) in a different way, +# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way, # replace this symlink by a static file or a different symlink. # -# See systemd-resolved.service(8) for details about the supported modes of +# See man:systemd-resolved.service(8) for details about the supported modes of # operation for /etc/resolv.conf. nameserver 127.0.0.53 diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 0f9c4fa47a..ea4459a89a 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -425,7 +425,6 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { DnsSearchDomain *d; - DnsServer *dns_server; assert(s); assert(domain); @@ -458,24 +457,27 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co if (dns_name_endswith(domain, "invalid") > 0) return DNS_SCOPE_NO; - /* Always honour search domains for routing queries. Note that - * we return DNS_SCOPE_YES here, rather than just - * DNS_SCOPE_MAYBE, which means wildcard scopes won't be - * considered anymore. */ - LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) - if (dns_name_endswith(domain, d->name) > 0) - return DNS_SCOPE_YES; - - /* If the DNS server has route-only domains, don't send other requests - * to it. This would be a privacy violation, will most probably fail - * anyway, and adds unnecessary load. */ - dns_server = dns_scope_get_dns_server(s); - if (dns_server && dns_server_limited_domains(dns_server)) - return DNS_SCOPE_NO; - switch (s->protocol) { - case DNS_PROTOCOL_DNS: + case DNS_PROTOCOL_DNS: { + DnsServer *dns_server; + + /* Never route things to scopes that lack DNS servers */ + dns_server = dns_scope_get_dns_server(s); + if (!dns_server) + return DNS_SCOPE_NO; + + /* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that + * we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes + * won't be considered anymore. */ + LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) + if (dns_name_endswith(domain, d->name) > 0) + return DNS_SCOPE_YES; + + /* If the DNS server has route-only domains, don't send other requests to it. This would be a privacy + * violation, will most probably fail anyway, and adds unnecessary load. */ + if (dns_server_limited_domains(dns_server)) + return DNS_SCOPE_NO; /* Exclude link-local IP ranges */ if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 && @@ -490,6 +492,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co return DNS_SCOPE_MAYBE; return DNS_SCOPE_NO; + } case DNS_PROTOCOL_MDNS: if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index b182f4319e..4ea7490ac9 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -32,11 +32,41 @@ #include "string-util.h" #include "strv.h" +/* A resolv.conf file containing the DNS server and domain data we learnt from uplink, i.e. the full uplink data */ +#define PRIVATE_UPLINK_RESOLV_CONF "/run/systemd/resolve/resolv.conf" + +/* A resolv.conf file containing the domain data we learnt from uplink, but our own DNS server address. */ +#define PRIVATE_STUB_RESOLV_CONF "/run/systemd/resolve/stub-resolv.conf" + +/* A static resolv.conf file containing no domains, but only our own DNS sever address */ +#define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf" + +static bool file_is_our_own(const struct stat *st) { + const char *path; + + assert(st); + + FOREACH_STRING(path, + PRIVATE_UPLINK_RESOLV_CONF, + PRIVATE_STUB_RESOLV_CONF, + PRIVATE_STATIC_RESOLV_CONF) { + + struct stat own; + + /* Is it symlinked to our own uplink file? */ + if (stat(path, &own) >= 0 && + st->st_dev == own.st_dev && + st->st_ino == own.st_ino) + return true; + } + + return false; +} + int manager_read_resolv_conf(Manager *m) { _cleanup_fclose_ FILE *f = NULL; - struct stat st, own; + struct stat st; char line[LINE_MAX]; - usec_t t; int r; assert(m); @@ -57,20 +87,10 @@ int manager_read_resolv_conf(Manager *m) { } /* Have we already seen the file? */ - t = timespec_load(&st.st_mtim); - if (t == m->resolv_conf_mtime) + if (timespec_load(&st.st_mtim) == m->resolv_conf_mtime) return 0; - /* Is it symlinked to our own file? */ - if (stat(PRIVATE_UPLINK_RESOLV_CONF, &own) >= 0 && - st.st_dev == own.st_dev && - st.st_ino == own.st_ino) - return 0; - - /* Is it symlinked to our own stub file? */ - if (stat(PRIVATE_STUB_RESOLV_CONF, &own) >= 0 && - st.st_dev == own.st_dev && - st.st_ino == own.st_ino) + if (file_is_our_own(&st)) return 0; f = fopen("/etc/resolv.conf", "re"); @@ -87,6 +107,9 @@ int manager_read_resolv_conf(Manager *m) { goto clear; } + if (file_is_our_own(&st)) + return 0; + dns_server_mark_all(m->dns_servers); dns_search_domain_mark_all(m->search_domains); @@ -117,7 +140,7 @@ int manager_read_resolv_conf(Manager *m) { } } - m->resolv_conf_mtime = t; + m->resolv_conf_mtime = timespec_load(&st.st_mtim); /* Flush out all servers and search domains that are still * marked. Those are then ones that didn't appear in the new @@ -216,14 +239,18 @@ static void write_resolv_conf_search( static int write_uplink_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { Iterator i; - fputs_unlocked("# This file is managed by man:systemd-resolved(8). Do not edit.\n#\n" + fputs_unlocked("# This file is managed by man:systemd-resolved(8). Do not edit.\n" + "#\n" "# This is a dynamic resolv.conf file for connecting local clients directly to\n" - "# all known DNS servers.\n#\n" + "# all known uplink DNS servers. This file lists all configured search domains.\n" + "#\n" "# Third party programs must not access this file directly, but only through the\n" "# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,\n" - "# replace this symlink by a static file or a different symlink.\n#\n" + "# replace this symlink by a static file or a different symlink.\n" + "#\n" "# See man:systemd-resolved.service(8) for details about the supported modes of\n" - "# operation for /etc/resolv.conf.\n\n", f); + "# operation for /etc/resolv.conf.\n" + "\n", f); if (ordered_set_isempty(dns)) fputs_unlocked("# No DNS servers known.\n", f); @@ -242,10 +269,23 @@ static int write_uplink_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSe } static int write_stub_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { - fputs("# This file is managed by man:systemd-resolved(8). Do not edit.\n#\n" - "# 127.0.0.53 is the systemd-resolved stub resolver.\n" - "# run \"systemd-resolve --status\" to see details about the actual nameservers.\n\n" - "nameserver 127.0.0.53\n", f); + fputs_unlocked("# This file is managed by man:systemd-resolved(8). Do not edit.\n" + "#\n" + "# This is a dynamic resolv.conf file for connecting local clients to the\n" + "# internal DNS stub resolver of systemd-resolved. This file lists all\n" + "# configured search domains.\n" + "#\n" + "# Run \"systemd-resolve --status\" to see details about the uplink DNS servers\n" + "# currently in use.\n" + "#\n" + "# Third party programs must not access this file directly, but only through the\n" + "# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,\n" + "# replace this symlink by a static file or a different symlink.\n" + "#\n" + "# See man:systemd-resolved.service(8) for details about the supported modes of\n" + "# operation for /etc/resolv.conf.\n" + "\n" + "nameserver 127.0.0.53\n", f); if (!ordered_set_isempty(domains)) write_resolv_conf_search(domains, f); diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h index 99b3ca88fb..ef34f8e09e 100644 --- a/src/resolve/resolved-resolv-conf.h +++ b/src/resolve/resolved-resolv-conf.h @@ -22,8 +22,5 @@ #include "resolved-manager.h" -#define PRIVATE_UPLINK_RESOLV_CONF "/run/systemd/resolve/resolv.conf" -#define PRIVATE_STUB_RESOLV_CONF "/run/systemd/resolve/stub-resolv.conf" - int manager_read_resolv_conf(Manager *m); int manager_write_resolv_conf(Manager *m);