皆さんお久しぶりです! 長い間ブログを書いてなくて申し訳ないです… 実は最近Web系のプログラムを書くのが多くなり、そちらばかりに時間を割いていました…w
なので、今回からWebプログラミング関連のTipsも軽くメモ程度に書いていこうと思っております。
前置きが長くなりましが、今回は私がRubyで書いたDNSサーバープログラム書いたのでメモを残そうと記事を書きました!
何故作ったの?
最近漫画村やAnitubeなどの海賊版サイトが話題になっており、先日NTTグループがブロッキングを開始するとプレス出して話題になりました。また、そのちょっと前にCloudflareが新しいPublic DNS(1.1.1.1)を公開したりなどDNS周りが盛り上がっておりました!
僕もTwitterでDNS周りのツイートを見かけるようになり、少しネットワーク周りに興味を持ったわけです…w そこで、ブロッキングの話が出てきて僕のお家のプロバイダ確認したら… 見事NTTグループだったわけで、ネタで対抗してやるという理由で作りましたw
また、DNS over HTTPSという新技術が出てるのにみんなあまり触れていなかったので自分で作っちゃえという軽い気持ちで作業に入りましたw
案外簡単にできた!
僕も思っていたのですが、DNSのサーバー作るのは容易ではないと勘違いしておりました。色々検証するんだろうな〜 と思いながらGithub漁っていたら、いい感じのライブラリー見つけて1時間ほどで開発できましたw
今回はRubyDNSというライブラリを利用して作りました。また、接続先はCloudflareの新DNSが提供してるDNS over HTTPSで解決しております。
仕組みの説明
まずは、DNS over HTTPS(DOH)についてご存知でない方は以下のリンクをご覧ください! 簡単に言えばDNS解決をWebAPIでできるようにしたのがDOHです。
今回はRubyDNSを利用しDNSサーバーを立て、受け取ったリクエストを元にQueryを作成しサーバーにリクエストを投げ、JSONで受け取ったデータをパーズして解決先IPを送り返すという簡単な仕組みです。
RubyDNS::run_server(INTERFACES) do otherwise do |t| type = t.resource_class.to_s # リクエストされたレコードタイプを文字列として吐き出す type.slice!(0..26) uri = URI.parse('https://cloudflare-dns.com/dns-query') # CloudflareDNSのURL uri.query = { ct: 'application/dns-json', name: t.question.to_s, type: type }.to_param # 解決するホスト名とタイプをURLQueryとして入れる begin answers = JSON.parse(uri.read)['Answer'] # JSONで帰ってきた解決先IPアドレス・データを読み取る if answers.present? t.respond!(answers.last['data']) # もし解決できた場合、IPアドレスを返す puts "Req: #{t.question.to_s} Type: #{type} Ans: #{answers.last['data']}" else t.fail!(:NXDomain) # 解決できなかった場合はNXdomainを返す puts "!!CANNOT RESOLVE!! Req: #{t.question.to_s} Type: #{type}" end rescue t.fail!(:NXDomain) # 通信エラッタらNXDomainを返す end end end
1時間クオリティ… 結構雑ですが、これでもちゃんと動いてくれますw
作った感想
案外ネットワークにわかにも作れたことに感動しつつ、正直このロジックでDNS鯖として実用的なのか? とは思いました。 実際にクライアント繋げてネットしてみても、割と快適にサーフィンできましたが、やはりdigコマンドで調べてみると、ちょっぴり遅い…
プロバイダが提供してるDNSは60msecぐらいに対して、自作DNS鯖では200msecぐらいかかっています… ここの速度を解決できれば最高ですが、解決策が見つからず… 方法が見つかり次第書き直そうかと思います!