Linux/DNSのipv4、v6取得順の変更(getaddrinfo)

DNSでIPアドレスを取得する時にIPv6 よりも IPv4 の方を優先させる(2017-08-06、更新:2017-08-18)


DNS名前解決*1で getaddrinfo を使っているならば gai.conf が利くようです。
(詳しくは man getaddrinfo やら man gai.conf やらを参照)

/etc/gai.conf は存在して無かったですが、
「find / -name gai.conf 」 してみたら、うちの CentOS 7 環境だと
/usr/share/doc/(中略)/gai.conf が元ネタにできそうだったので、このファイルを
cp して、vi で編集します。

コピーした /etc/gai.conf の以下を更新
#    For sites which prefer IPv4 connections change the last line to
#
precedence ::ffff:0:0/96  100

英文に IPv4 connect を prefer するなら~みたいな記述があるので
上記の precedence の行のコメント(#)部分を消して有効な行へと変えます。
これで、うちの環境は IPv6 優先だったんですが、IPv4 優先に変更することができました。

・・・今度は忘れた頃に、v4 から v6 優先に戻す必要があったりして。


・・・と、言ってるそばから、必要が出ました。
(忘れる前で本当に良かった)
今度は 4 から 6 に変換できないエラーです。

Ip::Address::getSockAddr : Cannot convert non-IPv4 to IPv4. from [xxxx:xxxx::1]:53

これは squid*2 で出たログなんですが、IPv4 アドレスが取得できずに
(名前解決(port:53) ができずに、接続が確立できずに、何だかんだあって)
接続を受けることができなくなってしまいました。
結局 gai.conf を消して、一旦もとに戻してみました。

gai.conf の条件をもう少し真面目に書けば良いのかもしれません。
そもそも、IPv6 から v4 の変換は上手くいかなくても不思議ではないですし。
(v4 が枯渇したから v6 を作ったので、v4 - v6 変換が上手くいく方が運が良いのかも)

とはいえ、失敗も含めて、
これを使えば変換の優先順位が制御できることが分かりました。


ことの発端は、
とあるサイトへIPv6 https 接続しようとしたら無応答で
IPv4 接続したら成功したという事象からでした。*3

以下、具体的な話
(17/8/1 現在のお話。監視ツール snort のお話は こちら

snort で、設定周りを最新版に更新するツール pulledpork.pl があるのですが
その情報を snort.org から取得することができませんでした。

# pulledpork.pl -c pulledpork.conf -i disablesid.conf -T -H -vv
(以下中略。ちなみに -vv は実行内容の詳細を表示させるオプション)
** GET https://www.snort.org/reg-rules/snortrules-snapshot-2990.tar.gz.md5/自分の設定 ==>

と、コマンド実行時の https 接続で固まってしまいます。

  • 「tcpdump port https」 などで確認しつつ 再実行すると、
    うちの環境だとsnort.org へIPv6接続しに行っているようで、
    かつ、tcp接続(ハンドシェイク)で無応答になってしまっているらしい
  • dig や nslookup などで snort.org のIPアドレスを引いてみると
    うちの環境でも IPv4、IPv6 両方が引けることは確認できた
  • 「https://[snort.orgのIPv4アドレス] 」で実行すると応答はあった

という事が分かったので、どうやら
snort.org へは IPv4 で接続すれば良さげです。それで冒頭の gai.conf へ戻ります。

原因が思いつかず、苦戦してしまいました。
(v4とv6の処理は自動的に(親切な小人が)やってくれるような感覚なので)

接続されるWebサイト側でセキュリティ対策、DoS対策やらSSL証明書設定やらで
いちいち v4 だの v6 だの分けて管理するのが大変なのかもしれませんね。
・・・かく言う私も、v4しか対応していないサイトです。
v6でもIPアドレスフィルタを実装するのがめんどくさい ISPの制約で v6 の検証ができない環境なので、移行しづらいのです。


*1 正しくは「DNS」の話では無く、単に「名前とアドレスの変換」の話ですが、なんとなくふんわり理解できれば良いと思ってますので。
*2 リバースプロキシを提供する機能(詳細は後日まとめる予定)。「-d 1」オプションを付けて確認したときのログです。
*3 通常は http://null-i.net みたいにIPv4だのv6だの指定することは無いんですが、http://[IPアドレス] みたいに、アドレス直打ちにしたり[~]でアドレスを囲むことで、IPv4 か IPv6 かを指定することができます。IPアドレスは dig や nslookupコマンドで、あるいはそれらでググれば、nslookup の情報を提供しているサイトから調べることができます。