IPsec「トランスポートモード」の正体:ホスト間暗号化のリアルと現場の作法
おい、そこの君。APIのパフォーマンスチューニングやコンテナのオーケストレーションに夢中になっているところ悪いが、ちょっと手を止めてネットワークの深層を覗いてみないか?
クラウド全盛の今、「ゼロトラスト」という言葉が踊り、境界防御の時代は終わったと言われている。しかし、クラウドのVPC間ピアリングであれ、オンプレミスのレガシーなサーバー群であれ、パケットが物理的・論理的な荒野を駆け抜けるとき、データを守る最後の砦となるのは、やはりIPsecやTLSといった暗号化技術だ。
特にインフラエンジニアやバックエンドエンジニアを悩ませるのが、IPsecの2つのモード――「トンネルモード」と「トランスポートモード」の使い分けだ。
拠点間を結ぶルーター同士の接続であれば、迷わずトンネルモードを選べばいい。しかし、「ホストとホストの間で直接、アプリケーションのペイロードだけを暗号化したい」「すでにTLSを使っているが、トランスポート層以下でも厳格な暗号化と完全性保証を強制したい」という要件に直面したとき、君はどちらを選ぶべきか?
今回は、多くのエンジニアがその仕組みや適用シナリオを曖昧にしがちな「IPsec トランスポートモード」に直球で焦点を当て、パケットの挙動から実際の構築・デバッグ手順まで、現場の泥臭い知見を交えて徹底的に解説しよう。
—
1. トランスポートモードの構造:トンネルモードとの決定的違い
まず、IPsecの基本原理のおさらいからだ。IPsecはOSI参照モデルの「ネットワーク層(レイヤー3)」で動作し、IPパケット単位で暗号化と認証を行う。これによって、上位のTCPやUDP、さらにはその上のHTTPやgRPCといったアプリケーション層のプロトコルを意識することなく、セキュアな通信路を作り出せるのが最大の強みだ。
このIPsecには、パケットをカプセル化する方式として以下の2つが存在する。
1. トンネルモード(Tunnel Mode)
- 元のIPパケット全体を新しいIPヘッダーで包み込む(カプセル化)。
- 拠点間(ルーター対ルーター)の接続で標準的に使われる。
2. トランスポートモード(Transport Mode)
- 元のIPヘッダーはそのまま活かし、IPヘッダーと上位プロトコル(TCP/UDP等)の間にIPsecヘッダーを挿入する。
- 「上位層のペイロードのみ」を保護する。ホスト間(エンドツーエンド)の通信で真価を発揮する。
なぜトランスポートモードなのか?
図解してみよう。通常のIPv4パケットは [元IPヘッダー][TCPヘッダー][データ] という構造をしている。これをトランスポートモードで保護すると、以下のようになる。
+-------------------+--------------------+------------------+------------------+
| 元IPヘッダー | IPsecヘッダー | TCPヘッダー | データ |
| (送信元/宛先IP維持) | (AH または ESP) | (暗号化 or 保護) | (暗号化対象) |
+-------------------+--------------------+------------------+------------------+
ここで重要なのは、「IPヘッダーが書き換わらない」という点だ。
トンネルモードでは外側に全く新しいIPヘッダーが付与されるため、ルーター間の中継において元のルーティング情報が隠蔽される。しかしトランスポートモードでは、送信元および宛先のIPアドレスは元のパケットのものがそのまま維持される。
そのため、ルーター同士ではなく、「アプリケーションが稼働するサーバー(ホスト)同士」が直接IPsecのセキュリティアソシエーション(SA)を終端するシナリオにおいて、ルーティングの複雑化を避けつつ暗号化を適用できるという強力なメリットが生まれる。
—
2. 適用シナリオ:どんな現場でトランスポートモードを採用すべきか?
「じゃあ、すべてのホスト間通信をトランスポートモードで暗号化すればいいのでは?」と思ったそこの君。甘い。現場には現場の制約がある。
実務において、トランスポートモードがピタリとハマる代表的な適用シナリオを3つ挙げよう。
シナリオA:ホスト間(End-to-End)の厳格なゼロトラスト通信
同一セグメント内、あるいは同一VPC内であっても、「コンプライアンス要件により、サーバー間の生トラフィック(平文)を一切流してはならない」という厳しい金融や医療系のシステムがある。
この場合、アプリケーション側でTLSを実装しきれないレガシーなバッチ処理や、内部で飛び交うDBのネイティブプロトコル(PostgreSQLのTDSやMySQLのビナログ同期など)をまるごと保護するために、OSのIPsecスタック(LinuxのlibreswanやstrongSwanなど)を用いてトランスポートモードを張る。
シナリオB:L2TP/IPsec等のリモートアクセスVPN(クライアント端末の保護)
社外のカフェや自宅から社内ネットワークへ接続する際、L2TP over IPsecのデータ転送部分(ESP)にはトランスポートモードが使われることが多い。クライアント端末(ホスト)とVPNゲートウェイの間で、端末の仮想IPと社内リソース間の通信を直接保護するのに適している。
シナリオC:すでにあるルーティング設計を崩したくない環境
もしここでトンネルモードを使ってしまうと、新たな仮想IPトンネルインターフェース(VTIなど)を生やし、ルーティングテーブルを書き換え、経路制御の設計をやり直す必要がある。
トランスポートモードであれば、既存のIPアドレス体系やルーティングを一切変更せず、ポリシーベース(あるいはルートベース)で特定の通信だけを暗号化の対象にねじ込むことができる。
—
3. 実践!Linux環境(strongSwan)でのトランスポートモード構築
百聞は一見にしかず。実際にLinux(Ubuntu Server等)環境で、2台のホスト間に強固なトランスポートモードのトンネルを構築する手順をハンズオン形式で解説しよう。
今回は、IPsecのプロトコルとして暗号化と完全性を提供する ESP(Encapsulating Security Payload) のトランスポートモードを採用する。
サーバー構成
- Host A (Alice):
192.168.1.10 - Host B (Bob):
192.168.1.20 - ツール:
strongSwan(現代のLinuxにおけるデファクトスタンダード)
—
ステップ1: インストールと事前準備
両方のホストで strongSwan をインストールする。
# Ubuntu / Debian系の場合
sudo apt update
sudo apt install strongswan libcharon-extra-plugins -y
—
ステップ2: 共通の事前共有鍵(PSK)の設定
今回はシンプルかつ確実な事前共有鍵(Pre-Shared Key)認証を用いる。
/etc/ipsec.secrets を両方のホストで編集し、秘密の文字列を共有する。
# /etc/ipsec.secrets
192.168.1.10 192.168.1.20 : PSK "SuperSecretKeyForOurZeroTrustNetwork202X!"
*(※セキュリティ上の注意:パーミッションは必ず 600 に絞っておくこと。chmod 600 /etc/ipsec.secrets を忘れないように!)*
—
ステップ3: IPsecコネクションの設定 (ipsec.conf)
これがキモだ。設定ファイル /etc/ipsec.conf に、明示的に type=transport を指定する。
両方のホストで以下の設定を記述する(Host A側の例)。
# /etc/ipsec.conf の設定例
config setup
uniqueids = yes
conn host-to-host-transport
# IKEのバージョンは強固なIKEv2を使用
keyexchange = ikev2
# 【最重要】ここでトランスポートモードを指定!
type = transport
# 接続が切れた場合の自動再接続
auto = start
# 自ホストの設定
left = 192.168.1.10
leftid = 192.168.1.10
# 相手ホストの設定
right = 192.168.1.20
rightid = 192.168.1.20
# 暗号アルゴリズムの指定(現代の標準:AES-GCMによる認証付き暗号)
ike = aes256gcm16-prfsha384-ecp384!
esp = aes256gcm16-ecp384!
ここで指定している aes256gcm16 は、暗号化とデータ改ざん検知(完全性)を同時に高速処理できるGCMモードだ。実務では、暗号スイートの選定において「枯れた技術」ではなく「現代の推奨暗号(AES-GCMやChaCha20-Poly1305など)」を選ぶのがプロの作法である。
—
ステップ4: サービスの起動と接続確認
設定を反映させ、strongSwan(Charonデーモン)を再起動する。
sudo systemctl restart strongswan-starter
# あるいは systemdベースなら
sudo systemctl restart ipsec
さあ、ステータスを確認してみよう。
sudo ipsec status
コンソールに ESTABLISHED という文字が出れば、IKE(Internet Key Exchange)のネゴシエーションが無事に成功し、SA(セキュリティアソシエーション)が確立された証拠だ。
—
4. 現場のトラブルシューティングとデバッグ手法
「設定は完璧なはずなのに、パケットが通らない……」
ネットワークエンジニアなら誰もが絶望するこの瞬間。トランスポートモード特有のハマりどころと、現場で使えるデバッグの流儀を授けよう。
1. MTU(Maximum Transmission Unit)問題の罠
トランスポートモード特有のトラブルとして非常に多いのが「フラグメンテーションに起因する通信途絶」だ。
トンネルモードであれば新しいIPヘッダー分のオーバーヘッドを考慮して外側でうまいことやってくれるが、トランスポートモードでは元のIPパケットの中にIPsecヘッダーが割り込む。
もしホスト間の物理ネットワークのMTUが 1500 で、アプリケーションがギリギリのサイズ(1500バイト)のパケットを送り出そうとすると、IPsecヘッダー(ESPのトレーラー等を含む)の分だけサイズがオーバーし、フラグメンテーションが発生する。途中のルーターが Don't Fragment (DF) ビットを見てパケットをドロップし、かつICMP(Destination Unreachable: Fragmentation Needed)がファイアウォールでブロックされている場合、「なぜか特定の大きいサイズのリクエストだけがタイムアウトする」という悪夢のような現象が起きる。
【解決のTips】
- インターフェースのMTUを少し下げる(例:
1400や1420に設定する)。 - パム・マングリング(MSS Clamping)を適切に設定するか、IPsecのセキュリティポリシーでパケットサイズを調整する。
2. パケットキャプチャによる現実の直視
口でゴチャゴチャ言うより、パケットを見れば真実は一目瞭然だ。tcpdump を使って、パケットが実際にどう流れているかを観察しよう。
Host A上で以下のコマンドを実行し、ICMPや適当なTCP通信を流してみる。
sudo tcpdump -i eth0 -nn -vvv "host 192.168.1.20"
もしトランスポートモードが正常に機能していれば、通信プロトコルとして通常の TCP や UDP ではなく、ESP プロトコル(プロトコル番号 50)のパケットが流れていることが確認できるはずだ。
もしここで平文のTCPパケットがそのまま流れていたら、IPsecのポリシー(SPD: Security Policy Database)がマッチしていない、あるいはファイアウォール(iptables / nftables / security group)でESPトラフィック(UDP 500/4500ポートのIKE、およびESPプロトコル自体)がブロックされている可能性が高い。
# ファイアウォールでESPが許可されているか確認する例 (iptables)
sudo iptables -L -v -n | grep esp
—
まとめ:ネットワークの根底にある「信頼」をコードでデザインする
ここまで、IPsecトランスポートモードの内部構造から、具体的な設定例、そして現場特有のトラブルシューティングまでを一気通貫で解説してきた。
最後に、シニアエンジニアとして君に伝えたいことがある。
「ゼロトラスト」という言葉がどれだけバズろうとも、最終的にパケットを運び、暗号化し、完全性を担保しているのは、OSのカーネルが持つ堅牢なネットワークスタックや、枯れた信頼性の高いプロトコルたちだ。
アプリケーション層でのセキュアな設計はもちろん重要だが、それだけでは防げないネットワーク層の脅威に対して、トランスポートモードのような技術を適切に選択・実装できるスキルこそが、インフラとアプリケーションの境界線を知り尽くした「真に信頼されるエンジニア」の証となる。
さあ、次のデプロイでは、ただコードを書くだけでなく、その足元を支えるパケットの息吹にまで意識を向けてみてほしい。君のインフラストラクチャは、もっと強靭になるはずだ。
コメント