無関係な二つの不具合が同じ不満を生む。第一に、アドレスが同じサブネットにないか、サーバーがピア間の通信を転送していないため、あるクライアントがトンネルアドレスでも別のクライアントに届かない。第二に、ping は通るのにアプリのデバイス一覧が空のままで、これはレイヤー 3 のトンネルが運べないブロードキャストに検出が依存しているためだ。一度の ping で両者は分かれ、それぞれの直し方は互いにまったく似ていない。

一度の ping で問題は二つに分かれる

あるクライアントから、もう一方のクライアントのトンネルアドレスへ ping する。名前や LAN アドレスではない。失敗すれば転送かアドレス設計の問題で、直るまで検出は無関係だ。成功すれば転送はすでに動いており、残る隙間はブロードキャストか名前解決である。

ip addr show tun0

何より先にクライアントのインターフェースを読む。ネットマスクが構成の名前を示すからだ。/24 などのサブネットマスクなら共有プール、ピアアドレス付きの /30 なら各クライアントがサーバーという一つの隣人だけを持つ古いポイントツーポイント構成だ。

net30 とサブネットをクライアント側から読む

What you observenet30subnet
Client netmask/30 with a peer addressThe pool's own mask
Peers a client can address directlyOne, the serverEvery client in the pool
AddressingOne /30 block per client, with the server as the only peerOne pool mask shared by all clients
Effect of client-to-clientRequired for any peer trafficRequired for peer traffic, still no broadcast

net30 ではサーバーが クライアントごとに小さなブロックを割り当てるため、サーバーが転送しない限り別クライアントのトンネルアドレスへの経路は存在しない。サブネットならプール全体が一つのネットワークになり、どのクライアントも他のすべてに宛てられ、サーバーがそれらの間を転送する。だからサーバー設定が健全に見えてもピア間の ping が失敗する。壊れているのではなく、クライアントが同じネットワークにいないだけだ。クライアントからは動くリンクと応答しないピアアドレスが見え、ファイアウォールのように読めるが実体はアドレス設計である。

ディレクティブの切り替えはサーバー側の編集と再起動であり、すでに確立したセッションではなく次の接続に効く。変更を判断する前にクライアントを再接続すること。機器が Web 画面から設定を再生成する場合、ディレクティブ、ファイル、日付を記録し、画面があるなら画面から編集する。再生成は次の保存で手編集を上書きするからだ。

client-to-client は別の関門

同じサブネット内でも、client-to-client が設定されていなければ、サーバーは一方のクライアントから来て他方宛てのパケットを捨てる。このキーワードはサーバーを、受け取るだけの端点ではなくピア間通信の転送役にする。構成を直した後に人が見落とす第二の条件がこれだ。

これはブロードキャストには及ばない。この設定はクライアント間のユニキャストを転送するだけで、トンネルを共有セグメントには変えない。どれだけ設定してもマルチキャストの検出クエリが全ピアに届くことはない。

TUN と TAP、それぞれが運べるもの

PropertyTUNTAP
LayerLayer 3, IP packetsLayer 2, Ethernet frames
Broadcast and multicastNot carriedCarried
Bridging to the LANNot applicableRequired for a shared segment
Client platform supportEverywhereMissing on Android and iOS, limited on macOS

tap デバイスを LAN にブリッジすると、遠隔クライアントがオフィスのブロードキャストドメインに入り、検出は完全に解決する。代償は TAP を実装しないプラットフォーム、サーバー上に必要なブリッジ、そしてオフィスの配線のブロードキャストストームが全遠隔ノートに届く障害ドメインだ。

名前解決を必要とする二三台のワークステーションなら、hosts の項目やユニキャストアドレスのほうがブリッジよりはるかに安い。置き換えられないプロトコルがレイヤー 2 の検出に依存するときだけ TAP に手を伸ばし、それ以前には使わない。

ブリッジなしの同一サブネットのクライアント

LAN の範囲からアドレスを与えても、クライアントが配線に載るわけではない。サーバーがトンネルとイーサネットの間をルーティングするので、そのアドレスの ARP はサーバーのインターフェースで止まり、LAN の残りはそれがどこに住むかを知らないままだ。

ip neigh add proxy 10.50.1.250 dev eth0

Proxy ARP はサーバーがクライアントの代わりに答えることでその隙間を埋める。範囲に対しては parpd がクライアントの出入りに合わせて項目を管理し、sysctl net.ipv4.conf.eth0.proxy_arp=1 は他所へルーティングされるすべてに答える。これは広すぎて、混雑したセグメントで独自の驚きを生む。

どの経路を選んでも、トンネルと配線の間の NAT は外すこと。MASQUERADE ルールは、答えようとしているアドレスの問いをまさに隠してしまう。次の人には、クライアント側から推論できない構成を残すことにもなる。

何かを変える前に、サーバー上で tcpdump -ni tun0 により一度の試行を捕捉し、ピアのパケットがそもそも届くかを確認する。届いて捨てられるなら client-to-client を指し、まったく届かないなら構成かルーティングを指す。OpenVPN 2.6 のマニュアルには両方のキーワードと既定の構成が記載されており、フォーラムの投稿から一行コピーする前に自分のバージョンと突き合わせる価値がある。

  • tun インターフェースは /30 のピア対ではなくプールのマスクを示す。
  • 検出を試す前に、もう一方のトンネルアドレスへの直接 ping が成功する。
  • ピアがパケットを交換する必要があるときは常に、サーバー設定に client-to-client が含まれる。
  • アプリが失敗すると言う代わりに、テストしている検出プロトコルを名指しする。
  • グループ内のすべてのクライアントプラットフォームが対応する場合に限り TAP を使う。
  • 同一サブネット内の到達性が重要なら、NAT をトンネルと LAN の間の経路から外す。

関連記事