1 台の Pi、2 つの OpenVPN インスタンス:各ユニットが読むもの
1 台の Pi 上の 2 つの OpenVPN デーモンは別々の構成ファイルを読み、別々のフックから出ていきます。各インスタンスを対応づけ、ペイロードの経路を別々に検証してください。
プロファイルに触れる前に、OpenVPN のプロセスを数えてください。ローミング ユーザーを受け入れながら上流サービスへも接続する Pi は 二 つのデーモンを動かしており、それぞれが入力したインスタンス名で選ばれる構成ファイルを読みます。パッケージのテンプレートは各デーモンに専用の作業ディレクトリ、実行時ステータス ファイル、トンネル デバイスを割り当てます。この分割を間違えると、稼働中のプロセスが決して開かないファイルの中にある正しい設定を、一晩かけて変更することになります。
インスタンス名がそれぞれのファイルを決める
OpenVPN 2.6 に同梱されるユニット ファイルでは、起動引数にインスタンスのプレースホルダーが含まれ、@ 記号の後ろのテキストで埋められます。サーバー テンプレートはサーバー構成ディレクトリから実行され、引数をそこの %i.conf に対して解決します。クライアント テンプレートもクライアント ディレクトリから同じことをします。したがって [email protected] はサーバー ディレクトリの admits.conf を読み、[email protected] はクライアント ディレクトリの uplink.conf を読み、どちらの名前ももう一方のディレクトリでは何の意味も持ちません。
パッケージが上流の既定値を保っていると決めつけず、マシン上で対応を確認してください。ディストリビューションの drop-in は作業ディレクトリや構成引数を丸ごと置き換えられます。
systemctl cat [email protected]
systemctl cat [email protected]その出力の WorkingDirectory 行と構成引数を読んでください。どのファイルが読み込まれるかを決めるのは有効なユニットだけです。ExecStart に --config を追加する drop-in は、テンプレートのパスが正しく見えてもテンプレートに勝ちます。ローカルの上書きが効いているかを知りたいときは、フラグメントと drop-in のパスを確認してください。両方のロールが同じファイルに解決されるなら、一 つのプロセスがサーバーとクライアントを兼ねようとしており、そのファイル内の後ろのオプションが黙って勝ちます。
ローカル転送と転送ペイロードは別のフックに当たる
サーバーの各ローミング ユーザーへの暗号化接続は Pi 自身で生成されるため、その外側の応答はローカル出力フックから出ます。クライアントの上流ピアへの接続も、遠隔ネットワークに届くとはいえローカルに生成された出力です。転送されるペイロードは 三 番目のカテゴリで、カーネルはパケットの送出デバイスをすでに選んだ後にだけそれを照合します。
| Flow | Hook that sees it | What to inspect |
|---|---|---|
| Roaming user handshakes to the server | Local input and local output | Listener socket, bind address, rule admitting the UDP port |
| User payload leaving through the upstream tunnel | Forward | IPv4 forwarding switch, selected route, permission rule, any translation |
| Pi's own connection to the upstream peer | Local output | Underlay route to the provider endpoint, not the tunnel route |
forward チェーン内で送出インターフェースに一致するルールは、ルーティングがすでにそのインターフェースに割り当てたパケットを許可または破棄できますが、インターフェースを選ぶことは決してありません。一 台のホストが一方のトンネルを終端し他方を開始するとき、ユーザーのペイロードを上流トンネルへ送るポリシーと、Pi 自身の暗号化応答を守るポリシーは別々の判断です。たまたま同じ物理 NIC に乗るため、混同されます。
この区別がよくある半端な障害を説明します。ユーザーは接続し、ハンドシェイクも完了し、それでもトラフィックは間違った方向へ出ます。ハンドシェイクはローカルで、ペイロードは forward であり、二 つのうち片方しか試されていないからです。
取り込まれたルートがユーザーへの応答を飲み込む
クライアント プロファイルのセキュリティ設定は、上流が Pi のルーティング テーブルへ何を push できるかを決めます。広いリダイレクトは、機能しているデュアルロール ホストを壊れたホストに変えるオプションです。push されたルートがローミング ユーザーの公開アドレスを覆うと、サーバーが彼らに向けて生成する応答は、アンダーレイから出る代わりに新しいルートをたどって上流トンネルへ入りえます。プロバイダーへのトンネルがまだ動くと確認してそこで止める人が多いのは、そのトラフィックがトンネル自身の転送であり、他のすべてが不調でも流れ続けるからです。
送信元または mark に基づくポリシーが、二 つのストリームを分ける方法です。OpenVPN の Linux mark オプションはデーモン自身の暗号化パケットにファイアウォール mark を付け、ルーティング ルールがそれを専用テーブルへ送れるようにします。サーバーの外側応答が常に 一 つのアンダーレイ アドレスから出るなら、送信元アドレスも同じくらい有効です。どちらの方法も、選んだテーブルに有効なルートとプロバイダーのエンドポイント用の例外が必要で、そうでなければトンネル自体が上がらなくなります。
ルールを書く前に、応答が実際にたどる経路をカーネルに尋ねてください。以下のアドレスは Pi のアンダーレイ アドレスと 一 人のローミング ユーザーの公開アドレスのプレースホルダーです。
ip rule show
ip route get 198.51.100.7 from 192.0.2.10分割を検証し、その後で 一 ロールずつ止める
三 つのフローを別々に試してください。ハンドシェイクが通っても他の 二 つについては何も証明できません。新しい受信接続を受け入れ、許可されたアプリを 一 つ上流の出口へ送り、両方のプロセスが今もそれぞれのピアに到達することを確認します。
次にクライアント ロールを停止し、サーバー ロールが何を保つかを見ます。一 つのインスタンス向けだったルートや mark ルールが両方に適用されていないかを見つける最も安価な方法です。
systemctl stop [email protected]
systemctl status [email protected] --no-pager
ss -lunp | grep openvpn
journalctl -u [email protected] -n 20 --no-pager望むのは、クライアント ロールが停止している間もリスナーがバインドされたままで、トンネル デバイスが存在し、ログに新しいエラーがないことです。クライアントを止めると既存ユーザーへのサーバーの応答も切れるなら、二 つのロールは片方に限定すべき何かを共有しています。どのインスタンス、どの構成ファイル、どのフローの所有者に各変更が触れたかを記録してください。そうしないと、このホストを次にデバッグする人が同じ発見をゼロから繰り返します。