サーバーにユーザーを追加し、パスワードも正しく入力したのに、接続は依然として AUTH_FAILED で終わる。プラグイン行が理由を説明していることが多い:プラグインのパスの後ろの語は PAM サービスの名前であり、どのモジュール群が問い合わせに答えるかを決める。これはユーザー名ではなく、 OpenVPN が自分で読むパスワードファイルへのポインタでもない。

二番目の語が選ぶもの

設定行はプラグインのパスと一つの引数を取る:

plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn

その引数はサービスの名前として PAM ライブラリに渡され、/etc/pam.d/openvpn のスタックが実行される。そこに login と書けば、代わりにインタラクティブなログインポリシーが使われ、そのポリシーがお使いのディストリビューションで含むモジュールが適用される。

インストール済みパッケージが提供するプラグインのパスを使い、別のホストからコピーしたパスは使わない。ファイル名とディレクトリはディストリビューションによって異なり、誤ったパスは認証時ではなく起動時にプラグイン読み込みエラーで失敗する。

スタックが実際にアカウントを読む場所

PAM はディスパッチャーである。サービスファイルはモジュールを順に列挙し、最初に答えられるモジュールが結果を決める。pam_unix を呼ぶスタックはローカルのアカウントを読み、LDAP や RADIUS のモジュールを呼ぶスタックは資格情報をまったく別の場所へ送る。

サービス名が解決されるファイルを、そこに含まれるものも含めて読む:

cat /etc/pam.d/openvpn
grep -H pam_ /etc/pam.d/openvpn /etc/pam.d/common-auth

スタックがディレクトリに委譲するなら、ローカルアカウントを追加しても何も変わらない。ローカルアカウントを読むなら、ディレクトリにユーザーを作っても何も変わらない。アカウントはスタックが見る場所に存在しなければならず、これらの報告のほとんどではそれが診断のすべてである。

一回の試行、二つのログ

一つの失敗した接続を両側で突き合わせる。OpenVPN のログはプラグインの結果とクライアントの拒否を示し、システムの認証ログはどのモジュールが動き何を決めたかを示す。同じ時間枠で両方を読むことが、サービスファイルの欠落とバックエンドのタイムアウトを分ける。認証ログに空白があれば、スタックにはまったく到達していない。

journalctl -u openvpn-server@server --since "-2 min"
journalctl -t sshd -t sudo --since "-2 min"

PAM を話すユーティリティでサービスを直接試し、VPN とスタックを同時にデバッグしないようにする。同じサービス名と同じアカウントでの直接テストが成功すれば、問題はデーモンが資格情報を渡す方法に絞られ、アカウント自体ではない。

pamtester openvpn alice authenticate

直接テストがコンソールで機能するのと同じ資格情報で失敗するなら、スタックは想定したアカウントの取得元を読んでいない。成功するなら、プラグインが行う対話とクライアントが実際に送ったものを見る。わざと間違ったパスワードでもう一度実行し、拒否とモジュールエラーの違いを確認する。その二つの結果は VPN のログでは同じに見え、ここではまったく異なる。

専用のサービスはログインの編集に勝る

VPN の要件が対話的なログインと異なるとき、通常は異なるのだが、VPN に専用のサービスファイルを与える。login や common-auth を編集すると、それらを含むすべてのプログラムのポリシーが変わり、無関係なログイン問題をデバッグする次の人があなたの変更を引き継ぐ。

必要なモジュールを小さなサービスファイルにコピーし、順序を明示し、誰が所有するかを記す。パスワードのリセットが効果がないように見えるときに確認すべきはそのファイルである。

クライアントが送るもの、送らないもの

クライアントは対応するプロンプトまたはファイルを通じてユーザー名とパスワードを提供する。サーバープラグインはその値を PAM の対話に渡し、サーバーの設定から読むのではない。パスワードを定義しているように見えるサーバー側の行はそうしておらず、プロファイルの編集でアカウントが作られることもない。

ユーザー名とパスワードはクライアント証明書と共存できる、そして PAM を有効にすることは証明書の検証をやめる理由ではない。配備が意図した層を保ち、アカウントの取得元だけを直す。

受け入れは両面である:想定したアカウントは成功し、拒否されるべきアカウントは依然として失敗する。 auth-pam プラグインの README は、サービスの引数と前面に置けるバックエンドを文書化しており、構築しようとしている構成を確認する場所はそこである。

関連記事