足りないっていうとNATっていう。
こだまでしょうか、いいえIPv4。
枯渇するといわれ続けて三千年、枯渇しても普及しませんIPv6。
まずは自宅から始めてみましょう。
未来ずらぁ
皆さんはIPv6と聞くとどんなイメージを抱きますか?
私自身IPv6に対しては割り当て数が多い次世代規格程度の認識しか持っておらず、手持ちの環境(ISP)では実現不可だと思っていました。
ですが、先日、自宅回線をauひかりからコミュファ光に乗り換えようとしたところ「IPv6?速いらしいじゃん?PPPoE?IPoE?ポッポー!」みたいな状態だったので、きちんと理解しようと一念発起し勉強しました。
すると、今の環境でもIPv6いけるんじゃねということになり、実際、Wi-FiルーターのIPv6という項目をポチっとするだけでIPv6で接続ができ、じゃあサーバーなんかもIPv6にしてしまえってことで本件が開戦した次第です。
別にIPv6のヘッダフォーマットやらまで理解する必要はありませんが、最低限、書式やリンクローカルアドレス等が分からないと危険ですので、僕と同じでIPv6?ピーポ君?な人はこちらの記事でも読んでみてください。
IPv6に限らずですが、ルーターのセキュリティはきちんと設定してくださいね。
IPv6デュアルスタック化
ネットをあさればゴロゴロと情報がありますが、当方の設定は以下のようにしてあります。
server:
#ログ
verbosity: 0 #無効
#CPUコア数
num-threads: 4
#受け入れインターフェース
interface: ::1 #IPv6ローカルホスト≒127.0.0.1
interface: :: #IPv6任意IP≒0.0.0.0
interface: 127.0.0.1 #IPv4ローカルホスト
interface: 0.0.0.0 #IPv4任意IP
#受け入れポート
port: 53 #デフォルト
#アクセスコントロール
access-control: 192.168.1.0/24 allow #IPv4ローカル
access-control: fe80::/10 allow #IPv6ローカル
#動作設定
do-ip4: yes #IPv4を解決する
do-ip6: yes #IPv6を解決する
do-udp: yes #UDPを解決する
do-tcp: yes #TCPを解決する
#情報の秘匿
hide-identity: yes
hide-version: yes
#IPv6優先
prefer-ip6: yes
#パフォーマンス設定
outgoing-range: 200 # 1024/コア数 - 50
num-queries-per-thread: 100 # outgoing-rangeの半分
msg-cache-size: 64m #キャッシュメモリサイズ(合計で最大2.5倍になるので余裕をもって)
rrset-cache-size: 128m #キャッシュメモリサイズ(msg-cache-sizeの2倍)
msg-cache-slabs: 4 #コア数に最も近い2の累乗
rrset-cache-slabs: 4 #コア数に最も近い2の累乗
infra-cache-slabs: 4 #コア数に最も近い2の累乗
key-cache-slabs: 4 #コア数に最も近い2の累乗
#該当しない問い合わせをDNSに投げる
forward-zone:
name: "." #すべて
forward-addr: 2001:4860:4860::8888 #Google public DNS IPv6
forward-addr: 2001:4860:4860::8844 #Google public DNS IPv6
forward-addr: 8.8.8.8 #Google public DNS IPv4
forward-addr: 8.8.4.4 #Google public DNS IPv4
このように設定しておけばIPv4/IPv6デュアルスタックのDNSキャッシュサーバーとして稼働するはずです。
outgoing-range
パフォーマンス設定についてoutgoing-range
とnum-queries-per-thread
を8192
のように大きく設定している記事がありますが、ユーザー会様によると、outgoing-range
には最大で1024
の制限があるとのことです。
libevent
というプラットフォームをコンパイル時に導入すると、1024
の制限を突破できるようですがapt installした場合は不可だと思われます。
当方は家庭内のみでの実装なので制限に甘んじて、推奨の1024/コア数 - 50
としています。
ファイアウォール
忘れないようにファイアウォールも開けておきましょう。
当方ではufw
を使用していますので、sudo ufw allow from fe80::/10 to any port 53
とすればローカルから53ポートへのアクセスが可能になります。
機器側設定
IPv6ではIPアドレスは基本的にDHCPv6かRA(Router Advertisement)を用いた自動割り当てですから任意のIPを設定することはありません。
ですが、ローカル内ではプレフィックスやMACアドレスを用いて生成されたリンクローカルアドレスという固有のアドレスを持っていますので、そいつを使ってDNSサーバーを指定します。
まず、ip a
でUnboundを走らせるマシンのリンクローカルアドレスを調べます。
hogehoge@hogehoge:~ $ ip a #リンクローカルアドレスを調べます
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.1.x/24 brd 192.168.1.255 scope global noprefixroute wlan0
valid_lft forever preferred_lft forever
inet6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 297sec preferred_lft 117sec
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link #こいつがリンクローカルアドレス
valid_lft forever preferred_lft forever
inet6
というところにあるfe80::xxxx:xxxx:xxxx:xxxx
がリンクローカルアドレスです。
ちなみに、リンクローカルアドレスはfe80::
から始まります。
このアドレスをPCのDNSサーバーとして設定すれば完了です。
DNSゾーン設定
ここからが本命のローカルでのDNSに関する設定です。
ダメです!
こっちがダメだった設定です。
ゾーンファイルについて少しですが解説も書いておきます。
server:
# local-zone: "ローカルで返すゾーン." type => 以下の表参照
local-zone: "example.com." transparent
# 正引きの設定
# local-zone: ローカルで返すドメイン.(最後尾の.を忘れずに)
# | TTL(パケットの寿命、一個ルーターを通る毎に減るので300回渡り歩く)
# | | クラス名(INTERNETの略)
# | | | Aレコード(エラーの原因でした)
# | | | | IPアドレス
local-data: "example.com. 300 IN A 192.168.1.x" #これをそのままIPv6に書き換えたら…。
local-data: "www.example.com. 300 IN A 192.168.1.x"
#IPv6の正引き設定
local-data: "example.com. 300 IN A fe80::xxxx:xxxx:xxxx:xxxx" #ダメです!
local-data: "www.example.com. 300 IN A fe80::xxxx:xxxx:xxxx:xxxx" #動きません!
IPv6のlocal-zone
をコメントアウトすると動くので、ここが原因と推測。
local-zoneの主なtype
type | |
---|---|
deny |
local-data に一致したら問い合わせに回答します。一致しない場合は無視します。 |
refuse |
local-data に一致したら、問い合わせに回答します。一致しない場合は rcode REFUSED を添えてエラーを返します。 |
static |
local-data に一致したら、問い合わせに回答します。完全不一致なときは、 nodata あるいはnxdomain を回答します。サブドメインなどで部分一致として local-data に存在するときには、否定回答として回答にSOAが含まれます。 |
transparent |
local-data に一致したら、問い合わせに回答します。一致しない場合は forward-zone で設定したDNSサービスに問い合わせます。 |
原因と解決策
IPv4の時はlocal-data: "example.com. 300 IN A 192.168.1.x"
のように設定してたので、IPv6でも"example.com. 300 IN A fe80::xxxx:xxxx:xxxx:xxxx"
と設定しましたがエラーになりました。
試行錯誤した結果、IPv6ゾーンはAレコードではなくAAAAレコードであることが分かりました。
ですので、"example.com. 300 IN AAAA fe80::xxxx:xxxx:xxxx:xxxx"
とするのが正解です。
正解
IPv6をAAAAレコードにして、逆引き設定を追加して完成形です。
server:
local-zone: "example.com." transparent
local-data: "example.com. 300 IN AAAA fe80::xxxx:xxxx:xxxx:xxxx"
local-data: "www.example.com. 300 IN AAAA fe80::xxxx:xxxx:xxxx:xxxx"
local-data-ptr: "fe80::xxxx:xxxx:xxxx:xxxx 300 example.com."
local-data-ptr: "fe80::xxxx:xxxx:xxxx:xxxx 300 www.example.com."
local-data: "example.com. 300 IN A 192.168.1.x"
local-data: "www.example.com. 300 IN A 192.168.1.x"
local-data-ptr: "192.168.1.x 300 example.com."
local-data-ptr: "192.168.1.x 300 www.example.com."
これでexample.com
とwww.example.com
に対してIPv6アドレスとIPv4アドレスの両方を返してくれます。
ディレクトリ/etc/unbound/unbound.conf.d/
以下にあって拡張子が.conf
であればファイル名は任意です。
気分爽快
デュアルスタックにすると処理量が増えます。
もう一度言います。
デュアルスタックにすると、IPv6とIPv4二重に処理をするため処理量が増えます。
見にくいし、長いし、つまりメリットなんてありません。多分。
それでも、「俺、IPv6使ってるぜー!」
って爽快感が堪りません。
同じ気分を味わいたい方はぜひ挑戦してみてください。
それと「v6プラス契約してもうたー」って人も参考にしてみてください。
IPv6化のメリットについて追記
自宅IPに動的DNSを設定してサーバーを開設したものの、ローカルからドメインにアクセスするとルーターの管理画面に繋がってしまい、IP直打ちだとSSLエラーになる、といった事情に陥っている方は結構いらっしゃると思います。
私もその一人でしたので内向きDNSサーバーを立ててローカルからのDNSの問い合わせにサーバーのローカルIPを回答するようにしたわけです。
ところが、IPv6化しただけで当該事象が解決したので、これがIPv6化最大のメリットだと感じました。
Unbound
の記事でUnbound不要になったぜー
なんて書くのはあほらしいんですが、お役に立てれば幸いです。
理屈
IPv4
ではルーターにグローバルIPアドレス
が割り振られ、宅内はローカルIPのみで管理されていたと思います。
DNSから回答されるのはルーターのグローバルIPアドレスになりますので、WAN側からのアクセスはNAT転送
で目的サーバーに繋がりますが、LAN側からルーターの80ポートへのアクセス=>ルーター管理画面となってしまうのです。
しかし、IPv6では全ての機器にグローバルIPアドレスが設定されますのでローカルのサーバーもグローバルIPを持つことになります。
このサーバーが持っているグローバルIPアドレスをDNSに通知した場合、回答されたグローバルIPアドレスで一意にサーバーへ到達が可能ですので、仮にローカルからのアクセスだとしてもサーバーにたどり着くことができるわけです。
この場合、ルーターで宅外からIPv6のパケットをホスト非公開(セキュリティ上推奨)の設定があったとしても、IPパケットは(宛先はグローバルIPアドレスですが)ローカル内でのやり取りにとどまるので問題なくアクセスが可能です。
グローバルIPアドレスは自動割り振りが基本なのでルーターでのファイアウォール設定がやや複雑になります。
IPv4とのデュアルスタックであれば宅外からのアクセスはIPv4としてNATを活用したセキュリティの維持が可能です。
IPv6で80と443全開放
などはくれぐれもなさらないで、IPv6で宅外からアクセスを望まれる場合は、MACアドレス等で宛先をサーバーに限定して、ファイアウォールを開けてくださいますようお願いいたします。