alexdalitz / dnsruby

Dnsruby is a feature-complete DNS(SEC) client for Ruby, as used by many of the world's largest DNS registries and the OpenDNSSEC project
Other
197 stars 77 forks source link

dnsruby cannot interpret an IPv6 link-local address with interface specifier #184

Open Supermathie opened 1 year ago

Supermathie commented 1 year ago

This is affecting one of our MacOS users who is using ruby 2.7.5 and dnsruby 1.61.5.

(separate bug, but interacts with #179 to cause an infinite loop for him)

His resolv.conf is:

nameserver fe80::feed:face:c0ff:ee00%en0
nameserver 192.168.0.1

which is valid since that's an interface-specific LLA, but Dnsruby::Resolver.new.query(…) hangs indefinitely, probably because of #179

I can replicate this with:

pry> Dnsruby::Resolver.new('fe80::feed:face:c0ff:ee00%en0')
ArgumentError: Can't make sense of nameserver : , exception : Nameserver invalid!
from /home/michael/.rvm/gems/ruby-2.6.6/gems/dnsruby-1.61.5/lib/dnsruby/config.rb:306:in `rescue in rescue in rescue in resolve_server'
Caused by Dnsruby::ResolvError: Nameserver invalid!
from /home/michael/.rvm/gems/ruby-2.6.6/gems/dnsruby-1.61.5/lib/dnsruby/recursor.rb:444:in `get_closest_known_zone_for'
Caused by ArgumentError: cannot interpret as IPv6 address: nil
from /home/michael/.rvm/gems/ruby-2.6.6/gems/dnsruby-1.61.5/lib/dnsruby/ipv6.rb:97:in `create'
Caused by ArgumentError: cannot interpret as IPv4 address: nil
from /home/michael/.rvm/gems/ruby-2.6.6/gems/dnsruby-1.61.5/lib/dnsruby/ipv4.rb:35:in `create'

though it returns after ~5s in my case, not creating an infinite loop.

alexdalitz commented 1 year ago

Dnsruby::Resolver.new(:nameserver => 'fe80::feed:face:c0ff:ee00%en0')

Supermathie commented 1 year ago

That only makes dnsruby not throw an exception immediately.

It still doesn't work, nor does it fix the problem when these LLAs are in the resolv.conf file

e.g.:

pry(main)> dns = Dnsruby::Resolver.new(nameserver: '192.168.1.51'); dns.query('www.google.ca').answer
=> [#<Dnsruby::RR::IN::A:0x000055a690c0f120
  @address=#<Dnsruby::IPv4 142.251.41.67>,
  @klass=IN,
  @name=#<Dnsruby::Name: www.google.ca.>,
  @rdata=#<Dnsruby::IPv4 142.251.41.67>,
  @ttl=245,
  @type=A>]

pry(main)> dns = Dnsruby::Resolver.new(:nameserver => 'fe80::5054:ff:fe8b:6576%br0'); dns.query('www.google.ca').answer
Dnsruby::ResolvTimeout: Query timed out - no nameservers configured
from /home/michael/.rvm/gems/ruby-2.6.6/gems/dnsruby-1.61.5/lib/dnsruby/resolver.rb:257:in `send_message'

# from shell, it works:
○ → host www.gooogle.ca fe80::5054:ff:fe8b:6576%br0
Using domain server:
Name: fe80::5054:ff:fe8b:6576%br0
Address: fe80::5054:ff:fe8b:6576%4#53
Aliases: 

www.gooogle.ca has address 78.41.204.26
alexdalitz commented 1 year ago

Yes, I'm sorry for my previous response - I shouldn't have attempted to do anything whilst suffering from Covid! Dnsruby does not currently support IPv6 link local addresses. It doesn't look like Ruby itself has support for them yet, in the IPAddr class. If you'd like to provide a patch for support for these addresses, I'd be very pleased to accept it! Otherwise, I think I will wait until the Ruby IPAddr class has support for them. It doesn't seem useful to provide a separate implementation in Dnsruby. Once IPAddr does have support, then I can move the resolver name servers to be IPAddr instances, rather than the DNS IPv6 and IPv6 classes. In the meantime, I think the answer is simply not to use Dnsruby with those addresses for name servers.