LinuxでTaygaとBIND9を使ったNAT64・DNS64の設定:IPv6-onlyサーバーをIPv4レガシーサービスに接続する

Network tutorial - IT technology blog
Network tutorial - IT technology blog

データセンターをIPv6-onlyに移行したときの問題

約8ヶ月前、使っているVPSプロバイダーからパブリックIPv4に追加料金を課すとの告知があり、ロードマップも明らかにIPv6-only方向を示していました。15台ほどのサーバークラスターを管理しており、ほとんどは内部通信だけでよかったため、コスト削減のためにIPv6-onlyへの移行を試みることにしました。

問題は最初の週から噴出しました。外部サービスの多くがIPv6に対応していなかったのです。古いディストリビューションのaptミラーリポジトリはIPv4のみ。顧客が使っているペイメントゲートウェイもIPv4-only。商用ソフトウェアのライセンスサーバー?もちろんIPv4。接続エラーの一覧を眺めながら、移行するのが早すぎたと痛感しました。

各マシンにIPv4を追加購入するとコストが台数に比例して増えます。クラスター全体をデュアルスタックに戻せば当初の目標が無意味になってしまいます。一週間調べた末に、真の解決策を見つけました——NAT64とDNS64の組み合わせです。これにより、IPv6-onlyサーバーからIPv4-onlyサービスへ完全に透過的に接続でき、アプリケーションのコードを一行も変更する必要がありません。

なぜIPv6-onlyはIPv4に直接接続できないのか

IPv6とIPv4はアドレス構造もパケットヘッダーも根本的に異なるため、直接通信できません。IPv6-onlyサーバーが203.0.113.5(IPv4)に接続しようとする場合、二つの問題を解決する必要があります:

  • ルーティング:パケットの宛先がわかるように、IPv4アドレスをIPv6形式に「エンコード」する手段が必要——これがNAT64の役割です
  • DNS:ドメインの名前解決時に、宛先にAレコード(IPv4)しかない場合、DNSリゾルバーが合成したAAAAレコードを返す必要がある——これがDNS64の役割です

技術的には、DNS64はNAT64プレフィックス(通常はRFC 6052に従い64:ff9b::/96)とIPv4アドレスを組み合わせて疑似AAAAレコードを生成します。クライアントがその合成IPv6アドレスにパケットを送ると、NAT64ゲートウェイがパケットを受け取り、元のIPv4アドレスを抽出して、ゲートウェイのIPv4で実際の宛先にフォワードします。このプロセス全体がアプリケーションに対して透過的に行われます。

3つの解決策とNAT64を選んだ理由

Option 1: デュアルスタック——シンプルだがスケールしない

各マシンにパブリックIPv4を追加する方法です。追加設定は不要ですが、コストがマシン台数に比例して増加します。15〜20台なら問題ありませんが、50〜100台にスケールすると財務的に現実的ではありません。

Option 2: アプリケーションレベルプロキシ(Squid、SOCKS5)

デュアルスタックマシン1台をHTTPプロキシまたはSOCKS5ゲートウェイとして使う方法です。試してみましたが、HTTP/HTTPSは動作するものの、バイナリプロトコル、gRPC、カスタムTCPではアプリケーションごとに個別設定が必要です。数十ものサービスが存在すると、メンテナンスが非常に煩雑になります。

Option 3: NAT64 + DNS64——ネットワーク層での透過的な解決

この解決策はアプリケーション層より下で完全に機能します。IPv6-onlyマシンのDNSをDNS64サーバーに向けるだけで、外向きのTCP/UDP接続がすべて自動処理されます。これが6ヶ月間本番環境で使っている方法です。

Tayga(NAT64)とBIND9(DNS64)のデプロイガイド

アーキテクチャ

IPv4とIPv6の両方を持つLinuxマシン1台をゲートウェイとして使用し、TaygaとBIND9の両方をそこで実行します:

  • Tayga:ユーザースペースで動作するstateful NAT64トランスレーター
  • BIND9:DNS64——AレコードからAAAAレコードを合成
  • NAT64プレフィックス64:ff9b::/96(ウェルノウンプレフィックス)
  • TaygaのIPv4プール192.168.255.0/24(プライベートレンジ)

ステップ1:Taygaのインストールと設定

Ubuntu/Debianの場合:

sudo apt update && sudo apt install tayga

設定ファイル/etc/tayga.confを作成します:

tun-device nat64
ipv4-addr 192.168.255.1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
data-dir /var/db/tayga

Taygaを起動してインターフェースを設定します

sudo mkdir -p /var/db/tayga
sudo tayga --mktun
sudo ip link set nat64 up
sudo ip addr add 192.168.255.1/24 dev nat64
sudo ip -6 route add 64:ff9b::/96 dev nat64
sudo tayga

ステップ2:フォワーディングの有効化とiptables設定

# IPフォワーディングを有効化
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# TaygaプールからインターネットへのIPv4トラフィックをNAT
sudo iptables -t nat -A POSTROUTING -s 192.168.255.0/24 -j MASQUERADE

# nat64インターフェース経由のフォワーディングを許可
sudo ip6tables -A FORWARD -i nat64 -j ACCEPT
sudo ip6tables -A FORWARD -o nat64 -j ACCEPT

ステップ3:BIND9でのDNS64設定

sudo apt install bind9

dns64ブロックを/etc/bind/named.conf.optionsに追加します:

options {
    directory "/var/cache/bind";

    # DNS64:NAT64プレフィックスを使ってAレコードからAAAAを合成
    dns64 64:ff9b::/96 {
        clients { any; };
        # RFC1918(プライベートIPv4)は合成しない——パブリックのみ
        mapped { !rfc1918; any; };
        exclude { 64:ff9b::/96; ::ffff:0:0/96; };
    };

    allow-query { localhost; 2001:db8::/48; };
    recursion yes;

    forwarders {
        8.8.8.8;
        1.1.1.1;
    };

    # DNS64はDNSSECバリデーションを破壊するため無効化が必要
    dnssec-validation no;
};
sudo systemctl restart bind9 && sudo systemctl enable bind9

ステップ4:TaygaのSystemdサービス

Taygaはsystemdサービスを自動作成しないため、手動で作成する必要があります:

# /etc/systemd/system/tayga.service
[Unit]
Description=Tayga NAT64 daemon
After=network.target

[Service]
Type=forking
ExecStartPre=/usr/sbin/tayga --mktun
ExecStartPre=/bin/ip link set nat64 up
ExecStartPre=/bin/ip addr add 192.168.255.1/24 dev nat64
ExecStartPre=/bin/ip -6 route add 64:ff9b::/96 dev nat64
ExecStart=/usr/sbin/tayga --pidfile /run/tayga.pid
PIDFile=/run/tayga.pid
ExecStopPost=/usr/sbin/tayga --rmtun
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now tayga

ステップ5:IPv6-onlyサーバーの設定

IPv6-onlyサーバーで、DNSをゲートウェイに向けます(ゲートウェイIPv6が2001:db8::1の場合):

# /etc/resolv.conf
nameserver 2001:db8::1

# ゲートウェイ経由でNAT64プレフィックスのルートを追加
sudo ip -6 route add 64:ff9b::/96 via 2001:db8::1

動作確認

# DNS64をテスト——64:ff9b::x.x.x.x形式のAAAAが返されるはず
dig AAAA example.com @2001:db8::1

# NAT64経由でIPv4に直接ping
ping6 64:ff9b::8.8.8.8

# IPv6-onlyマシンから実際の接続をテスト
curl -6v https://example.com

# Taygaのマッピングテーブルを表示
sudo tayga --list

実際に踏んだ落とし穴——あなたが避けられるように記録しておく

DNS64リゾルバーではDNSSECを無効にする必要があります:DNS64はauthoritativeサーバーに存在しないAAAAレコードを合成するため、DNSSECバリデーションがすべて失敗します。これは慎重に検討すべきトレードオフです——DNS64は内部トラフィックのみを処理し、インターネットに公開しないため、この妥協を受け入れています。

Taygaはユーザースペースで動作——カーネルではありません:SIITのようなカーネルソリューションと比べてパフォーマンスが低くなります。HTTP APIコールや通常のデータベースクエリのワークロードでは体感できませんが、数Gbpsのスループットが必要な場合はカーネルレベルの高速パケット処理も検討すべきです。

Tracerouteが正常に動作しません:NAT64はICMP embedded addressを処理できないため、NAT64経由のtracerouteではホップが欠落します。ネットワークのデバッグが若干難しくなります——IPv6-onlyマシンからではなく、ゲートウェイ側からデバッグするようにしています。

iptablesルールがリブート後に消えますiptables-persistentをインストールするか、systemdサービスに追加する必要があります:

sudo apt install iptables-persistent
sudo netfilter-persistent save

6ヶ月間の本番運用を経て

このセットアップは私のオフィスサーバークラスターで安定稼働しています。各マシンにパブリックIPv4を追加購入する場合と比べてコストが明らかに削減されました。さらに重要なのは——開発チームが何も変更する必要がなく、apt update、curl、データベース接続、ライセンスサーバーを含む、IPv4-onlyサービスへのすべてのTCP/UDP接続が正常に動作していることです。

NAT64 + DNS64は恒久的な解決策ではありません——レガシーサービスが徐々にIPv6に移行するにつれ、このセットアップも段階的に廃止できます。しかし現在の移行期においては、古いインフラに引きずられることなくIPv6へ進む最も現実的かつ効果的な方法です。

Share: