OpenVPN に接続済みなのになにも読み込まれない:クライアントから外へ辿る
トンネルは上がっているのにブラウザは回り続ける。クライアントから外へ向かって進めます。二つのキャプチャ、カーネルのスイッチ一つ、実際の出口インターフェース、そして DNS です。
クライアントの画面には Connected と出ており、トンネルのアドレスもあり、それでもブラウザは回り続けています。この組み合わせは正常です。なぜなら、ハンドシェイクの成功はトンネルが作られたことしか証明しないからです。サーバーがパケットを転送するのか、送信元を書き換えるのか、DNS の問い合わせに答えるのかは何も語りません。多くの人がやる間違いは、まずサーバーの設定を開くことです。そうではなくクライアントから外へ向かって進めてください。以下の各手順が、次を調べる価値があるかどうかを教えてくれます。
クライアントから始めて外へ進む
この順番で三つのテストを行い、最初のどれが失敗したかを書き留めます。サーバーのトンネルアドレスに ping を打てば、トンネル自体が通信を運んでいることが分かります。番号で公開アドレスに ping を打てば、名前解決を介さずに転送と変換が証明できます。そのうえでホスト名の解決を試します。これが DNS を使う唯一のテストです。結果ごとに疑う層が一つ消えます。
ブラウザのほうが速く感じるからといって三つ目のテストに飛んではいけません。ページの読み込み失敗は三つの層をまとめて覆い隠すので、そこから始めると動いているトンネルを作り直すことになります。失敗したページは三つのうちどれが壊れたかを教えてくれません。
二つのキャプチャがパケットの止まる場所を示す
クライアントから公開アドレスへの ping を流したまま、トンネルのインターフェースで一つ、インターネットに出るはずの上流リンクで一つ、キャプチャを取ります。タイムスタンプが揃うよう、二つを同時に走らせてください。
sudo tcpdump -ni tun0 -c 20 icmp
sudo tcpdump -ni enp1s0 -c 20 icmp
要求がトンネル側に現れて上流リンクに一切現れないなら、サーバーがトンネルとケーブルの間で捨てています。原因は転送か転送用のファイアウォールポリシーであり、NAT ではありません。両方に現れるならサーバーは役割を果たしており、応答がもっと外側で失われています。これは変換、上流のフィルタ、あるいはプロバイダー側の制限を示します。
上流リンクの名前はチュートリアルではなくルーティングテーブルから取ります。クラウドのイメージや名前を変えたアダプターは解説の例のインターフェースとまず一致しませんし、間違ったデバイスで取ったキャプチャは転送していないサーバーとまったく同じに見えます。
ip -4 route get 9.9.9.9
その出力の dev フィールドが、あとで NAT ルールが必要とする名前です。だから残しておいてください。
転送はカーネルのスイッチとファイアウォールのポリシー
まずカーネルが転送を認める必要があります。現在の値を読み、実行中のカーネルに書くだけでなく設定を永続化します。
sysctl net.ipv4.ip_forward
printf 'net.ipv4.ip_forward=1\n' > /etc/sysctl.d/70-vpn-forward.conf
sysctl --system
転送は半分にすぎません。UFW を使うホストでは転送ポリシーが /etc/default/ufw で設定され、再読み込みが効く前に ACCEPT でなければなりません。転送経路の既定の破棄は、ハンドシェイクをまったく健全なまま放置しながら、トンネルから出ようとするすべてのパケットを黙って捨てます。これが最初に遭遇した症状そのものです。
nftables を直接管理するホストでは同じ問いが別の構文になります。クライアントのテストを流しながら転送チェーンのカウンターを見てください。参照されるチェーンと破棄するチェーンは、設定ファイル上では同じに見えるからです。
NAT ルールには実際の出口インターフェースを書く
送信元変換は、実際にホストを出るインターフェースに、サーバーが配るプールと組み合わせて置きます。ルールの両半分が現実を記述している必要があり、どちらも省略できません。
iptables -t nat -A POSTROUTING -s 10.44.0.0/24 -o enp1s0 -j MASQUERADE
よくある失敗は、解説からコピーしたルールが -o eth0 と言っているのに、そのマシンのアダプターが別の名前である場合です。ルールは警告もなく入り、何にも一致せず、クライアントはインターネットにつながらないままです。プールも同じ間違いのもう半分です。サーバーが 10.44.0.0/24 を配っているのにルールが 10.8.0.0/24 を覆っていれば、決して一致しません。
ルールの文面を信じるのではなくカウンターを見ます。一覧はルールごとのパケット数を報告し、決して一致しないルールはどれほど正しく見えてもゼロのままです。その数字から何かを読み取る前に、実際のクライアント通信を一分間流してください。
iptables -t nat -L POSTROUTING -v -n
実際のクライアントテストのあとにパケット数がゼロなら、一致条件が間違っているのであって、トンネルが壊れているのではありません。一致したらルールセットを保存し、再起動に耐えさせます。シェルの履歴にしか残らない修正は最初の再起動で消えます。
サーバーがクラウドの NAT インスタンスでもあるなら、プラットフォームにも発言権があります。アドレスを変換するインスタンスは通常、プロバイダーがその設定を用意している場所で送信元と宛先のチェックを無効にする必要があり、VPN ポート自体も外部から到達できなければなりません。
DNS は一つ目の後ろにある二つ目の失敗
名前が失敗するのにアドレスでの ping が通るのはリゾルバーの問題であり、それには独自の原因があります。ローカルのリゾルバーを残すクライアントは、その問い合わせを完全なトンネルに送り込み、決して来ない応答を待ちます。ローカルのリゾルバーが今や経路の逆側にあるからです。
サーバーからリゾルバーを配り、クライアントがどこに問い合わせるかを学べるようにします。二つの項目があれば、一つ目に届かないときの代替になります。どちらもトンネルが実際に許可するリゾルバーであるべきです。
push "dhcp-option DNS 9.9.9.9"
push "dhcp-option DNS 149.112.112.112"
それでも Windows クライアントはローカルのリゾルバーに戻ることがあり、まさにそれを防ぐために block-outside-dns があります。ただし、ローカルネットワークしか解決できない名前を失うという代償があります。systemd-resolved を使う Linux クライアントは、スクリプトが導入しない限り配られたリゾルバーを無視することが多いので、配布が無視されたと結論する前にトンネルデバイスの resolvectl status を確認してください。
利用者が体験する順序でこの道のりを終えます。クライアントから実際のページを読み込み、どのアドレスから出ているかを確認し、サーバーを再起動して再接続し、三つのテストを繰り返します。この二度目の確認だけが、保存したルール、ファイアウォールポリシー、配ったリゾルバーがそろって生き残ったことを証明します。