-
Notifications
You must be signed in to change notification settings - Fork 610
Support domain names and port numbers in dns_nameservers #2376
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
base: master
Are you sure you want to change the base?
Changes from all commits
97baf55
5f3cc67
584d596
6efc25a
8aa7366
d904ba0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| #include "ip/tools.h" | ||
| #include "MemBuf.h" | ||
| #include "mgr/Registration.h" | ||
| #include "parser/Tokenizer.h" | ||
| #include "snmp_agent.h" | ||
| #include "SquidConfig.h" | ||
| #include "Store.h" | ||
|
|
@@ -252,7 +253,7 @@ static int max_shared_edns = RFC1035_DEFAULT_PACKET_SZ; | |
| #endif | ||
|
|
||
| static OBJH idnsStats; | ||
| static void idnsAddNameserver(const char *buf); | ||
| static void idnsAddNameserver(const SBuf &ns, const SBuf &origin); | ||
| static void idnsAddMDNSNameservers(); | ||
| static void idnsAddPathComponent(const char *buf); | ||
| static void idnsFreeSearchpath(void); | ||
|
|
@@ -304,27 +305,73 @@ idnsAddMDNSNameservers() | |
| return; | ||
|
|
||
| // mDNS resolver addresses are explicit multicast group IPs | ||
| static const SBuf origin("mDNS specification"); | ||
| if (Ip::EnableIpv6) { | ||
| idnsAddNameserver("FF02::FB"); | ||
| nameservers.back().S.port(5353); | ||
| static const SBuf mDnsIp6("[FF02::FB]:5353"); | ||
| idnsAddNameserver(mDnsIp6, origin); | ||
| nameservers.back().mDNSResolver = true; | ||
| ++nns_mdns_count; | ||
| } | ||
|
|
||
| idnsAddNameserver("224.0.0.251"); | ||
| nameservers.back().S.port(5353); | ||
| static const SBuf mDnsIp4("224.0.0.251:5353"); | ||
| idnsAddNameserver(mDnsIp4, origin); | ||
| nameservers.back().mDNSResolver = true; | ||
|
|
||
| ++nns_mdns_count; | ||
| } | ||
|
|
||
| static void | ||
| idnsAddNameserver(const char *buf) | ||
| idnsAddNameserver(const SBuf &buf, const SBuf &origin) | ||
| { | ||
| Ip::Address A; | ||
|
|
||
| if (!(A = buf)) { | ||
| debugs(78, DBG_CRITICAL, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address"); | ||
| try { | ||
| static const CharacterSet hostChars = CharacterSet("host", "._-") + CharacterSet::ALPHA + CharacterSet::DIGIT; | ||
| static const CharacterSet ip6Chars = CharacterSet("ip6", ":") + CharacterSet::HEXDIG; | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not add a yet another code snippet parsing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no choice at the moment, the other parsers we have a) do not check the requirements properly, or b) do not parse all the valid cases, or c) are hidden privately inside code that cannot be made a dependency of DNS startup. |
||
| Parser::Tokenizer tok(buf); | ||
| SBuf foundHost; | ||
| if (tok.prefix(foundHost, hostChars)) { | ||
| debugs(78, 5, "found host name or IPv4: " << foundHost); | ||
| } else if (tok.prefix(foundHost, ip6Chars) && tok.remaining().isEmpty() /* no port allowed */) { | ||
| debugs(78, 5, "found IPv6 address: " << foundHost); | ||
| } else if (tok.skip('[')) { | ||
| // Squid extension for servers with custom ports needs to handle bracketed IPv6 | ||
| if (tok.prefix(foundHost, ip6Chars) && tok.skip(']')) | ||
| debugs(78, 5, "found IPv6 with brackets: " << foundHost); | ||
| else | ||
| throw TextException("invalid IP address", Here()); | ||
| } else { | ||
| throw TextException("missing or invalid host/IP", Here()); | ||
| } | ||
|
|
||
| // Squid extension for servers with custom ports | ||
| int64_t foundPort = 0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And how exactly do you propose we access the non-existent value inside this |
||
| if (tok.skip(':')) { | ||
| if (tok.int64(foundPort, 10, false)) { | ||
| if (foundPort <= 0 || foundPort > std::numeric_limits<uint16_t>::max()) | ||
| throw TextException("invalid port number", Here()); | ||
| debugs(78, 5, "found port number: " << foundPort); | ||
| } else | ||
| throw TextException("missing or invalid port", Here()); | ||
| } | ||
|
|
||
| if (!tok.remaining().isEmpty()) | ||
| throw TextException("garbage after host:port", Here()); | ||
|
|
||
| // TODO: support host/FQDN that resolves to multiple IPs | ||
| // TODO: support configured append_domain search for non-IPs | ||
|
|
||
| // XXX: performance regression. c_str() copies | ||
yadij marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (!A.GetHostByName(foundHost.c_str())) | ||
| throw TextException("invalid IP, or unknown hostname", Here()); | ||
| A.port(foundPort != 0 ? foundPort : NS_DEFAULTPORT); | ||
|
|
||
| if (!Ip::EnableIpv6 && !A.setIPv4()) | ||
| throw TextException("IPv6 is disabled", Here()); | ||
|
|
||
| } catch (...) { | ||
| debugs(78, DBG_CRITICAL, "ERROR: rejecting " << origin << " nameserver '" << buf << "' with " << CurrentException); | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -334,19 +381,14 @@ idnsAddNameserver(const char *buf) | |
| debugs(78, DBG_CRITICAL, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine"); | ||
| } | ||
|
|
||
| if (!Ip::EnableIpv6 && !A.setIPv4()) { | ||
| debugs(78, DBG_IMPORTANT, "WARNING: IPv6 is disabled. Discarding " << A << " in DNS server specifications."); | ||
| return; | ||
| } | ||
|
|
||
| auto &nameserver = nameservers.emplace_back(ns()); | ||
| A.port(NS_DEFAULTPORT); | ||
| ns nameserver; | ||
| nameserver.S = A; | ||
| #if WHEN_EDNS_RESPONSES_ARE_PARSED | ||
| nameserver.last_seen_edns = RFC1035_DEFAULT_PACKET_SZ; | ||
| // TODO generate a test packet to probe this NS from EDNS size and ability. | ||
| #endif | ||
| debugs(78, 3, "Added nameserver #" << nameservers.size()-1 << " (" << A << ")"); | ||
| nameservers.emplace_back(nameserver); | ||
| debugs(78, Important(15), "Added nameserver #" << nameservers.size()-1 << " (" << A << ") from " << origin << " " << buf); | ||
| } | ||
|
|
||
| static void | ||
|
|
@@ -388,10 +430,10 @@ idnsFreeSearchpath(void) | |
| static bool | ||
| idnsParseNameservers(void) | ||
| { | ||
| static const SBuf origin("squid.conf dns_nameservers"); | ||
| bool result = false; | ||
| for (auto &i : Config.dns.nameservers) { | ||
| debugs(78, Important(15), "Adding nameserver " << i << " from squid.conf"); | ||
| idnsAddNameserver(i.c_str()); | ||
| idnsAddNameserver(i, origin); | ||
| result = true; | ||
| } | ||
| return result; | ||
|
|
@@ -418,15 +460,10 @@ idnsParseResolvConf(void) | |
| if (nullptr == t) { | ||
| continue; | ||
| } else if (strcmp(t, "nameserver") == 0) { | ||
| t = strtok(nullptr, w_space); | ||
|
|
||
| if (nullptr == t) | ||
| continue; | ||
|
|
||
| debugs(78, DBG_IMPORTANT, "Adding nameserver " << t << " from " << _PATH_RESCONF); | ||
|
|
||
| idnsAddNameserver(t); | ||
| result = true; | ||
| if (const auto label = strtok(nullptr, w_space)) { | ||
| idnsAddNameserver(SBuf(label), SBuf(_PATH_RESCONF)); | ||
| result = true; | ||
| } | ||
| } else if (strcmp(t, "domain") == 0) { | ||
| idnsFreeSearchpath(); | ||
| t = strtok(nullptr, w_space); | ||
|
|
@@ -526,6 +563,9 @@ idnsParseWIN32SearchList(const char * Separator) | |
| static bool | ||
| idnsParseWIN32Registry(void) | ||
| { | ||
| static const SBuf originDhcp("Registry 'DhcpNameServer'"); | ||
| static const SBuf originNs("Registry 'NameServer'"); | ||
|
|
||
| char *t; | ||
| char *token; | ||
| HKEY hndKey, hndKey2; | ||
|
|
@@ -548,9 +588,8 @@ idnsParseWIN32Registry(void) | |
| token = strtok(t, ", "); | ||
|
|
||
| while (token) { | ||
| idnsAddNameserver(token); | ||
| idnsAddNameserver(SBuf(token), originDhcp); | ||
| result = true; | ||
| debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry"); | ||
| token = strtok(nullptr, ","); | ||
| } | ||
| xfree(t); | ||
|
|
@@ -564,8 +603,7 @@ idnsParseWIN32Registry(void) | |
| token = strtok(t, ", "); | ||
|
|
||
| while (token) { | ||
| debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry"); | ||
| idnsAddNameserver(token); | ||
| idnsAddNameserver(SBuf(token), originNs); | ||
| result = true; | ||
| token = strtok(nullptr, ", "); | ||
| } | ||
|
|
@@ -618,8 +656,7 @@ idnsParseWIN32Registry(void) | |
| RegQueryValueEx(hndKey2, "DhcpNameServer", nullptr, &Type, (LPBYTE)t, &Size); | ||
| token = strtok(t, ", "); | ||
| while (token) { | ||
| debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry"); | ||
| idnsAddNameserver(token); | ||
| idnsAddNameserver(SBuf(token), originDhcp); | ||
| result = true; | ||
| token = strtok(nullptr, ", "); | ||
| } | ||
|
|
@@ -632,8 +669,7 @@ idnsParseWIN32Registry(void) | |
| RegQueryValueEx(hndKey2, "NameServer", nullptr, &Type, (LPBYTE)t, &Size); | ||
| token = strtok(t, ", "); | ||
| while (token) { | ||
| debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry"); | ||
| idnsAddNameserver(token); | ||
| idnsAddNameserver(SBuf(token), originNs); | ||
| result = true; | ||
| token = strtok(nullptr, ", "); | ||
| } | ||
|
|
@@ -677,8 +713,7 @@ idnsParseWIN32Registry(void) | |
| token = strtok(t, ", "); | ||
|
|
||
| while (token) { | ||
| debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry"); | ||
| idnsAddNameserver(token); | ||
| idnsAddNameserver(SBuf(token), originNs); | ||
| result = true; | ||
| token = strtok(nullptr, ", "); | ||
| } | ||
|
|
@@ -1618,9 +1653,12 @@ Dns::Init(void) | |
| #endif | ||
|
|
||
| debugs(78, DBG_IMPORTANT, "or use the 'dns_nameservers' option in squid.conf."); | ||
| static const SBuf origin("squid default"); | ||
| static const SBuf localhost4("127.0.0.1"); | ||
| static const SBuf localhost6("::1"); | ||
| if (Ip::EnableIpv6) | ||
| idnsAddNameserver("::1"); | ||
| idnsAddNameserver("127.0.0.1"); | ||
| idnsAddNameserver(localhost6, origin); | ||
| idnsAddNameserver(localhost4, origin); | ||
| } | ||
|
|
||
| if (!init) { | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a test for multiple
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 8aa7366
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please adjust It is probably a good idea to also note
Edit: GitHub hit this change request while I was writing my review, so I added another, similar one. I deleted the latter after I noticed that this change request was resurrected.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done in d904ba0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ## Copyright (C) 1996-2026 The Squid Software Foundation and contributors | ||
| ## | ||
| ## Squid software is distributed under GPLv2+ license and includes | ||
| ## contributions from numerous individuals and organizations. | ||
| ## Please see the COPYING and CONTRIBUTORS files for details. | ||
| ## | ||
|
|
||
| # | ||
| # This file contains the list of valid nameserver syntax Squid is supposed | ||
| # to accept. It covers various uses of: | ||
| # IPv4 | ||
| # IPv6 with and without IPvFuture compatible braces | ||
| # Fully Qualified Domain Name (FQDN) | ||
| # Hostname label | ||
| # Optional port values | ||
| # | ||
|
|
||
| # IPv4 | ||
| dns_nameservers 127.0.0.1 | ||
| dns_nameservers 127.0.0.1:53 | ||
| dns_nameservers 127.0.0.1:80 | ||
|
|
||
| # IPv6 | ||
| dns_nameservers ::1 | ||
| dns_nameservers [::1] | ||
| dns_nameservers [::1]:53 | ||
| dns_nameservers [::1]:80 | ||
|
|
||
| # FQDN | ||
| dns_nameservers example.com | ||
| dns_nameservers example.com:53 | ||
| dns_nameservers example.com:80 | ||
|
|
||
| # host name | ||
| dns_nameservers localhost | ||
| dns_nameservers localhost:53 | ||
| dns_nameservers localhost:80 | ||
|
|
||
|
|
||
| # multiple mixed entries per line | ||
| dns_nameservers localhost:81 example.com:52 ::7 [::2] 127.0.0.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we make this code more complex, I recommend changing/fixing this code error handling so that configuration errors trigger an exception (and, hence, become fatal at startup). That change should be done in a dedicated prerequisite PR. It will affect how this code is structured and called/used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setup should be done by the
Dns::ConfigRrrunner. However that refactoring project for startup runners is stuck awaiting reviewer on a number of prerequisites already.For now this PR keeps the status-quo behaviour when receiving invalid configurations: log and ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have done the
Dns::ConfigRrchanges in PR #2378. Order of merge does not matter for these two.Have been experimenting today with what is needed to parse the
dns_nameserversand validate immediately instead of just storing for later validation. I am not seeing any particular reason why that change cannot be done as a followup - there is only a few lines of overlap with this PR.