クラウドの「出口」が悲鳴を上げる時:NATゲートウェイを守るための異常トラフィック検知と防御戦略
「なぜかAPIのレスポンスが極端に遅い」「突然、NATゲートウェイ(NATGW)のメトリクスが跳ね上がった」。そんな深夜の呼び出しで冷や汗をかいた経験はありませんか?
AWSやGCPといったクラウド環境において、NATGWはインターネットへの唯一の窓口です。しかし、この「窓」は無制限に開かれているわけではありません。今回は、アプリケーションの不適切な実装や、あるいは悪意ある攻撃によって引き起こされる「NATGWのパフォーマンス低下と異常トラフィック」という泥沼に、SREの視点から切り込んでいきます。
なぜNATゲートウェイでボトルネックが発生するのか?
NATGWは、RFC 2663で定義されるNAPT(Network Address Port Translation)という仕組みで動いています。プライベートサブネット内の膨大なリクエストを、たった一つのパブリックIP(Elastic IP)のポートへとマッピングするわけです。
ここで注意すべきは「ポートの枯渇」です。
1. 接続の乱立: curlやrequestsで外部APIを叩く際、接続先IPとポートの組み合わせ(Tuple)が同じ場合、NATGWは同じ変換エントリを使い回せますが、宛先がバラバラであれば、その分だけソースポートを消費します。
2. コネクションの残留: TIME_WAIT状態のTCPコネクションが大量に残ると、NATGWはそれらを「使用中」とみなします。
3. スループットの限界: AWSのNATGWは帯域幅が最大100Gbpsまで自動スケールしますが、急激なトラフィック増には追いつけず、パケットロスが発生します。
リアルな現場で見かける「アンチパターン」
例えば、Pythonのrequestsライブラリをデフォルト設定で使い、ループの中で毎回コネクションを生成していませんか?
# 悪い例:毎回コネクションを張って切断するため、NATのソースポートを即座に消費する
import requests
for _ in range(1000):
# 毎回TCPハンドシェイクが発生し、NATのポートを占有する
response = requests.get("https://external-api.example.com/data")
これを防ぐには、requests.Session()を使ってKeep-Aliveを有効にすることが鉄則です。コネクションを再利用することで、NATGWの負荷は劇的に下がります。
異常トラフィックの検知:VPCフローログとGuardDuty
NATGWを経由した通信が「攻撃」なのか「実装ミス」なのかを見極めるには、ログを読み解く力が必要です。
1. VPCフローログによる「異常」の兆候
VPCフローログを確認する際、注目すべきはactionがREJECTになっているものや、特定の宛先IPへの大量の通信です。
以下は、AWS CLIを使って特定のIPへのリクエスト数が多いインスタンスを特定するための思考プロセスです。
# Athenaでフローログをクエリし、宛先IPごとのリクエスト数を集計する
SELECT dstaddr, COUNT(*) as connection_count
FROM vpc_flow_logs
WHERE action = 'ACCEPT'
GROUP BY dstaddr
ORDER BY connection_count DESC
LIMIT 10;
2. GuardDutyによる自動検知
自分でログを監視するのも限界があります。ここで頼りになるのが Amazon GuardDuty です。特に以下の検知タイプは、NATGWの先で起きている異常を即座に教えてくれます。
UnauthorizedAccess:EC2/PortProbeUnprotectedPort: インスタンスが外部の不審なポートをスキャンしている。Trojan:EC2/DNSDataExfiltration: インスタンスがバックドアを通じてデータを外部へ流出させている。
攻撃を制限する:実務的な防御策
もし攻撃や異常なAPIコールが検知された場合、どう対応すべきでしょうか?「NATGWを止める」という選択肢はビジネス上あり得ません。
ネットワークACLとセキュリティグループの使い分け
NATGW自体には直接的なレートリミット設定はできませんが、送信元であるEC2インスタンスの「外向きの口」を絞ることは可能です。
- 送信先制限: NATGWを通す必要のない社内リソースや特定のAPIエンドポイントに対しては、VPCエンドポイント(Interface型)を使い、NATGWを経由させない構成に切り替えます。
- レート制限:
- アプリケーションレベルでのサーキットブレーカー(
Resilience4jやPollyなど)を導入し、外部APIへの同時接続数を制限します。 - OSレベルの
iptablesやnftablesで、特定の外部IPへの出力パケットを制限します。
# 特定の悪意あるIPへの接続をiptablesでDROPする例
sudo iptables -A OUTPUT -d 192.0.2.1 -j DROP
最後に:SREとしての心構え
NATGWのトラブルは、多くの場合「アプリケーション層の不適切な接続管理」か「セキュリティインシデント」の二択です。
パケットがNATGWを通り抜けるとき、そこにはTCPの3ウェイ・ハンドシェイクがあり、ポートの変換という重い処理が行われています。この挙動を常に頭の中に描き、「自分の書いたコードがNATGWという共有リソースにどう影響を与えるか」を想像できるようになると、皆さんのインフラは一段と強固なものになります。
インフラは「繋がって当たり前」の世界です。しかし、その「当たり前」の裏側で、NATGWは今日も膨大なパケットを捌き続けています。ぜひ、メトリクスを眺めるだけでなく、フローログという「通信の履歴書」を読み解く習慣を付けてみてください。それが、最強のSREへの第一歩です。
コメント