なぜ「ベストエフォート」の接続では不十分なのか
私は過去6ヶ月間、本番環境でLinuxベースのゲートウェイを管理してきました。そこで学んだ重要なことは、VPNの信頼性は「障害時の挙動」にかかっているということです。WireGuardは高速でモダンですが、ネットワークの瞬断やISPのDHCP更新によってトンネルが切断されることがあります。ハードウェアレベルのロックがない場合、Linuxマシンは標準のルートにデフォルト設定されます。これにより、200ミリ秒以内に本物のIPとすべてのDNSクエリがISPに露出してしまいます。
このセットアップは、1つのパケットも漏らすことなく180日間の稼働を維持しました。私の目標は単なる「プライバシー」ではなく、システム全体の金庫(ボルト)を構築することでした。データがWireGuardトンネル内で暗号化されていない限り、マシン外に出ることはありません。本ガイドでは、隙間から何も漏れないようにするために私が使用している正確なファイアウォールロジックを解説します。
ギャップ:アプリケーション対ファイアウォールのロジック
多くのユーザーはGUIアプリの「キルスイッチ」トグルを頼りにしていますが、これらはしばしばリアクティブ(事後対応的)です。セキュリティを向上させる第一歩は、それらがどのように失敗するかを理解することです。
1. ソフトウェアベースのキルスイッチ
商用VPNクライアントは通常、VPNプロセスを監視しています。デーモンがクラッシュすると、アプリがルーティングテーブルを更新しようとします。問題は、「漏洩ウィンドウ」が存在することです。トンネルが失敗してからソフトウェアが反応するまでの数ミリ秒の間に、OSがプレーンテキストのデータを漏洩させる可能性があります。これは負けたくないレースコンディションです。
2. カーネルレベル(iptables)の強制
私はプロアクティブ(先回り的)な姿勢を好みます。失敗を待つのではなく、Linuxカーネルの基本ルールを変更します。デフォルトポリシーを DROP に設定し、VPNに必要な特定の暗号化トラフィックのみをホワイトリストに登録します。トンネルが壊れた場合、トラフィックは壁に突き当たります。壁は常にそこにあるため、反応時間は必要ありません。
本番環境での6ヶ月運用から得られた教訓
この方法でネットワークを要塞化するには、いくつかのトレードオフが伴います。テスト期間中に気づいた点は以下の通りです。
- メリット:
- 漏洩ウィンドウがゼロ: 「DROP」がデフォルトであるため、再接続中にデータが「誤って」外に出ることはありません。
- 静かな保護: トレイで重いGUIアプリを動かし続ける必要なく、バックグラウンドで動作します。
- 強固なDNS: すべてのポート53トラフィックをトンネル経由に強制することで、ISPによるスヌーピングを完全に阻止します。
- 苦労した点:
- 設定のオーバーヘッド: コマンドラインと基本的なネットワーキングに慣れている必要があります。
- SSHロックアウト: リモートVPSで作業している場合、スクリプトの1つのタイポ(打ち間違い)で即座に接続が切断されます。
- 静的なルール: VPNプロバイダーがサーバーIPを変更した場合、スクリプトを更新する必要があります。
ブループリント:WireGuard + iptables
この構成では、Ubuntu、Debian、FedoraなどのLinuxディストリビューションの業界標準である iptables を使用します。また、IPv6を完全に無効化します。ほとんどのVPNはいまだにIPv6トラフィックを漏洩させており、Linuxシステムにおける匿名化解除の一般的な「バックドア」となっています。
ロジックは厳格な階層に従います:
- デフォルトですべての送受信トラフィックをブロック。
- システム内部用にローカルループバックを許可。
- 物理インターフェース上で暗号化されたVPNハンドシェイク用に1つの特定の「穴」を許可。
- それ以外のすべては自由に流れることを許可するが、
wg0インターフェース経由のみに制限。
実装:ステップバイステップの要塞化
ステップ 1: IPv6漏洩を阻止
IPv6を運任せにせず、/etc/sysctl.conf に以下の行を追加してカーネルレベルで無効化します:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
sudo sysctl -p を実行して反映させます。
ステップ 2: ネットワーク情報の収集
WireGuardの設定(通常は /etc/wireguard/wg0.conf)で以下の値を確認します:
- Endpoint IP: VPNサーバーのリモートアドレス。
- VPN Port: 通常は 51820。
- Interface Name:
ip route show defaultでアクティブなネットワークカード(例: eth0 または wlan0)を確認します。
ステップ 3: キルスイッチ・スクリプト
手動ミスを防ぐためにスクリプトを使用します。vpn-killswitch.sh を作成し、変数を調整してください:
#!/bin/bash
# 設定
VPN_SERVER_IP="1.2.3.4"
VPN_PORT="51820"
PHYS_IF="eth0"
WG_IF="wg0"
# 1. すべてをリセット
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
# 2. 確立済みのトラフィックを許可 (SSHから締め出されないために重要)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 3. ループバックとSSHをホワイトリストに登録
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
# 4. ロックダウンポリシーを設定
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
# 5. 「VPNの穴」: 暗号化トンネルの接続を許可
iptables -A OUTPUT -p udp -d $VPN_SERVER_IP --dport $VPN_PORT -o $PHYS_IF -j ACCEPT
# 6. 「グリーンゾーン」: トンネル内のすべてのトラフィックを許可
iptables -A OUTPUT -o $WG_IF -j ACCEPT
iptables -A INPUT -i $WG_IF -j ACCEPT
ステップ 4: 永続化
標準の iptables ルールは再起動後に消失します。iptables-persistent を使用して永続化させます:
sudo apt update && sudo apt install iptables-persistent
sudo netfilter-persistent save
防御のテスト
検証が重要です。まず、インターネットアクセスがあることを確認します。次に、トンネルを停止します:
sudo wg-quick down wg0
ping google.com を試します。即座に “Operation not permitted”(操作は許可されていません)というエラーが表示されるはずです。もしpingが反応したり解決したりする場合、ルールが機能していません。DNSについて100%確信を得るには、ブラウジング中に次のコマンドを実行します:
sudo tcpdump -i eth0 udp port 53
もし eth0 上にトラフィックが見える場合、漏洩しています。正常なセットアップでは、ブラウジング中もこのコマンドは完全に沈黙しているはずです。すべてのクエリは不可視であり、WireGuardのUDPパケットの中に包まれているからです。
最終的な結論
Linuxネットワーキングは、明示的な制御に報いてくれます。自動化は便利ですが、iptables はGUIの「キルスイッチ」では到達できないレベルの確実性を提供します。私のセットアップは、プレーンテキストのデータを1バイトも漏らすことなく、数十回のISPの微細な停止に対応しました。設定には10分かかりますが、それによって得られるセキュリティは、あなたのデジタルプライバシーに対する永続的なアップグレードとなります。

