トンネルの片側が、もう片側が決して確認しないキースロットで制御チャネルに署名し、証明書が一つも交換される前に接続は認証エラーで落ちます。これが tls-auth の方向不一致の姿で、しかも決定的です。同じ二つのファイルは、どのネットワークからでも、何度試しても失敗します。ログには探しているオプションの名前は出てこないため、人々は壊れてもいない鍵を作り直し、証明書を再発行します。解決策は両端を相補的にするか、両方を双方向のままにすることで、検証を弱めることではありません。

失敗は証明書より前に起きる

tls-auth では両方のピアが同じ共有鍵を持ち、それぞれがそこから導かれる二つのスロットの一方を使います。一方のスロットは送信する制御パケットに署名し、もう一方は受信したパケットを検証します。方向 0 と方向 1 はこの役割を逆順に割り当てるので、HMAC の検査が揃うには組が相補的でなければなりません。片側で割り当てが反転すると、受信側は誤ったスロットに署名を探し、パケットを拒否します。セッションはそこで終わるため、このエラーは証明書ストアが生み出す何かではなく、パケット認証に関わるものです。

決定性は診断に重要です。時刻や経路の問題は別の痕跡を残すからです。断続的な切断、片方向だけの失敗、特定のネットワークでだけ死ぬセッションなどです。方向不一致は毎回最初のハンドシェイクで失敗し、同じ二つのファイルを持つ別のマシンでもまったく同じように失敗します。--verb 4 でログを読み、最後の行ではなく最初に拒否されたパケットを見つけてください。その拒否が証明書の交換より前に起きているなら、共有鍵とその方向こそ確認する価値のある二点です。

What you seeWhat it rules outNext check
Authentication error before any certificate is sentThe data channel is irrelevant; the control channel never authenticatedCompare tls-auth and its direction on both ends
Certificate or handshake failure after the control channel authenticatesThe shared key and its direction already agreeCheck the CA, the certificate dates and the hostname
Session completes but throughput or cipher warnings appearDirection was never the problemCompare the data-channel cipher settings
Startup stops on an options errorThe number itself is not the issueRe-read the inline versus external directive syntax

番号はどこにあるのか

OpenVPN 2.6 のマニュアル は方向の指定箇所を二つ示しています。鍵が独立したファイルにある場合は tls-auth の第二引数、鍵がプロファイルにインラインで書かれている場合は独立した key-direction 行です。どちらも同じ値を設定するので、プロファイルはどちらか一方の形式を使うべきで、両方は決して使いません。省略も選択肢で、どちらの側も方向を指定しない場合に機能する双方向の配置になります。同じ番号を持つ二つのピアはその配置にはありません。それぞれが一方のスロットで署名し他方で検証することを期待し、両方とも同じ向きにやってしまうからです。

# server.conf, external key
tls-auth ta.key 0

# client.ovpn, external key
tls-auth ta.key 1

# client.ovpn, inline key
key-direction 1

インライン形式は独立した行のディレクティブであり、鍵ブロックの開始タグの属性ではありません。そのタグに引数を足すのは方向の変更ではなく誤りです。位置も重要で、ディレクティブは属するブロックの外に置かれるため、ブロックの内側に書いた値は鍵素材として読まれます。ペアをでっち上げず、プロファイルの配布元が意図した配置をそのまま写してください。一方のサーバーで動くプロファイルは、もう片側ですでに鏡像になっているかもしれません。

このオプションが触れないもの

アプリケーションのトラフィックは暗号化しません。tls-auth は制御チャネルのパケットの周りに HMAC を置くだけで、データチャネルはハンドシェイクで交渉したセッション鍵で保護されます。したがってスループットや暗号方式の話は方向の番号とは無関係です。この設定は二層目の暗号化も加えません。長い鍵を探しに行く人がいるのは、この思い込みのせいです。

これは tls-crypt には適用されません。独自のオプションと鍵の扱いを持つ別の制御チャネル機構です であり、どのピアの証明書の身元についても何も語りません。したがって方向の一致が機能することは、両端が制御チャネルの認証方法で合意していることだけを示し、信頼の連鎖が検証されたことは示しません。

組を揃えてから再接続する

どちらかを変更する前に二つの設定を比較してください。すでに正しい側を編集すると作業が二倍になります。下の grep は各ファイルがどの機構を選ぶかを示し、詳細な実行は制御チャネルがそもそも認証されたかを示します。両方の出力を保存し、次の変更を既知の状態と比べられるようにしてください。

grep -n -E 'tls-auth|tls-crypt|key-direction' server.conf client.ovpn
openvpn --config client.ovpn --verb 4 2>&1 | grep -i -E 'hmac|tls error|control channel'

変更のたびに両方のピアを再起動してください。これらのオプションは起動時に一度だけ読まれ、片側だけ再読み込みすると古いセッションの寿命の間ずっと組が不整合になります。いま方向を設定せずに展開が動いているなら、片方のピアに設定を足すと最初の失敗を再現します。両方をそのままにするか、両方を設定してください。一度に片端だけ変え、前のファイルを残しておけば、退行は再構築ではなく二分の巻き戻しで済みます。

各端の機構、鍵ファイル、方向を展開ノートに記録してください。そうしないと次の人は似た二つのファイルを読み、番号は互いに一致すべきだと誤解します。方向は調整の細部であり、セキュリティの強化ではありません。制御チャネルの二つの方向を分けるだけで、それ以外の何もしません。

関連記事