LoginSignup
3
3

More than 5 years have passed since last update.

Ruby のプログラム実行時に DNS resolver を切り替えるやつ

Posted at

sonots/resolver_replace を使ってみたら再帰して too many open files になったので別の方法を探る事に。といっても、Ruby に付いてくる resolv-replace を使うだけで良かった。

DNS サーバ

ioquatix/rubydns を使って、 *.dev なドメインを 127.0.0.1 として解決し、それ以外は上流に任せるという DNS サーバを書く。以下は rubydns の README ほぼそのまま。

#!/usr/bin/env ruby
require 'rubydns'

# Use upstream DNS for name resolution.
upstream = RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]])

# Start the RubyDNS server
RubyDNS.run_server(listen: [[:udp, '0.0.0.0', 5300], [:tcp, '0.0.0.0', 5300]]) do
  match(/\.dev/, Resolv::DNS::Resource::IN::A) do |transaction|
    transaction.respond!('127.0.0.1')
  end

  # Default DNS handler
  otherwise do |transaction|
    transaction.passthrough!(upstream)
  end
end

WEB サーバ

DNS resolver が変更できているか確認するために、ローカルホストで適当なウェブサーバを動かす。

require 'sinatra'

get '/' do
  'OK'
end

検証

以下の様なスクリプトで、プログラム中でのみ DNS resolver を変更できるかを確認。

require 'resolv'
require 'resolv-replace'
require 'open-uri'

resolver = Resolv::DNS.new(nameserver_port: [['127.0.0.1', 5300]])
Resolv::DefaultResolver.replace_resolvers([Resolv::Hosts.new, resolver])

puts open('http://hoge.dev:4567').read
  • Resolv::DNS で任意の DNS サーバのインスタンスを作り、 Resolv::DefaultResolver.replace_resolversResolv::DefaultResolver の中身を入れ替える
  • resolv-replace.rb をロードしていれば、モンキーパッチによってソケットの #getaddressResolv::DefaultResolver を使って名前解決する様になる
    • なお、 #gethostbyname などは対象外なので、ホストで設定されている DNS resolver を使い続ける
  • Resolv::DefaultResolver はソケットの #getaddress のレシーバ
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3