DNAT(宛先NAT)とは?iptables・nftablesでの設定例、トラブルシューティングと実務での注意点

DNAT(Destination NAT)とは何か

DNAT(Destination Network Address Translation、宛先アドレス変換)は、パケットの「宛先アドレス(および必要に応じて宛先ポート)」を書き換える NAT の一種です。外部からルーターやゲートウェイの公開アドレスへ届いたパケットの宛先を、内部ネットワーク上のプライベートIPアドレス(およびポート)に変換して転送する用途で主に使われます。一般に「ポートフォワーディング」「リバースプロキシ(L4)」と呼ばれる操作は DNAT に相当します。

基本動作とパケット処理の流れ

典型的な Linux の実装(netfilter/iptables, nftables)では、DNAT は NAT テーブルの PREROUTING チェーンまたは OUTPUT(ローカル発)チェーンで行われます。処理の流れは以下の通りです。

  • 外部クライアントからパケットが到着
  • カーネルは PREROUTING(ルーティング判断前)で DNAT ルールを評価し、宛先アドレス/ポートを書き換える
  • ルーティング決定に基づき、書き換え後の内部ホストへパケットを転送
  • 返送パケットは逆方向で NAT テーブルの POSTROUTING または conntrack の情報を参照して元の送信元へ戻される(逆変換される)

重要なのは、NAT は接続ごとの「状態(state)」を持つ点です。最初のパケットで変換し、その後は conntrack(接続追跡)テーブルを参照してパケットを処理します。

典型的な利用例

  • 家庭/SOHOルーターのポートフォワーディング(外部:80 → 内部サーバ:80)
  • DMZ や複数サービスを単一パブリックIPで公開するときのポートマッピング
  • コンテナ・仮想化環境(Docker の -p オプション、Kubernetes kube-proxy の iptables モード)のサービス公開
  • ロードバランサ(L4)でのバックエンドノードへの転送(実装によっては DNAT を用いる)

iptables での具体例(IPv4)

代表的なコマンド例(外部パブリック 203.0.113.10 の TCP 80 を内部 192.168.1.10:80 に転送):

iptables -t nat -A PREROUTING -d 203.0.113.10 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80

多くの場合、内部ホストから外向けの応答が NAT デバイス経由になるように POSTROUTING で SNAT または MASQUERADE を設定します:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

nftables での DNAT の例

nftables だとテーブルとチェーンを作り、PREROUTING にルールを追加します:

nft add table ip nat

nft 'add chain ip nat prerouting { type nat hook prerouting priority 0 ; }'

nft add rule ip nat prerouting ip daddr 203.0.113.10 tcp dport 80 dnat to 192.168.1.10:80

DNAT と他の NAT タイプの違い

  • SNAT(Source NAT):送信元アドレスを書き換える。通常は内部クライアントの送信元をグローバルIPに置き換えてインターネットに出すために使う。
  • DNAT:宛先を書き換えて受信トラフィックを適切な内部サーバへ誘導する。
  • PAT(Port Address Translation):1つのグローバルIP上でポートごとに複数の内部アドレス/ポートへ対応させる、広義ではDNAT/PATの一形態。

実装上の注意点と落とし穴

  • 非対称ルーティング:内部サーバの返信が別のゲートウェイ経由で戻ると、NAT デバイスで逆変換されず接続が壊れる。対策として内部サーバのデフォルトゲートウェイを NAT デバイスに向けるか、内部サーバ側でソースを SNAT(POSTROUTING)して応答が NAT デバイス経由になるようにする。
  • hairpin NAT(NAT ループバック):内部クライアントが公開アドレスでサービスへ接続する場合、ルーター側で DNAT と同時に POSTROUTING の SNAT を行わないと内部クライアントへの返りが不正になる。正しい設定が必要。
  • パフォーマンス:NAT は接続ごとの状態を保持するため高スループット・多数コネクションでは CPU/メモリ負荷が問題になる。ハードウェアオフロードや専用ロードバランサの検討が必要。
  • IPv6 では一般的に NAT を使わない設計が推奨される(グローバルアドレスを割り当てる)。IPv6⇄IPv4 の変換が必要な場合は NAT64(RFC6146 等)や DNS64(RFC6147)など専用技術を使う。

セキュリティ上の考慮

DNAT によって内部ホストは外部から直接到達可能になるため、以下に注意してください。

  • 公開するポートは最小限に限定し、必要なアクセス元 IP を制限する(ファイアウォールでフィルタリング)。
  • 可能なら TLS 終端、WAF、認証をリバースプロキシ側で行い内部サービスを保護する。
  • ログ・モニタリングを有効にし、不正アクセスや異常接続を検知できるようにする。
  • 脆弱な内部ホストを直接公開しない。公開は最新のセキュリティパッチ適用済みかつ最小権限で。

クラウドやコンテナ環境での DNAT の使われ方

コンテナ技術(Docker)は、ホストのポートをコンテナへ割り当てる際に内部で DNAT を作成します。Kubernetes の kube-proxy(iptables モード)も Service へのアクセスを Pod のバックエンドに転送するために iptables の NAT ルール(DNAT 相当)を生成します。

クラウドのロードバランサ(L4)や NAT ゲートウェイも内部で DNAT/SNAT 相当の処理を行い、公開IPとプライベートIPのマッピングを実現します。実装細部はプロバイダにより異なるため、運用時はプロバイダのドキュメントを確認してください。

トラブルシューティングの基本コマンド

  • iptables の NAT ルール確認: iptables -t nat -L -n -v
  • nftables の設定確認: nft list ruleset
  • conntrack テーブル確認(接続追跡): conntrack -L または sudo cat /proc/net/nf_conntrack
  • パケットキャプチャ: tcpdump -i <インタフェース> host and port <ポート>
  • 接続状況確認: ss -tnp / netstat -tnp

まとめ(実務での指針)

DNAT はサービス公開やロードバランシングの基本的な仕組みであり、適切に設定すれば内部サービスを柔軟に公開できます。しかし非対称ルーティング、hairpin、パフォーマンス、セキュリティといった注意点があり、単純にルールを追加するだけでは問題が発生しがちです。設計段階でネットワーク経路(返り経路)、接続数の見積、監視・ログ設計、必要なフィルタリングを検討することが重要です。

参考文献