「専用線だから安全」は幻想だ:VPNとDirect Connectを狙う中間者攻撃の現実と要塞化
現場で「Direct ConnectやExpressRouteを使っているから、暗号化は不要だよね?」という言葉を耳にするたびに、私は背筋が凍る思いがする。物理回線が専用線であっても、ルーターのコンフィグミスやキャリア網内でのフラッピング、あるいはクラウド側のエンドポイント設定の甘さは、そのまま「暗号化されていない社内LANを世界中に解放している」のと同義だ。
今日は、インフラエンジニアが陥りやすい「閉域網の罠」と、それを確実に封じ込めるための要塞化手法について、泥臭い知見を共有しよう。
—
1. なぜ「専用線」が突破されるのか(PoC的視点)
攻撃者が狙うのは、通信の終端点であるVPNゲートウェイやルーターの「設定の綻び」だ。
もし貴方のチームが、AWS Direct ConnectやAzure ExpressRouteを経由して、IPsecなしで「平文のHTTP」や「MySQL(デフォルトポート)」を流しているとしたら、攻撃者はこう動く。
1. BGPハイジャック/経路注入: クラウドとの接続ポイントであるルーターに対し、不正な経路情報を広告させる。
2. 中間者攻撃 (MitM): 物理的な専用線の中に侵入できなくとも、接続先の仮想ルーターや仮想スイッチの脆弱性を突き、トラフィックをミラーリング(TAP)する。
3. パケットキャプチャ: 平文で流れるDBのクエリや認証トークンを丸裸にする。
「物理的な専用線だから盗聴は不可能」という前提は、現代のクラウド環境では通用しない。「通信経路は常に汚染されている」というゼロトラストの原則を、インフラレベルに落とし込む必要がある。
—
2. VPNゲートウェイ・IPsecの要塞化設定
VPNトンネルを構築する際、デフォルト設定のまま放置するのは「鍵のかかっていない玄関」を放置するのと同じだ。特に、古臭い暗号スイート(3DESやSHA-1)は、今のコンピューティングパワーなら数分で突破される。
強固なIPsec設定(StrongSwan / Linuxルーター用)
以下は、現代の基準で最低限守るべきipsec.confの抜粋だ。
# /etc/ipsec.conf の推奨設定
conn vpn-to-cloud
# 暗号化アルゴリズムを最新に限定する
# AES-256-GCM は認証付き暗号で、安全性と高速性を両立する
ike=aes256gcm16-sha384-modp4096!
esp=aes256gcm16-sha384-modp4096!
# Perfect Forward Secrecy (PFS) を有効化
# 万が一、長期鍵が漏洩しても過去の通信が解読されるのを防ぐ
keyexchange=ikev2
ikelifetime=24h
keylife=1h
pfs=yes
# 認証は必ず証明書ベースにする(PSKは論外)
authby=pubkey
leftcert=gatewayCert.pem
rightid=@cloud-gateway.example.com
ポイント:
aes256gcm16: GCMモードを使うことで、暗号化と認証を同時に行う。これにより、パケット改ざん攻撃をレイヤーレベルで無効化できる。modp4096: Diffie-Hellmanグループに4096bitを選択し、将来的な量子計算耐性を少しでも高める。
—
3. アプリケーション層での最後の砦:TLS 1.3の強制
インフラでIPsecを張るのが大前提だが、さらにアプリケーション側でも防御を固めるのがプロの流儀だ。たとえVPNがバイパスされたとしても、アプリ側で平文を許さない構成にしておく。
NginxでのTLS 1.3強制設定
Web APIを公開しているサーバーでは、古いTLS(1.0/1.1)を拒絶し、TLS 1.3のみを許可する設定をnginx.confに記述する。
# /etc/nginx/nginx.conf
server {
listen 443 ssl http2;
# 強固なTLSプロトコルのみを許可
ssl_protocols TLSv1.3;
# 弱い暗号スイートを排除
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# HSTSを有効化し、ブラウザに強制的にHTTPS接続させる
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}
—
4. 運用エンジニアへの提言:自動化による検証
「設定したつもり」が一番怖い。私は、定期的にnmapやopensslコマンドを叩いて、意図しない暗号化スイートが通っていないかを確認するスクリプトをCI/CDパイプラインに組み込んでいる。
Pythonによる暗号化確認スクリプト(スニペット)
import ssl
import socket
def check_tls_version(hostname, port=443):
# TLS 1.2以下での接続を試み、失敗することを確認する
context = ssl.create_default_context()
context.minimum_version = ssl.TLSVersion.TLSv1_3
try:
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print(f"Success: {hostname} supports {ssock.version()}")
except ssl.SSLError:
print("Failure: Weak TLS version is still accepted or misconfigured.")
# 運用環境のエンドポイントに対して実行
# check_tls_version("api.your-company.com")
最後に:セキュリティは「性悪説」で設計せよ
VPNゲートウェイの管理画面を開くとき、あるいはDirect Connectの回線構成図を引くとき、常にこう自問自答してほしい。「もし今、この経路を敵対勢力が傍受していたら、私のデータは守れるか?」と。
インフラの要塞化とは、単なる設定変更の積み重ねではない。ネットワークの設計思想を「信頼」から「検証(Verification)」へとシフトさせることだ。この記事が、貴方のチームの防御力を一段引き上げる一助となれば幸いだ。
何か具体的なトラブルや、複雑なマルチクラウド構成での実装に悩んでいるなら、いつでも相談してほしい。エンジニア同士、泥臭く手を動かして守り抜こう。
コメント