【入門編】 NATインスタンス(EC2ベース)におけるSrc/Dstチェックの無効化要件 – クラウド&コンテナネットワーク実践ガイド

クラウドの世界へ足を踏み入れたばかりの頃、誰もが一度は「プライベートサブネットにあるサーバーから、どうやって外のインターネットへ出ていくんだろう?」という疑問にぶつかりますよね。

AWSなどのメガクラウドでは、マネージドな「NATゲートウェイ」が用意されていますが、コストの最適化や特定のルーティング制御の都合上、あえて自分たちでEC2インスタンスを立てて「自前(DIY)のNATルーター」として運用する場面に直面することがあります。

そんな時、避けて通れないのが「送信元/宛先チェック(Source/Destination Check)」の無効化という設定です。
「なんだか難しそうな名前だな……」と感じるかもしれませんが、一歩ずつ身近な例えから紐解いていけば、決して怖くありません。今回は、パケットの気持ちになりながら、この設定がなぜ絶対に欠かせないのかを一緒に見ていきましょう!

—

郵便配達でイメージする「NATルーター」の役割

まずは、パケットの動きを私たちの身近な「手紙や荷物のやり取り」に置き換えて考えてみましょう。

インターネットの世界は、まるで巨大な郵便網です。プライベートサブネットにいるEC2インスタンス(仮に「A君」としましょう)から、「外のWebサイト(Bさん)」へ手紙を送りたいとします。

A君は内輪のネットワークにしかいないため、外の世界へ手紙を出すときは、宛先をBさんにした上で、一度アパートの管理人である「自作NATインスタンス(NAT君)」に手紙を預けます。

ここで、NAT君の仕事が始まります。
外の世界(インターネット)へ手紙を出すとき、Bさんから返事をもらうためには、差出人をA君のプライベートIPアドレスではなく、インターネットの世界でも通用する「NAT君自身のグローバルIPアドレス(Elastic IP)」に書き換える必要がありますよね。この仕組みこそが「NAT(Network Address Translation)」です。

そして、Bさんからの返事が届いたとき、NAT君は「お、これはさっきA君が送った手紙の返事だな」と気づき、宛先をNAT君自身からA君のIPアドレスに書き直して、プライベートサブネットにいるA君の元へ届けてあげます。

—

なぜAWSはデフォルトでパケットを止めてしまうのか?

ここで、AWSという「巨大でセキュリティに厳しい管理会社」のルールが登場します。

AWSのネットワーク基盤は、デフォルトの状態だと極めておせっかい(かつ安全第一)に作られています。
AWSのルーターやスイッチは、EC2インスタンスから流れてくるネットワークのパケットを監視しており、次のようなルールを設けています。

> 「我が社のネットワークを流れるパケットは、『送信元IPアドレス』が、そのパケットを出したEC2インスタンス自身のIPアドレスでなければならない!」

もし、このルールに違反しているパケットを見つけたら、AWSの基盤側は「おや? このパケット、差出人の名前を偽装していないか? 悪意ある攻撃かもしれない!」と勘違いし、その場でパケットを容赦なくドロップ(破棄)してしまうのです。

自前NATインスタンスで何が起きるか?

先ほどの郵便配達の例を思い出してください。
自作NATインスタンスは、プライベートサブネットのA君に代わって、外の世界へ手紙を出します。このとき、パケットの「送信元IPアドレス(差出人)」は、A君のIPアドレスからNAT君のIPアドレスに書き換えられます。

もしAWSの「送信元/宛先チェック」が有効(デフォルト)のままだと、どうなるでしょうか?

NATインスタンスが「はい、このパケットは私のもの(送信元IP=NATインスタンスのIP)として外に出します!」と送り出した瞬間、AWSの基盤側がこう言います。
*「ちょっと待て! 元をたどるとこのパケット、さっきプライベートサブネットにいたA君の荷物じゃないか! なぜ差出人を君の名前に書き換えているんだ! 偽装だ! 破棄!」*

こうして、プライベートサブネットからの通信はすべてAWSの網の毛でブロックされてしまい、インターネットに出られないというトラブルが発生します。これが、送信元/宛先チェックを無効化しなければならない理由です。

—

「送信元/宛先チェックの無効化」でAWSに何を伝えるのか?

AWSのコンソールやコマンドラインで「送信元/宛先チェック(Source/Destination Check)を無効にする」という設定を行うのは、AWSに対してこう宣言する意味を持っています。

*「このEC2インスタンスは、ただの一般サーバーではありません。我が社のネットワークを守る『NATルーター(交通整理のお巡りさん)』なのです。だから、他のサーバーのパケットを代行して、差出人や宛先の名前を書き換えて外に出したり入れたりすることが仕事なのです。どうかそのパケットを怪しんで捨てないでください!」*

この設定を施すことで、AWSのセキュリティ監視の網目をくぐり抜け、ルーターとしての正当なパケット書き換えが認められるようになります。

—

実践! 構築時の具体的な設定手順

それでは、実際にAWS環境で自作NATインスタンスを構築する際の、設定の流れを確認していきましょう。ここでは、AWS CLIを使った設定手順を例に解説します。

1. OSレベルでのパケット転送(IPフォーワーディング)の有効化

まず、Linux(EC2のOS)自身が「私はルーターとして、自分宛てではないパケットを別の場所へ転送する役割を担います」と設定する必要があります。

SSHでNATインスタンスにログインし、カーネルパラメータを変更します。

# /etc/sysctl.conf ファイルにパケット転送を許可する設定を追記します
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf

# 設定をただちに反映させます
sudo sysctl -p

この設定により、LinuxのOSカーネルが「受け取ったパケットの宛先が自分以外でも、ルーティングテーブルに従って別のネットワークへ送り出す」ようになります。

2. AWS側での「送信元/宛先チェック」の無効化(AWS CLI)

次に、EC2インスタンスのネットワークインターフェース(ENI)に対して、AWS側でチェックを無効化します。

# 対象のEC2インスタンスのインスタンスIDと、ネットワークインターフェースIDを特定し、チェックを無効化します
# ※ network-interface-id には、NATインスタンスにアタッチされているENIのIDを指定します

aws ec2 modify-instance-attribute \
    --instance-id i-0123456789abcdef0 \
    --no-source-dest-check

もちろん、AWSマネジメントコンソールから操作する場合は、対象のEC2インスタンスを選択し、「アクション」 > 「ネットワーキング」 > 「送信元/宛先チェックの変更」 から「無効化」にチェックを入れるだけで完了します。

—

トラブルシューティングの現場から:ありがちな落とし穴

現場のSREとして数々の環境構築を見ていると、このNAT構築でハマるポイントがいくつかあります。最後に、よくある失敗パターンをご紹介します。

1. OSのパケット転送を忘れていた
AWS側のチェックを無効化したのに外に出ない場合、大体はOS側の net.ipv4.ip_forward = 1 が抜けています。OSがパケットを受け取ったものの、「これ、僕宛てじゃないや……ポイっ」と捨ててしまっている状態です。
2. ルートテーブル(Route Table)の向き先が違う
プライベートサブネット側のルートテーブルで、インターネット向け(0.0.0.0/0)の送信先ターゲットが、NATインスタンスの「ENI ID」または「インスタンスID」に正しく向いているか確認しましょう。
3. セキュリティグループのインバウンド/アウトバウンド制限
NATインスタンス自体のセキュリティグループが、プライベートサブネットからのトラフィックを遮断していないか、また外のインターネットへの通信(ポート80や443など)を許可しているかも要チェックです。

—

まとめ

今回は、NATインスタンスにおける「送信元/宛先チェックの無効化」について、郵便配達の例えを交えながら解説しました。

  • マネージドではない自作NATルーターは、パケットの宛先や送信元を書き換える(偽装ではなく正当なルーティング業務を行う)
  • AWSのデフォルトのセキュリティ基盤は、書き換えられたパケットを「不正」とみなして破棄してしまう
  • そのため、AWS側に「このインスタンスはルーターです」と伝えるために、送信元/宛先チェックを無効化する必要がある

インフラやネットワークの仕組みは、一見すると複雑なルールの連続に思えますが、「パケットがどこから来て、どこに行き、誰が書き換えるのか」というストーリーを追っていくと、非常にロジカルでスッキリと理解できるようになります。

日々のインフラ運用やトラブルシューティングで「おや?」と思ったときは、ぜひ今回のパケットの旅を思い出してみてくださいね。それでは、快適なクラウドライフを!

コメント

タイトルとURLをコピーしました