ログに GRE 書き込み失敗が出ると、まずユーザーのパスワードをリセットしたくなる。その直感はほぼ常に間違っている。これらのメッセージは認証情報の確認ではなくデータ経路を説明している:クライアントは認証に成功した後、ネットワークに登録する段階で止まっている可能性がある。二つの異なるメッセージは二つの異なる障害を指しており、どちらも新しいパスワードでは解決しない。

二つのメッセージ、二つの障害

読み取り失敗は、GRE パケットがデーモンに届かないか、入り口で破棄されていることを意味する。制御接続は完全に正常に見えても、データ経路を何も通過していないことがある。認証だけは間違いなく機能していた。

書き込み失敗は通常、カーネルやクライアントが使えないものをセッションが交渉したことを意味する。制御チャネルは完了したが、その交換で合意したオプションがエンドポイントの実際の能力と一致していない。これは設定の不一致であり、認証の事象ではない。

何かを変える前に、どちらが出ているかを読む。両者は異なる層へ導くものであり、同じ症状として扱うから同じサーバーが無関係な理由で二回パッチされる。ログの行だけが無料で得られる診断だ。

プロトコル 47 はポート 47 ではない

PPTP は呼の確立に TCP 1723 を、ペイロードの運搬に GRE を使う。GRE はポート番号ではなく IP プロトコル 47 なので、ポート 47 を開けるファイアウォール規則では何の役にも立たない。

経路上のルーターには PPTP パススルー機能か明示的な GRE の許可が必要だ。それがなければ TCP ハンドシェイクは完了してもトンネルはパケットを運ばず、上記の読み取り失敗がそのまま起きる。ファイアウォールのポート 47 規則は、このプロトコルで最もよく無駄にされる午後だ。

どちら側が通信を落としているかを推測するのではなく、サーバーで両方向を同時に観察する: tcpdump -ni any port 1723 or proto gre。

1723 が呼の確立を示すのに GRE が沈黙しているなら、遮断はホストより上流にある。GRE が届いてもデーモンが失敗するなら、問題はローカルであり、次に見るべきはオプションだ。

ホストが実際に転送する場所で GRE を許可する

GRE の forward 規則を挿入するのは、トンネル通信を転送するホストでの妥当な試験であり、ポリシーではない。一つのプロトコルのすべてを許可する試験規則は診断であり、設計ではない。何か学べるだけの時間だけ置き、その後は範囲を絞った規則に置き換える。

サーバー自身宛てのパケットには input 規則を追加する(forward チェーンはそれらを見ないからだ)。そのうえで接続試行の前後で規則のカウンターを見れば、パケットがそもそも届くかがわかる。

再起動のたびに実行し直すのではなく、ディストリビューションのファイアウォールサービスで規則を永続化する。nftables ホストでは、input チェーンと forward チェーンの両方で ip protocol gre を一致させる。

ppp_generic モジュールも読み込まれていることを確認し、接続追跡が戻りの方向を落としていないか調べる。どちらもファイアウォール問題に見えてそうではない障害を生む。カーネルモジュールの欠落は、確認するまでブロックされたプロトコルとまったく同じに見える。

オプションを実際に持っているクライアントに合わせる

もう一方の報告の修正は /etc/ppp/pptpd-options にあり、そこではレシピが PAP、CHAP、MSCHAP を拒否し、対応する require 行をコメントアウトし、状態付き MPPE を維持している。そのレシピは一つのクライアント構成向けに書かれたもので、盲目的にコピーすると一般的なケースを壊す。拒否行は推薦ではなく、著者がどのクライアントを持っていたかという記述として読むべきだ。

Windows クライアントは通常 MS-CHAPv2 と MPPE-128 を必要とする。その要件は維持し、クライアントが本当に交渉できないオプションだけを外す。

# keep encryption; drop only what this client cannot negotiate
refuse-pap
refuse-chap
refuse-mschap
mppe-stateful
require-mschap-v2
require-mppe-128

接続を成功させるために暗号化を無効にするのは修復ではなく格下げだ。そのような変種はラボの回線で試し、サービスが実クライアントに接する前に暗号化を戻す。安全でなく動く接続は、正直に失敗する接続より悪い。

クライアントのエラー番号を読む

クライアントの数値コードは、サーバーログより速く段階を絞り込む。何より先にそれを読む。691 は認証情報が拒否されたこと、721 はサーバーが応答しなかったこと、619 は接続が切れたことを意味する。番号に二分使えば、設定に一時間使うのを省ける。

何かを編集する前にそのコードをサーバーログと比べ、変更のたびに同じクライアントで再試験する。そうしなければ二つ目の障害が一つ目の陰に隠れ、修正が効かないように見える。

ログインが成功して通信が動かないなら、GRE が依然として容疑者だ。その瞬間は認証情報の保管場所ではなくキャプチャに戻るべきときだ。

関連記事