一方のクライアントは共有鍵で認証でき、もう一方は拒否する。貼り付けた文字はどちらから見ても同じに見える。おそらく同じ文字であり、違いはファイルがどのデコード規則を適用するかにある。引用符で囲んだ文字列はそのまま扱われ、0x で始まるトークンは十六進数として読まれ、0s で始まるトークンは Base64 として読まれる。三つの書き方のうち意図どおりの意味を持つのは一つだけなので、修正はたいてい変換であり、より良いパスワードではない。

症状が示すのは暗号ではなくエンコード

両端が異なるバイトを保持しているとき、ネゴシエーションは成功したまま、その後に証明が失敗する。ログにはアルゴリズムの不一致ではなく、整合性または HMAC の失敗が記録される。提案は選ばれ、認証の段階だけが噛み合わなかったからだ。その行がシークレットの形に触れることはない。

手がかりは段階にある。提案が選ばれた後に届く失敗は、両者が鍵素材以外のすべてで合意したことを意味する。一方「提案が選ばれない」はポリシーや暗号スイートの側の問題だ。パスワードが正しく見えるのに整合性チェックが失敗するのは、エンコードの不一致が表に出た姿である。

一つのシークレット、ファイルが読む三つの方法

四バイトの値 key1 について、十六進数と Base64 は同じバイトの二つの再エンコードであり、先頭の文字だけがパーサーにどちらを保持しているかを伝える。swanctl の資格情報も同じ慣習に従うため、二つのインターフェース間で移した値は、接頭辞が一緒に移動して初めて意味を保つ。

10.20.0.5 %any : PSK "key1"
10.20.0.5 %any : PSK 0x6b657931
10.20.0.5 %any : PSK 0sa2V5MQ==

このブロックで最も時間を食うのは二つの細部だ。十六進数の数字は大文字小文字のどちらも受け付けるので、0x6b657931 と 0x6B657931 は同じ値になる。しかし奇数の文字数は拒否されずに黙って読み違えられ、切れ目の後ろのバイトがすべてずれる。Base64 の詰め物は値の一部なので、末尾の = 記号を欠いたまま貼り付けた文字列は、大きな音を立てて失敗する代わりに別のバイトへデコードされる。

一度値をデコードしたプロファイルはすでに変換済みであり、もう一度デコードすると別のバイトになり、間違ったパスワードのような認証失敗が起きる。曖昧なものには引用符が安全な方向だ。内容はエンコード記号で始まっていてもリテラルとして扱われる。

Base64 のテキストはどこから来るのか

プロファイルのエクスポートやベンダーのポータルは、すでにエンコード済みの鍵を渡してくることが多い。たいていは手入力することを想定していないデータ欄だ。その値を展開してデコードしたテキストを引用符で保存するか、記号を前に付けたままエンコードされた状態で残すか。どちらも半分ずつやるのが壊れる原因である。どちらの道も、値の全体がコピーを生き延びたときにだけ機能する。

どちらの向きもコマンド一つで済み、保存された値を生んだ正確な操作としてチケットに残す価値がある。次の順で実行する。

printf '%s' 'a2V5MQ==' | base64 -d
printf '%s' 'key1' | base64

エンコードされたテキストを平文のように貼り付けるのが高くつく誤りだ。ファイルは書かれたとおりに文字をハッシュし、導出鍵は相手が計算したものよりおよそ三分の一長くなり、どの試行も警告なしに同じように失敗する。パーサーは与えられた規則に従っただけだからだ。

各ピアが実際にどのバイトを使っているかを確かめる

エラー文字列から原因を推測するのではなく、まずデーモンから見た接続の姿を、次に認証の結果を読む。保存された長さを比べるのは手早い妥当性確認だ。エンコードされたテキストは、それが表すバイトより長いからである。次にどの識別情報の行が一致したかを確かめる。正しいシークレットでも間違ったピアの下に置かれれば、間違ったものとまったく同じように失敗する。行の順序がそれを決める。最初の一致が勝つので、上部近くの広い %any の行が、いま編集した特定の行を静かに置き換えてしまう。

ファイルが正しくなったら再起動ではなく再読み込みをする。ipsec rereadsecrets は IKE デーモンの複製を更新し、swanctl の構成は独自のコマンドで資格情報を読み込む。再起動は確立済みの関連をすべて落とし、調べようとしていた比較を台無しにする。

これらの確認はいずれもシークレットを晒す必要がない。長さ、識別情報の選択子、行の位置で、この種の失敗のほとんどは説明がつく。十六進ダンプが必要になる前に。

結果を隠さずにファイルを変える

ファイルはデーモンのアカウントだけに制限し、生きたシークレットはチケット、チャット、スクリーンショットから遠ざける。貼り付けた鍵は診断ではなく漏洩だからだ。それは鍵を生んだインシデントより長く生き残る。

設定を自分で管理しているクライアントから試し、認証が成功することを確かめ、そのうえでトンネルが通信を運ぶことを確かめる。ハンドシェイクは直ったのに経路が壊れたままの再読み込みは別の問題であり、シークレットが動かなくなった途端に見えてくる。

関連記事