フルトンネル OpenVPN:サーバー側にインターネット出口を追加する
デフォルトルートをプッシュするのは、フルトンネルサービス全体の半分にすぎない。サーバーには転送、範囲を絞った転送ルール、プールへの戻り経路も必要である。
クライアントは認証を受け、プールからアドレスを受け取り、VPN ホスト上のサービスに到達する。それでも、あらゆる公開宛先はタイムアウトする。これが出口のないトンネルの姿であり、四つの別個の条件がそろうまでそのまま続く。クライアントがデフォルトルートを受け入れること、サーバーが転送すること、ファイアウォールが通過を許可すること、そして応答がプールへ戻る経路を持つことが必要である。四つの不具合はどれも同じ症状を示すので、一度に一つだけ変えて結果を記録してほしい。
デフォルトルートをプッシュし、クライアントが何を入れたかを確認する
サーバー側の一行は短く、プッシュされたオプションを受け入れるクライアントにしか効かない。def1 形式は既存のデフォルトを削除する代わりに二本のハーフデフォルトルートを入れるので、現在の接続を生かしたまま、あらゆる宛先を取り込める。
push "redirect-gateway def1"
再接続したら、プロファイルを信じるのではなくクライアントのルーティングテーブルを読む。Linux では二つの /1 エントリが元のデフォルトの隣に現れ、Windows は同じ組を 0.0.0.0/1 と 128.0.0.0/1 として表示する。プッシュされたオプションを無視するクライアント、あるいはそれらを拒否する設定のクライアントは、古いデフォルトを保持したまま、インターネットの通信をトンネルへ送らない。サーバー側のどのルールでも埋め合わせはできないので、サーバーに手を入れる前にこの問いを決着させてほしい。
転送はサーバーの設定であり、VPN の設定ではない
ルーティングに触る前に転送フラグを読む。そこがゼロなら、カーネルはクライアントのパケットを受け取っても先へ渡さない。これは遠端から見たファイアウォールの遮断とまったく同じに見える。値はシステムの設定ディレクトリ経由で設定し、再起動後も残るようにする。
sysctl net.ipv4.ip_forward
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-vpn-forward.conf
sudo sysctl --system
次に、ホスト自身がインターネット出口への経路を持っていることを確認する。サーバーのシェルからの要求は上流の経路が使えることを示すだけで、クライアントのパケット転送については何も語らない。だから二つは別の試験として扱う。サーバーが宛先に届かないなら、転送の設定をどれだけ足しても役に立たない。
意図した通過だけを許可し、それ以外は通さない
転送されたパケットは forward 経路を通り、VPN ホスト自身宛ての通信は input 経路を通る。これは別々の判断であり、input 経路を開いてもマシンを通り抜けることは許可されない。両者を取り違えるのが、ファイアウォールがすべて許可しているように見えるのにクライアントがタイムアウトし続ける最も一般的な理由である。
最小限のポリシーは、プールから出口インターフェース向けの新しい接続を許可し、確立済みフローに属する応答を許可する。起動のたびに重複ルールを足すのではなく、ディストリビューションが使うルールセットの管理先へ置く。重複ルールは積み上がり、カウンタは意味を失う。
sudo iptables -A FORWARD -i tun0 -o eth0 -s 10.90.0.0/24 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
すべてのチェーンを許可に変えれば試験は通るが、ファイアウォールの存在理由が消える。範囲はプールと出口インターフェースに限り、無関係な転送はそのままにする。
応答の戻り先を用意する
プールのアドレスは非公開なので、公開サーバーは応答を直接そこへ届けられない。VPN ホストが出る方向で送信元アドレスを変換するか、上流の機器がプールへの戻り経路を持つかのどちらかである。
sudo iptables -t nat -A POSTROUTING -s 10.90.0.0/24 -o eth0 -j MASQUERADE
変換の層はきっかり一つだけ足す。さらに上流に二つ目の NAT を置くと最初の層が隠れ、後で問題が起きたときに両方のログがほとんど役に立たなくなる。上流のルーターがすでにプールを戻しているなら、ホストでの変換は冗長であり、戻り経路は自分の設定ではなくそのルーターの設定に依存する。
クラウドのインスタンスはもう一つ関門を加える。一部のプラットフォームは、送信元アドレスがインスタンス自身のものでないパケットを、その検査を緩めない限り捨てる。この設定はゲストの外にあり、ローカルの試験機が動いていると忘れやすい。
サーバーのシェルではなく、クライアントから証明する
まず数値の IPv4 要求、次に名前解決、最後にアプリケーションの順で試す。ping は転送と変換を証明するが、名前解決については何も証明しない。DNS オプションは、クライアント側の統合がそれを設定して初めて効くからである。
curl -4 -m 5 http://198.51.100.10/
dig +short example.com
変更と元に戻す手順はその都度記録し、試験が失敗したときに出口ポリシーを一手で戻せるようにする。この手順が扱うのは IPv4 だけである。導入がすべての通信を運ぶと主張する前に、IPv6 を別途棚卸ししてほしい。