CIDR 接尾辞とドット表記のマスクを混ぜたサーバー行は、デーモンがポートを開く前に停止させます。IPv4 の server ヘルパーは、整列したネットワークアドレスと、そのあとのドット表記のネットマスクという二つの引数を別々に受け取ります。それ以外はすべて推測であり、プールサイズやクライアントのマスクが狂うのはこの推測の部分です。

ヘルパーが受け取る二つの引数

ネットワークを先に、マスクを後に書き、アドレスには何もつなげません。

server 10.72.16.0 255.255.240.0

/20 の場合はこの形です。下の行が誤りで、実行時ではなくオプション解析の段階で失敗します。

server 10.72.16.0/20 255.255.240.0

デバッグでは二つの考えを切り離してください。プレフィックス長とドット表記のマスクは同じ範囲を表しますが、ヘルパーは両方を同時には受け付けず、拒否された行は計算ではなくディレクティブを示すオプションエラーになります。

マスクを打つ前にネットワークを整列させる

最初のアドレスは範囲のネットワークアドレスであり、その中の都合のよいクライアントアドレスではありません。/20 では範囲は 10.72.16.0 から 10.72.31.255 までで、そのうち最初だけが有効なネットワーク引数です。/21 は 255.255.248.0 を使い、10.72.16.0 から 10.72.23.255 までを覆うので、その行は server 10.72.16.0 255.255.248.0 です。

プレフィックスを変えると範囲が変わるだけで、ほかは変わりません。一人のクライアントが受け取るアドレスの数は変わらず、それはこの行のマスクではなくトポロジーの性質だからです。

サーバー側からプールを確認する

詳細ログを有効にしてインスタンスを前面で起動し、ヘルパーが出す行を読みます。構築されたプールは起動時に出力され、手で計算するより確実です。

openvpn --config /etc/openvpn/server.conf --verb 4 --dev tun9 --port 1195

出力の上のほうにあるプールの要約を探します。ヘルパーが確保した範囲が並んでおり、その範囲が意図と合わなければ、マスクの計算が何と言おうと行の引数が間違っています。

次にクライアントを一つ接続し、渡されたアドレスを記録した行を探します。その一つのアドレスをプールの範囲と並べれば、クライアントが確保されたブロックに入ったのか、想定外の場所に落ちたのかが分かります。両者が食い違うなら、クライアントではなく引数を直します。一致していてクライアントが何にも届かないなら、プールは最初から問題ではありません。

トポロジーを念頭にクライアントのマスクを読む

クライアントがトンネルインターフェースに /30 を表示していても、プールが壊れている証拠にはなりません。ポイントツーポイントのアドレス指定では各クライアントが小さなブロックを受け取り、そのインターフェースのマスクはそのブロックを表し、サーバーのプールは全体を覆います。サブネットトポロジーでは代わりにクライアントのマスクがプールのマスクと一致します。したがってマスクだけでは、どのトポロジーが使われているかは分かっても、プールが正しく書かれているかは分かりません。

結論を出す前に、設定されたトポロジーと割り当てられたアドレスを一緒に確認します。

ip -4 addr show tun0

アドレスがプールの内側にあり、マスクがプールより狭ければ、それはトポロジーが仕事をしているだけです。アドレスがプールの外側ならプールが誤りで、クライアント側をいくら調べても直りません。

稼働中のプールを変更する

現在のプール、LAN、そして すでにクライアントへ送られたルート のどれとも重ならない範囲を選びます。重なりは再起動を生き延び、数日後に一つの拠点が一方向から到達できない形で現れる障害です。

行を変更して再起動し、利用者を戻す前に起動時のプールを読み直します。新しい範囲が何かと衝突すれば、同じ起動出力がすぐに示します。切り戻しは一行の編集と、もう一度の再起動です。

変更後もしばらくは古い範囲を確保したままにします。遅れて再接続するクライアントは前のプールのアドレスをまだ持っていることがあり、そのアドレスを再利用する新しい範囲は、ルーティング障害に見える重複割り当てを生みます。OpenVPN 2.6 のマニュアル はヘルパーの引数とその展開を説明しており、あるディレクティブが隣と同じ記法を取ると決めつける前に読む価値があります。

関連記事