TCP 443 しか許可しないネットワークは、UDP を問題なく通すネットワークと共存しており、一台のサーバーが両方を処理する必要があります。proto udp を持つプロファイルは後者のグループに応答し、前者では失敗します。同じ設定を proto tcp に書き換えても二つ目のリスナーはできません。このディレクティブは一つのプロセスに一つのトランスポートを選び、それ以外はすべてこの制約から導かれます。

複数のプロセスを動かすか、複数のソケットを同時にバインドできるバージョンを動かすかのどちらかです。

2.7 より前は一プロセスが一トランスポートをバインドする

コミュニティ版の OpenVPN は proto が示すソケットをバインドし、このディレクティブはインスタンスに一つのトランスポートを選びます。TCP と UDP は別のスタックなので、同じポート番号を両方が同時に使用できますが、一つのプロセスが両方を持つことはできません。そのため 2.6 系ではデーモンごとに一つのトランスポートになります。OpenVPN 2.7 はサーバーについてこの制限を撤廃し、一つのプロセス内で複数の --local 文を通じて複数のソケットをバインドできるようになりました。

どちらの答えで設計するにしても、2.7 の構成は独自の設定構文を持つ別の運用モデルなので、まずバージョンを確認してください。2.6 向けに書かれたガイドは、そう明記していなくても二つのプロセスを前提にしています。

二つのインスタンスを動かす三つの方法

TAP インターフェースでは、トランスポートごとに一つのインスタンスを動かし、ホスト上で二つの tap デバイスをブリッジします。両方のクライアント群が同じブロードキャストドメインに入るため、一つのアドレスプールで両方をカバーでき、ブロードキャストに依存するプロトコルも動作し続けます。TUN ではブリッジが使えないので、最も単純な分割は各インスタンスに独自のサブネットを与え、ルーティングで二つのクライアント群を分けます。三つ目の選択肢は、各インスタンスが learn-address スクリプトを呼び、そのインスタンスのデバイス経由でクライアントに /32 ルートを入れることで、一つのプールを保ちます。

この三つ目の構成は、スクリプトがデータパスの一部となって追加・更新・削除のイベントを正しく処理しなければならないため、よく求められる一方で最も注意を要します。

ArrangementInterfacesAddress poolCost
Bridged TAP pairTwo tap devices joined by a bridgeOne shared poolBroadcast traffic and bridge maintenance
Two TUN subnetsTwo tun devices, no bridgeOne pool per instanceRouting rules and two plans
Shared pool with routesTwo tun devices plus a hookOne pool across bothA script on the data path

二つのインスタンスを分離する

各インスタンスには、別々のポートまたはアドレス、別々のステータスファイル、別々のログ出力先も必要です。二つのデーモンが一つのステータスファイルに追記すると、障害時に読めない出力になり、それはまさに出力が必要な瞬間です。二つ目のインスタンスが特定のアドレスをバインドする場合、そのアドレスはプロセス起動時にホスト上に存在している必要があり、そうでなければ鍵の話をする前にバインド失敗で終了します。

ユニット名とプロファイル名からトランスポートが分かるようにしてください。次の担当者が、どちらが TCP かを知るために設定を開く必要はありません。

プロファイルをリスナーに合わせる

proto tcp で動くサーバーは proto tcp-client を持つクライアントプロファイルを想定しており、proto udp のままのプロファイルはそのリスナーに対して ユーザーが対処できるエラーもなくタイムアウトします。両方のトランスポートを提供するならプロファイルを二つ用意し、どちらを試したかサポートが分かるようラベルを付けてください。ポート番号だけではトランスポートを表しません。

ファイアウォールのルールも同じ分け方に従い、UDP 1194 のルールは TCP 1194 については何も言っておらず、一方のアドレスのルールがもう一方のリスナーをカバーすることもありません。

まずサーバー側の見え方を読む

ss -lntup をサーバーで実行し、TCP と UDP の両方のリスナーが現れることを確認します。次に各種類のクライアントを一つずつ接続し、異なるアドレスを持つ二つのエントリがステータス出力にあるか確認します。ソケットはあるのにクライアントが来ない場合、デーモンが受け取る前に経路かファイアウォールがパケットを拒否しています。

決して現れないソケットは設定かバインドの問題で、現れるのに接続を記録しないソケットはフィルタリングの問題です。クライアントから見るとこの二つは同じに見えるため、サーバー自身の見え方を先に確認します。TCP はヘッドオブラインブロッキングを伴うので、提供することは UDP が正常に通るクライアントにとっての改善ではなく到達性の手段です。

関連記事