mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-25 23:21:33 +03:00
Merge pull request #25530 from poettering/resolved-stub-name
resolved: make _localdnsstub and _localdnsproxy resolve to 127.0.0.{53,54}
This commit is contained in:
commit
5bd346feb7
@ -323,11 +323,12 @@
|
||||
|
||||
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||
(the default), select domains are resolved on the local system, among them
|
||||
<literal>localhost</literal>, <literal>_gateway</literal> and <literal>_outbound</literal>, or
|
||||
entries from <filename>/etc/hosts</filename>. If false these domains are not resolved locally, and
|
||||
either fail (in case of <literal>localhost</literal>, <literal>_gateway</literal> or
|
||||
<literal>_outbound</literal> and suchlike) or go to the network via regular DNS/mDNS/LLMNR lookups
|
||||
(in case of <filename>/etc/hosts</filename> entries).</para></listitem>
|
||||
<literal>localhost</literal>, <literal>_gateway</literal>, <literal>_outbound</literal>,
|
||||
<literal>_localdnsstub</literal> and <literal>_localdnsproxy</literal> or entries from
|
||||
<filename>/etc/hosts</filename>. If false these domains are not resolved locally, and either fail (in
|
||||
case of <literal>localhost</literal>, <literal>_gateway</literal> or <literal>_outbound</literal> and
|
||||
suchlike) or go to the network via regular DNS/mDNS/LLMNR lookups (in case of
|
||||
<filename>/etc/hosts</filename> entries).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -118,6 +118,12 @@
|
||||
local default gateway configured. This assigns a stable hostname to the local outbound IP addresses,
|
||||
useful for referencing them independently of the current network configuration state.</para></listitem>
|
||||
|
||||
<listitem><para>The hostname <literal>_localdnsstub</literal> is resolved to the IP address 127.0.0.53,
|
||||
i.e. the address the local DNS stub (see above) is listening on.</para></listitem>
|
||||
|
||||
<listitem><para>The hostname <literal>_localdnsproxy</literal> is resolved to the IP address 127.0.0.54,
|
||||
i.e. the address the local DNS proxy (see above) is listening on.</para></listitem>
|
||||
|
||||
<listitem><para>The mappings defined in <filename>/etc/hosts</filename> are resolved to their
|
||||
configured addresses and back, but they will not affect lookups for non-address types (like MX).
|
||||
Support for <filename>/etc/hosts</filename> may be disabled with <varname>ReadEtcHosts=no</varname>,
|
||||
|
@ -60,4 +60,12 @@ static inline bool is_outbound_hostname(const char *hostname) {
|
||||
return STRCASE_IN_SET(hostname, "_outbound", "_outbound.");
|
||||
}
|
||||
|
||||
static inline bool is_dns_stub_hostname(const char *hostname) {
|
||||
return STRCASE_IN_SET(hostname, "_localdnsstub", "_localdnsstub.");
|
||||
}
|
||||
|
||||
static inline bool is_dns_proxy_stub_hostname(const char *hostname) {
|
||||
return STRCASE_IN_SET(hostname, "_localdnsproxy", "_localdnsproxy.");
|
||||
}
|
||||
|
||||
int get_pretty_hostname(char **ret);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "local-addresses.h"
|
||||
#include "macro.h"
|
||||
#include "nss-util.h"
|
||||
#include "resolve-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
@ -21,7 +22,7 @@
|
||||
* IPv6 we use ::1 which unfortunately will not translate back to the
|
||||
* hostname but instead something like "localhost" or so. */
|
||||
|
||||
#define LOCALADDRESS_IPV4 (htobe32(0x7F000002))
|
||||
#define LOCALADDRESS_IPV4 (htobe32(INADDR_LOCALADDRESS))
|
||||
#define LOCALADDRESS_IPV6 &in6addr_loopback
|
||||
|
||||
NSS_GETHOSTBYNAME_PROTOTYPES(myhostname);
|
||||
|
@ -480,7 +480,11 @@ static bool single_label_nonsynthetic(const char *name) {
|
||||
if (!dns_name_is_single_label(name))
|
||||
return false;
|
||||
|
||||
if (is_localhost(name) || is_gateway_hostname(name))
|
||||
if (is_localhost(name) ||
|
||||
is_gateway_hostname(name) ||
|
||||
is_outbound_hostname(name) ||
|
||||
is_dns_stub_hostname(name) ||
|
||||
is_dns_proxy_stub_hostname(name))
|
||||
return false;
|
||||
|
||||
r = resolve_system_hostname(NULL, &first_label);
|
||||
|
@ -635,8 +635,11 @@ DnsScopeMatch dns_scope_good_domain(
|
||||
if (dns_name_dont_resolve(domain))
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
/* Never go to network for the _gateway or _outbound domain — they're something special, synthesized locally. */
|
||||
if (is_gateway_hostname(domain) || is_outbound_hostname(domain))
|
||||
/* Never go to network for the _gateway, _outbound, _localdnsstub, _localdnsproxy domain — they're something special, synthesized locally. */
|
||||
if (is_gateway_hostname(domain) ||
|
||||
is_outbound_hostname(domain) ||
|
||||
is_dns_stub_hostname(domain) ||
|
||||
is_dns_proxy_stub_hostname(domain))
|
||||
return DNS_SCOPE_NO;
|
||||
|
||||
switch (s->protocol) {
|
||||
@ -764,8 +767,6 @@ DnsScopeMatch dns_scope_good_domain(
|
||||
return DNS_SCOPE_MAYBE;
|
||||
|
||||
if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
|
||||
!is_gateway_hostname(domain) && /* don't resolve "_gateway" with LLMNR, let local synthesizing logic handle that */
|
||||
!is_outbound_hostname(domain) && /* similar for "_outbound" */
|
||||
dns_name_equal(domain, "local") == 0 && /* don't resolve "local" with LLMNR, it's the top-level domain of mDNS after all, see above */
|
||||
manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
|
||||
return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative
|
||||
|
@ -7,20 +7,6 @@
|
||||
#include "missing_network.h"
|
||||
#include "resolved-dns-synthesize.h"
|
||||
|
||||
int dns_synthesize_ifindex(int ifindex) {
|
||||
|
||||
/* When the caller asked for resolving on a specific
|
||||
* interface, we synthesize the answer for that
|
||||
* interface. However, if nothing specific was claimed and we
|
||||
* only return localhost RRs, we synthesize the answer for
|
||||
* localhost. */
|
||||
|
||||
if (ifindex > 0)
|
||||
return ifindex;
|
||||
|
||||
return LOOPBACK_IFINDEX;
|
||||
}
|
||||
|
||||
int dns_synthesize_family(uint64_t flags) {
|
||||
|
||||
/* Picks an address family depending on set flags. This is
|
||||
@ -57,7 +43,7 @@ DnsProtocol dns_synthesize_protocol(uint64_t flags) {
|
||||
return DNS_PROTOCOL_DNS;
|
||||
}
|
||||
|
||||
static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
|
||||
static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, DnsAnswer **answer) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -77,7 +63,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
|
||||
|
||||
rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
|
||||
|
||||
r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
r = dns_answer_add(*answer, rr, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -91,7 +77,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
|
||||
|
||||
rr->aaaa.in6_addr = in6addr_loopback;
|
||||
|
||||
r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
r = dns_answer_add(*answer, rr, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -113,7 +99,7 @@ static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to,
|
||||
return dns_answer_add(*answer, rr, ifindex, flags, NULL);
|
||||
}
|
||||
|
||||
static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
|
||||
static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, DnsAnswer **answer) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -125,7 +111,7 @@ static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int i
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, dns_resource_key_name(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
|
||||
r = answer_add_ptr(answer, dns_resource_key_name(key), "localhost", LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -225,20 +211,19 @@ static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key,
|
||||
if (n == 0) {
|
||||
struct local_address buffer[2];
|
||||
|
||||
/* If we have no local addresses then use ::1
|
||||
* and 127.0.0.2 as local ones. */
|
||||
/* If we have no local addresses then use ::1 and 127.0.0.2 as local ones. */
|
||||
|
||||
if (IN_SET(af, AF_INET, AF_UNSPEC))
|
||||
buffer[n++] = (struct local_address) {
|
||||
.family = AF_INET,
|
||||
.ifindex = dns_synthesize_ifindex(ifindex),
|
||||
.address.in.s_addr = htobe32(0x7F000002),
|
||||
.ifindex = LOOPBACK_IFINDEX,
|
||||
.address.in.s_addr = htobe32(INADDR_LOCALADDRESS),
|
||||
};
|
||||
|
||||
if (IN_SET(af, AF_INET6, AF_UNSPEC) && socket_ipv6_is_enabled())
|
||||
buffer[n++] = (struct local_address) {
|
||||
.family = AF_INET6,
|
||||
.ifindex = dns_synthesize_ifindex(ifindex),
|
||||
.ifindex = LOOPBACK_IFINDEX,
|
||||
.address.in6 = in6addr_loopback,
|
||||
};
|
||||
|
||||
@ -260,7 +245,7 @@ static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_add
|
||||
assert(address);
|
||||
assert(answer);
|
||||
|
||||
if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
|
||||
if (af == AF_INET && address->in.s_addr == htobe32(INADDR_LOCALADDRESS)) {
|
||||
|
||||
/* Always map the IPv4 address 127.0.0.2 to the local hostname, in addition to "localhost": */
|
||||
|
||||
@ -268,19 +253,19 @@ static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_add
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->full_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->full_hostname, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
|
||||
r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -356,7 +341,90 @@ static int synthesize_gateway_rr(
|
||||
return 1; /* > 0 means: we have some gateway */
|
||||
}
|
||||
|
||||
static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
|
||||
static int synthesize_dns_stub_rr(
|
||||
Manager *m,
|
||||
const DnsResourceKey *key,
|
||||
in_addr_t addr,
|
||||
DnsAnswer **answer) {
|
||||
|
||||
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(key);
|
||||
assert(answer);
|
||||
|
||||
if (!IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY))
|
||||
return 1; /* we still consider ourselves the owner of this name */
|
||||
|
||||
r = dns_answer_reserve(answer, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, dns_resource_key_name(key));
|
||||
if (!rr)
|
||||
return -ENOMEM;
|
||||
|
||||
rr->a.in_addr.s_addr = htobe32(addr);
|
||||
|
||||
r = dns_answer_add(*answer, rr, LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int synthesize_dns_stub_ptr(
|
||||
Manager *m,
|
||||
int af,
|
||||
const union in_addr_union *address,
|
||||
DnsAnswer **answer) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(address);
|
||||
assert(answer);
|
||||
|
||||
if (af != AF_INET)
|
||||
return 0;
|
||||
|
||||
if (address->in.s_addr == htobe32(INADDR_DNS_STUB)) {
|
||||
|
||||
r = dns_answer_reserve(answer, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "53.0.0.127.in-addr.arpa", "_localdnsstub", LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (address->in.s_addr == htobe32(INADDR_DNS_PROXY_STUB)) {
|
||||
|
||||
r = dns_answer_reserve(answer, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = answer_add_ptr(answer, "54.0.0.127.in-addr.arpa", "_localdnsproxy", LOOPBACK_IFINDEX, DNS_ANSWER_AUTHENTICATED);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int synthesize_gateway_ptr(
|
||||
Manager *m,
|
||||
int af,
|
||||
const union in_addr_union *address,
|
||||
int ifindex,
|
||||
DnsAnswer **answer) {
|
||||
|
||||
_cleanup_free_ struct local_address *addresses = NULL;
|
||||
int n;
|
||||
|
||||
@ -405,7 +473,7 @@ int dns_synthesize_answer(
|
||||
|
||||
} else if (is_localhost(name)) {
|
||||
|
||||
r = synthesize_localhost_rr(m, key, ifindex, &answer);
|
||||
r = synthesize_localhost_rr(m, key, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
|
||||
|
||||
@ -437,15 +505,30 @@ int dns_synthesize_answer(
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
|
||||
} else if (is_dns_stub_hostname(name)) {
|
||||
|
||||
r = synthesize_dns_stub_rr(m, key, INADDR_DNS_STUB, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize local DNS stub RRs: %m");
|
||||
|
||||
} else if (is_dns_proxy_stub_hostname(name)) {
|
||||
|
||||
r = synthesize_dns_stub_rr(m, key, INADDR_DNS_PROXY_STUB, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize local DNS stub RRs: %m");
|
||||
|
||||
} else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 &&
|
||||
dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0 &&
|
||||
dns_name_equal(name, "53.0.0.127.in-addr.arpa") == 0 &&
|
||||
dns_name_equal(name, "54.0.0.127.in-addr.arpa") == 0) ||
|
||||
dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
|
||||
|
||||
r = synthesize_localhost_ptr(m, key, ifindex, &answer);
|
||||
r = synthesize_localhost_ptr(m, key, &answer);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
|
||||
|
||||
} else if (dns_name_address(name, &af, &address) > 0) {
|
||||
int v, w;
|
||||
int v, w, u;
|
||||
|
||||
if (getenv_bool("SYSTEMD_RESOLVED_SYNTHESIZE_HOSTNAME") == 0)
|
||||
continue;
|
||||
@ -458,7 +541,11 @@ int dns_synthesize_answer(
|
||||
if (w < 0)
|
||||
return log_error_errno(w, "Failed to synthesize gateway hostname PTR RR: %m");
|
||||
|
||||
if (v == 0 && w == 0) /* This IP address is neither a local one nor a gateway */
|
||||
u = synthesize_dns_stub_ptr(m, af, &address, &answer);
|
||||
if (u < 0)
|
||||
return log_error_errno(u, "Failed to synthesize local stub hostname PTR PR: %m");
|
||||
|
||||
if (v == 0 && w == 0 && u == 0) /* This IP address is neither a local one, nor a gateway, nor a stub address */
|
||||
continue;
|
||||
|
||||
/* Note that we never synthesize reverse PTR for _outbound, since those are local
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-manager.h"
|
||||
|
||||
int dns_synthesize_ifindex(int ifindex);
|
||||
int dns_synthesize_family(uint64_t flags);
|
||||
DnsProtocol dns_synthesize_protocol(uint64_t flags);
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
/* 127.0.0.54 in native endian (The IP address we listen on we only implement "proxy" mode) */
|
||||
#define INADDR_DNS_PROXY_STUB ((in_addr_t) 0x7f000036U)
|
||||
|
||||
/* 127.0.0.2 is an address we always map to the local hostname. This is different from 127.0.0.1 which maps to "localhost" */
|
||||
#define INADDR_LOCALADDRESS ((in_addr_t) 0x7f000002U)
|
||||
|
||||
typedef enum DnsCacheMode DnsCacheMode;
|
||||
|
||||
enum DnsCacheMode {
|
||||
|
@ -56,6 +56,17 @@ echo nameserver 10.0.3.3 10.0.3.4 | "$RESOLVCONF" -a hoge.foo.dhcp
|
||||
assert_in '10.0.3.1 10.0.3.2' "$(resolvectl dns hoge)"
|
||||
assert_in '10.0.3.3 10.0.3.4' "$(resolvectl dns hoge.foo)"
|
||||
|
||||
# Tests for _localdnsstub and _localdnsproxy
|
||||
assert_in '127.0.0.53' "$(resolvectl query _localdnsstub)"
|
||||
assert_in '_localdnsstub' "$(resolvectl query 127.0.0.53)"
|
||||
assert_in '127.0.0.54' "$(resolvectl query _localdnsproxy)"
|
||||
assert_in '_localdnsproxy' "$(resolvectl query 127.0.0.54)"
|
||||
|
||||
assert_in '127.0.0.53' "$(dig @127.0.0.53 _localdnsstub)"
|
||||
assert_in '_localdnsstub' "$(dig @127.0.0.53 -x 127.0.0.53)"
|
||||
assert_in '127.0.0.54' "$(dig @127.0.0.53 _localdnsproxy)"
|
||||
assert_in '_localdnsproxy' "$(dig @127.0.0.53 -x 127.0.0.54)"
|
||||
|
||||
# Tests for mDNS and LLMNR settings
|
||||
mkdir -p /run/systemd/resolved.conf.d
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user