【実務・中級編】 ネットワークACL(NACL)によるサブネットレベルのステートレス制御 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

現場でインシデント対応をしていると、「セキュリティグループ(SG)があるからNACLはデフォルト(全許可)でいいや」という設計に何度出会うことか。残念ながら、それは「玄関の鍵は閉めたが、庭の柵は取り払ったまま」と言っているのに等しい。

今日は、防御の「最後の一線」であり、かつ多くのエンジニアがその難解さから敬遠する「ネットワークACL(NACL)」について、実戦的な話をしよう。

なぜセキュリティグループだけでは不十分なのか

SGは「ステートフル」だ。許可した通信に対する戻りのパケットは、ルールに関係なく自動で通してくれる。便利だが、それゆえにミスも起きやすい。

対してNACLは「ステートレス」だ。往路と復路の両方を明示的に制御しなければならない。一見面倒だが、これが最強の防御になる。例えば、攻撃者がサーバーの脆弱性を突き、内部から外部へ踏み台として通信を試みた際、SGでインバウンドを絞っていても、アウトバウンドをNACLで制限していれば、攻撃者のC2サーバーとの通信を物理的に遮断できる。

ステートレス設計の悪夢を回避する計算式

NACLのルールは番号順に評価される。ここでハマるのが「エフェメラルポート」だ。クライアントがサーバーと通信する際、OSは動的に1024〜65535番のポートを割り当てる。ここを考慮しないと、SSHすら通らなくなる。

実務で使うべき鉄壁のNACL設計(AWS例)

以下は、Webサーバーを配置するサブネットの推奨設定だ。

| ルール番号 | タイプ | プロトコル | ポート範囲 | 送信元/送信先 | 許可/拒否 |
| :— | :— | :— | :— | :— | :— |
| 100 | HTTP(80) | TCP | 80 | 0.0.0.0/0 | 許可 |
| 110 | HTTPS(443) | TCP | 443 | 0.0.0.0/0 | 許可 |
| 120 | エフェメラル | TCP | 1024-65535 | 0.0.0.0/0 | 許可 |
| 32767 | すべてのトラフィック | すべて | すべて | 0.0.0.0/0 | 拒否 |

重要: アウトバウンド側にも、同様に「エフェメラルポート(1024-65535)」を許可するルールを入れないと、サーバーからの外部API呼び出しやOSのアップデートすら失敗する。

攻撃者の視点:ポートスキャンと「戻りパケット」

攻撃者は、あなたのサーバーがどのポートを開けているか、あるいはどこまで通信できるかを執拗に探る。NACLで不要なポートを明示的に「拒否」または「無視(暗黙の拒否)」しておくことで、ポートスキャンに対するレスポンスを返さず、存在感すら隠すことができる。

サーバーOS側での防御(Linux: iptables連携)

NACLはネットワーク境界での防御だが、OS内部では iptables や nftables でさらに固める。以下は、怪しい外部IPからの接続を拒否するPythonベースの自動スクリプトの断片だ。

import subprocess

def block_malicious_ip(ip_address):
    """
    特定のIPからの不審な挙動を検知した場合に、iptablesで遮断する
    ※ root権限での実行が前提
    """
    try:
        # すでに拒否設定があるか確認
        check = subprocess.run(["iptables", "-C", "INPUT", "-s", ip_address, "-j", "DROP"], 
                               capture_output=True)
        if check.returncode != 0:
            # 拒否ルールを追加
            subprocess.run(["iptables", "-A", "INPUT", "-s", ip_address, "-j", "DROP"], check=True)
            print(f"IP: {ip_address} をブロックしました。")
    except Exception as e:
        print(f"エラーが発生しました: {e}")

# 運用ログからレートリミット超過などを検知して呼び出す想定
block_malicious_ip("192.0.2.1")

実務上のアドバイス:ログのない環境は「目隠し」と同じ

NACLの設定を誤ると、通信がどこで遮断されたのか原因究明が非常に困難になる。

1. VPCフローログを必ず有効化すること: 通信が「REJECT」された場所を特定するために必須だ。
2. まず「全許可」から段階的に絞る: 最初から完璧を目指すと必ず事故る。最初は広めに許可し、フローログを見ながら「本当に必要な通信」だけを残して番号を若くしていくのがプロのやり方だ。
3. 踏み台サーバーの切り離し: 管理用アクセスはNACLで「特定の管理用VPN IPレンジ以外は全拒否」にする。SGが突破されても、NACLという強固な壁が残る。

セキュリティとは、単なる設定の羅列ではない。「何を通し、何を拒絶するか」という、君自身の哲学を反映させたインフラ構成のことだ。NACLという「最後の砦」を使いこなし、攻撃者が泣いて帰るようなセキュアな環境を構築してほしい。

何か疑問があれば、いつでも聞いてくれ。現場の泥臭い知見で答えるよ。

コメント

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