UFWのキルスイッチがVPNを遮断?ピアを許可しよう
外向き拒否のルールがトンネルのハンドシェイクを落としています。ufw enable の前に追加するピアの例外ひとつが、ポリシーをキルスイッチに変えます。
チェックリストどおりに進めました。外向きを拒否し、トンネルを許可し、ufwを有効化した。ところがクライアントはハンドシェイクで待ち続けて接続しないか、接続してもページが読み込まれません。どちらの失敗も同じ隙間から来ています。トンネルが存在することを許すルールが欠けているのです。トンネルはパケットが出ていくインターフェースではないからです。
tun0への許可が最初は何にも一致しない理由
tun0はセッションができた後にクライアントが作ります。そのセッションを組み立てるデータグラムは、プロバイダのポート1194宛ての普通のUDPパケットで、物理的な送信元アドレスのままwlan0かeth0から出ていきます。allow out on tun0 は外向きインターフェースがtun0の通信にしか一致しないので、ハンドシェイクの間は何にも一致しません。
その上にdefault deny outgoing を置くと、インターフェースが現れる前に外側のパケットが捨てられます。クライアントは再試行し、タイムアウトし、TLSやハンドシェイクの失敗を報告します。その結果、人々は証明書やMTUを探し回るのに、ファイアウォールは黙って接続を食べています。通信を閉じ込めるはずのルールが、その通信の閉じ込めを妨げているのです。
反射的な修正は漏れを恒久化します。sudo ufw allow out on wlan0、あるいは既定を許可に戻すと、トンネルは上がりますが、マシンはキルスイッチを失います。次にトンネルが落ちれば、すべてが物理アダプター経由で再開します。私はまさにその二つの編集で半日を失いました。自分が実際にどのパケットを絞り込んでいるのかを理解するまで。
二組のパケットに必要なもの
通信は二回、二つの形でファイアウォールを通過します。内側のパケットはトンネルのアドレスからtun0を通って外へ出ます。外側のパケットは物理アドレスからピアへ向かい、回線上で見えるのはこれだけです。形ごとに一つのルールです。
sudo ufw allow out on tun0
sudo ufw allow out to 203.0.113.10 port 1194 proto udp
sudo ufw allow out to 203.0.113.10 port 443 proto tcp comment 'tcp fallback'
アドレスとポートは自分のプロファイルのものに置き換えてください。WireGuardのピアは通常51820/udpで応答します。TCP 443を通るOpenVPNプロファイルは代わりにそのポートが要ります。細部は違っても形は同じです。どちらのルールも狭く、合わせて、トンネルが落ちている間にマシンが到達できる唯一の宛先を定義します。
順序は第二の神話です。生のiptablesならチェーンを上から下へ読み、どのルールが勝つかを考えます。ufwは入力した一覧を薄く包むものではありません。ルールを独自のチェーンにコンパイルし、挿入位置を選びます。ufw status はufwの順序で表示し、あなたの順序ではありません。ルールが無視されているように見えたら、書き換える前にufw show added とiptables -S | grep ufw からコンパイルされた集合を比べてください。
例外は一アドレスの幅にとどめるべきです
ピアのルールは、クライアントが接続するアドレスを名指ししている間だけ正しいものです。プロバイダはエンドポイントを回転させ、ホスト名を解決するプロファイルはDNSの変更に従って新しいアドレスへ移る一方、ルールは古いアドレスを指したままになります。何ヶ月も動いていたトンネルが上がらなくなったら、何かを広げる前に、ルールのアドレスとクライアントが探しているアドレスを比べてください。
サブネット全体へ、あるいはポート1194のすべての宛先へ広げると、ポリシーは穴あきのファイアウォールに戻ります。例外こそがキルスイッチです。一度広げてしまえば、切るものが残りません。一つのアドレスに保ち、どのプロファイルとプロバイダに属するかを書いたコメントを残してください。半年後にはそのアドレスは恣意的に見えるからです。
名前解決には専用の行が必要です。問い合わせはトンネルができる前に、物理インターフェース上で行われます。そのため厳格な外向き拒否ポリシーでは、クライアントが自分のサーバーを見つけられなくなります。リゾルバのアドレスへのポート53を許可するか、一度だけ解決してアドレスをプロファイルに固定してください。すべてのインターフェースでDNSを許可するのは決断であって、既定値ではありません。
トンネルが必要になる前にポリシーを組み立てる
ufw enable はポリシー全体を一度に適用してチェーンを再読み込みします。稼働中のファイアウォールで既定ポリシーを変えても再読み込みされます。ufwのマニュアル は、これがSSHのような既存の接続を落とす可能性があると警告しています。だからコマンドはこの順序で、SSHのルールを有効化の前に置き、コンソールセッションを開いたまま実行します。
sudo ufw default deny incoming
sudo ufw default deny outgoing
sudo ufw allow out on tun0
sudo ufw allow out to 203.0.113.10 port 1194 proto udp
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verbose
ufw reset は意図的にそのブロックから外しています。すべてのルールを削除してファイアウォールを無効にするもので、リモートホストでは続く有効化がセッションを落とす原因になります。どうしてもリセットするなら、SSHのルールを足し、先へ進む前にコンソール経由の戻り道を確保してください。
順序は見た目の問題ではありません。ufwの稼働中に足したルールは何も流しませんが、既定ポリシーを切り替えた瞬間にチェーンが再読み込みされ、古いポリシーが許していたセッションも一緒に消えます。既定値、許可、有効化を一度の流れで行ってください。マシンに依存しない入り口がまだあるうちに。
遮断状態を試し、元に戻す手段を残す
試していないキルスイッチは推測にすぎません。クライアントをわざと切断してページを読み込んでみてください。失敗しなければなりません。再接続すれば、ルールに触れずに回復するはずです。sudo ufw status verbose は既定値とログの状態を確認し、ufw status numbered は目的を過ぎたときにどのテストルールを消すべきかを示します。
逆方向のスクリプトを順方向の隣に置いてください。外向き拒否と死んだトンネルを抱えたマシンは自分の修理をダウンロードできません。だから元に戻す手段はディスク上にあり、コンソールから読めなければなりません。
sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
トンネルがすでに落ちていてルールを外す必要があるときに実行してください。日常の手順ではありません。ターミナルを閉じる前に、四つの条件が成り立つべきです。ピアのルールが正確に一つのアドレスを名指ししている。DNSに名前付きの例外がある。有効化が許可の後に来ている。トンネルを引くと通常の通信は死ぬが、クライアントは永久には死なない。