Linuxネットワークの要塞化:nftablesによるマイクロセグメンテーション

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

内部ネットワークの保護:境界防御のその先へ

多くのセキュリティ設定は、中世の城に似ています。外壁は厚いものの、内部には門が一つもありません。パケットが一度境界のファイアウォールを通過してしまうと、内部ネットワークは制限のない状態(フリーフォーオール)になりがちです。私はトラフィック量の多いマルチティア環境を6ヶ月間管理してきましたが、この「城郭と堀(castle and moat)」戦略が大きなリスクであることを痛感しました。たった一つのNginxインスタンスが侵害されただけで、攻撃者にデータベースクラスター全体へのフリーパスを与えるべきではありません。

そこで私は、本番環境のスタックをnftablesを使用したホストレベルのセキュリティモデルに移行しました。その効果はすぐに現れ、安定性も抜群でした。マイクロセグメンテーションを導入することで、セキュリティロジックをワークロードに直接組み込むことができたのです。これはゼロトラストの核心である「決して信頼せず、常に検証する」、そして「通信をサービスが機能するために必要な最小限に厳格に制限する」という原則に従っています。

戦略の比較:従来のファイアウォール vs マイクロセグメンテーション

コマンドラインを触る前に、この哲学の転換を理解することが不可不可欠です。従来のアプローチは「エッジ(境界)」に焦点を当てますが、マイクロセグメンテーションは「個々のサービス」に焦点を当てます。

1. 境界型セキュリティ(従来の手法)

レガシーなモデルは、単一の侵入ポイントに依存しています。Web、App、Databaseなどの内部サービスは通常、同じVLAN内に配置され、それらの間の制限はほとんどありません。もし攻撃者がリモートコード実行(RCE)の脆弱性でWebサーバーを攻撃した場合、機密データ層まで一直線に進まれてしまいます。

2. ネットワーク・マイクロセグメンテーション(ゼロトラストの手法)

この手法では、すべてのサービスを「孤島」として扱います。たとえ2つのサービスが同じ物理サブネットを共有していても、特定のルールで許可されない限り通信はできません。nftablesは、これらのパケットをカーネルレベルでフィルタリングするための高パフォーマンスなフレームワークを提供します。古いiptablesよりも構文がクリーンで、リソース効率にも優れています。

本番環境で nftables が選ばれる理由

内部トラフィック制御をnftablesに切り替えることで、いくつかの技術的なメリットが得られます。ただし、チームが新しい構文を学ぶ必要はあります。

メリット

  • アトミックな操作: ルールセット全体を一度に置き換えることができます。これにより、ルールが一つずつ更新されるiptablesで発生していた競合状態(レースコンディション)が解消されます。
  • パフォーマンスの向上: カーネル内のより効率的な仮想マシンを利用します。10Gbpsリンクのような高スループット環境では、CPUオーバーヘッドの削減は大きな利点となります。
  • 可読性の高い構文: 自然な論理に近い言語体系です。セットやマップを使用してポート、IP、プロトコルを一つのルールにまとめることができ、50行のコードを5行に短縮できます。
  • ツールの統合: iptablesip6tablesebtablesを一つの合理化されたツールに統合します。

デメリット

  • 学習曲線: iptablesを10年以上使い続けてきたチームは、新しい思考モデルに慣れるまで数日かかるでしょう。
  • ツールの更新: 古い監視スクリプトやレガシーなIaCパイプラインがiptablesの出力を期待している場合、リファクタリングが必要になります。

本番環境対応のアーキテクチャ

私がこの環境をデプロイした際、長くて線形なルールリストは廃止しました。代わりに、設定を機能ごとのテーブルに整理しました。監視エージェントやデータベースノードなどのサーバーグループを管理するためにセット(sets)を使用し、システムの拡張を容易にしました。

ロジックの要は「デフォルト拒否(Default Deny)」ポリシーです。すべてをブロックし、特定のデータパスのみをホワイトリストに登録します。標準的な3層(3-tier)アプリの場合、フローは以下のようになります。

  • Web層: 外部からポート443を受け入れ、App層のポート8080と通信する。
  • App層: Web層からの8080を受け入れ、DB層のポート5432と通信する。
  • DB層: App層からの5432を受け入れ、それ以外にはどこにも接続しない。

ステップ・バイ・ステップ:ルールセットの構築

それでは、本番グレードのnftables設定を構築しましょう。まず、パッケージがシステムにインストールされていることを確認します。Debian/Ubuntuの場合はapt install nftables、RHEL系のシステムの場合はyum install nftablesを使用します。

1. 状態の初期化

クリーンな状態から始めます。SSH経由で作業している場合は注意してください。自分のIPアドレスを許可する前に、デフォルトポリシーをdrop(破棄)に設定しないでください。

# 現在のすべてのルールを消去
nft flush ruleset

2. テーブルとチェーンの定義

IPv4とIPv6の両方のトラフィックを扱うために、filterという名前のテーブルを作成します。次に、input、forward、outputの標準的なフックを定義します。

nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }

3. 必須トラフィックの処理

ループバックインターフェースは決してブロックしないでください。また、送信リクエストに対する応答パケットが戻ってこれるように、確立済みの接続を許可する必要があります。

# ループバックインターフェースを許可
nft add rule inet filter input iifname "lo" accept

# 確立済みおよび関連するトラフィックを許可
nft add rule inet filter input ct state established,related accept

4. セットによる階層の整理

セットはnftablesで最も強力な機能です。何十もの反復的なルールを書く代わりに、グループを定義します。これにより、サーバーが2台から200台に増えても、拡張は容易です。

# インフラストラクチャ用のセットを定義
nft add set inet filter web_servers { type ipv4_addr \; }
nft add set inet filter app_servers { type ipv4_addr \; }
nft add set inet filter db_servers { type ipv4_addr \; }

# 実際のIPアドレスをセットに追加
nft add element inet filter web_servers { 10.0.1.10, 10.0.1.11 }
nft add element inet filter app_servers { 10.0.2.50, 10.0.2.51 }
nft add element inet filter db_servers { 10.0.3.100 }

5. マイクロセグメンテーション・ロジックの適用

ここで制限を適用します。AppサーバーからDBサーバーへのアクセスは、PostgreSQLポート(5432)のみを許可します。

# SSHを管理用サブネット(例:VPNなど)に制限
nft add rule inet filter input ip saddr 192.168.100.0/24 tcp dport 22 accept

# Web層からApp層への8080ポート通信を許可(Appノードで実行)
nft add rule inet filter input ip saddr @web_servers tcp dport 8080 accept

# App層からDB層への5432ポート通信を許可(DBノードで実行)
nft add rule inet filter input ip saddr @app_servers tcp dport 5432 accept

6. 設定の永続化

ルールを保存しないと、再起動時に消失してしまいます。DebianやUbuntuでは、標準的な場所は/etc/nftables.confです。

nft list ruleset > /etc/nftables.conf
systemctl enable nftables
systemctl start nftables

長期的なメンテナンスと自動化

この構成を数ヶ月運用して分かったのは、監査が非常にシンプルになるということです。監査人から「どのサービスがデータベースにアクセスできるか」と聞かれたら、nft list set inet filter app_serversを実行するだけです。出力は明確で、推測の余地はありません。

大規模な環境では、これらのルールを手動で管理せず、AnsibleやTerraformに統合しましょう。中央のインベントリでIPセットを定義することで、マイクロセグメンテーションの更新を数百のノードに同時に適用できます。このアプローチはインフラストラクチャを堅牢にし、複雑な接続の網を、管理可能で文書化されたシステムへと変えてくれます。

Share: