https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112020-02-25T14:58:44ZRuby Issue Tracking SystemRuby master - Bug #16653: Weird behaviour of Resolv modulehttps://bugs.ruby-lang.org/issues/16653?journal_id=843752020-02-25T14:58:44Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>Looks like the issue is using multiple domain names instead of IP addresses for the :nameserver option. Single domain name works, multiple IP addresses works, IP address and domain name works, multiple domain names does not work:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'a.iana-servers.net'</span><span class="p">,</span> <span class="s1">'b.iana-servers.net'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => []</span>
<span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'b.iana-servers.net'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => [#<Resolv::DNS::Resource::IN::A:0x0000177abba0b598 @address=#<Resolv::IPv4 93.184.216.34>, @ttl=86400>]</span>
<span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'a.iana-servers.net'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => [#<Resolv::DNS::Resource::IN::A:0x0000177a82c89998 @address=#<Resolv::IPv4 93.184.216.34>, @ttl=86400>]</span>
<span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'199.43.135.53'</span><span class="p">,</span> <span class="s1">'199.43.133.53'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => [#<Resolv::DNS::Resource::IN::A:0x0000177a98047e58 @address=#<Resolv::IPv4 93.184.216.34>, @ttl=86400>]</span>
<span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'a.iana-servers.net'</span><span class="p">,</span> <span class="s1">'199.43.133.53'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => [#<Resolv::DNS::Resource::IN::A:0x0000177a8d8fe0c0 @address=#<Resolv::IPv4 93.184.216.34>, @ttl=86400>]</span>
<span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">nameserver: </span><span class="p">[</span><span class="s1">'199.43.135.53'</span><span class="p">,</span> <span class="s1">'b.iana-servers.net'</span><span class="p">]).</span><span class="nf">getresources</span><span class="p">(</span><span class="s1">'example.com'</span><span class="p">,</span> <span class="no">Resolv</span><span class="o">::</span><span class="no">DNS</span><span class="o">::</span><span class="no">Resource</span><span class="o">::</span><span class="no">IN</span><span class="o">::</span><span class="no">A</span><span class="p">)</span>
<span class="c1"># => [#<Resolv::DNS::Resource::IN::A:0x0000177a1b8089a8 @address=#<Resolv::IPv4 93.184.216.34>, @ttl=86400>]</span>
</code></pre> Ruby master - Bug #16653: Weird behaviour of Resolv modulehttps://bugs.ruby-lang.org/issues/16653?journal_id=858442020-05-27T22:13:52Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>I've looked into this more. The underlying cause is that Resolv expects nameservers to be specified as IP addresses, not as domain names. When using multiple nameservers, Resolv tries to match the IP address of the nameserver responding to one of the nameservers given as input, and if you give a domain name as input, there will be no match.</p>
<p>It makes sense for Resolv to only handle IP addresses as nameservers, as if you are providing a domain name to use as a nameserver, where would you look up the IP address of that nameserver to know where to connect? You can't use the resolver you are setting up to resolve that. This is the same reason that no operating system allows you to use a domain name as a DNS server.</p>
<p>I was able to come up with a workaround that uses the system resolver:</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/lib/resolv.rb b/lib/resolv.rb
index e7b45e785a..d529550bdb 100644
</span><span class="gd">--- a/lib/resolv.rb
</span><span class="gi">+++ b/lib/resolv.rb
</span><span class="p">@@ -1027,12 +1027,33 @@</span> def lazy_initialize
if config_hash.include? :nameserver_port
@nameserver_port = config_hash[:nameserver_port].map {|ns, port| [ns, (port || Port)] }
end
<span class="gi">+
</span> @search = config_hash[:search] if config_hash.include? :search
@ndots = config_hash[:ndots] if config_hash.include? :ndots
<span class="err">
</span><span class="gd">- if @nameserver_port.empty?
</span><span class="gi">+ case @nameserver_port.length
+ when 0
</span> @nameserver_port << ['0.0.0.0', Port]
<span class="gi">+ when 1
+ # nothing
+ else
+ @nameserver_port = @nameserver_port.map do |host, port|
+ dns_name = true
+ case host
+ when /\A[0-9.]+\z/
+ dns_name = false
+ when /\A[a-fA-F0-9:]+\z/
+ dns_name = host.index(':')
+ end
+
+ if dns_name
+ host = Addrinfo.getaddrinfo(host, nil)[0]&.ip_address
+ end
+
+ [host, port]
+ end
</span> end
<span class="gi">+
</span> if @search
@search = @search.map {|arg| Label.split(arg) }
else
</code></pre>
<p>However, I'm fairly sure this is a misuse of the resolv library, and therefore I'm going to close this. The fact that things appear to work with a single domain name is just an implementation detail, not by design (single nameserver uses Requester::ConnectedUDP instead of Requester::UnconnectedUDP).</p>