ETBS Account Guard
ETBS Account Guard — ログイン名の保護と、権限・ユーザーごとのアクセス制限(IP/BASIC 認証)で、サイトを管理するアカウントを守る WordPress プラグイン
by ETBS (DAI) · github.com/etbsjp/etbs-account-guard · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/etbsjp/etbs-account-guard/archive/refs/heads/dist.zipサイトを管理するアカウントを守る WordPress プラグインです。 ログインしていない人に、ユーザーのログイン名(とログイン名から作られる URL 用の名前)を渡さないようにします。
なぜ必要か
WordPress は、ログインしなくても見られる次のような場所で、ユーザーのログイン名やそこから作られた名前を出しています。
- REST API のユーザー一覧(
/wp-json/wp/v2/users) - oEmbed の投稿者(
author_url/author_name) - ユーザーのサイトマップ(
wp-sitemap-users-1.xml) - コメントや投稿者ページの HTML のクラス名
?author=1の転送先(/author/<名前>/)- ログイン画面の文言(「そのユーザー名は登録されていません」と「パスワードが違います」が別々に出る)
ログイン名が分かると、あとはパスワードを当てるだけになり、総当たりの的になります。
できること(ログイン名の保護)
「設定 > ETBS Account Guard」の「ログイン名の保護」タブで、項目ごとに ON/OFF できます。 有効化した時点で、投稿者ページ以外はすべて ON です。
| 項目 | 何をするか | 既定 |
|---|---|---|
| REST API | ログインしていない人には、ユーザー関連のルート(/wp/v2/users 配下)を返しません。投稿に埋め込まれる投稿者(_embed)も同じです。存在する ID と存在しない ID で応答が同じになります。ログイン中(ブロックエディタ)は従来どおりです |
ON |
| oEmbed | 埋め込みの投稿者名と投稿者の URL を、サイト名とトップの URL にします | ON |
| サイトマップ | ユーザーのサイトマップを出しません | ON |
| クラス名 | 登録ユーザーのコメントの comment-author-<名前> と、投稿者ページの author-<名前> を外します。ID 入りのクラス(author-1 など)は残します |
ON |
| 投稿者 ID のリンク | /?author=1 をトップへ転送します。管理画面の投稿者での絞り込みには影響しません |
ON |
| ログインエラー | 存在しないユーザー名とパスワードの誤りで、同じ文言を出します。アプリケーションパスワード(REST API の Basic 認証)の失敗も同じエラーにします。パスワード再発行では、登録されていないユーザー名やメールアドレスを入力しても、登録済みのときと同じ画面を表示します(登録済みのユーザーには、従来どおり再設定のメールが届きます)。他のプラグインの画像認証やログインロックのエラーはそのまま出します | ON |
| 投稿者ページ | ログインしていない人に対して、投稿者ページ(/author/<名前>/)を 404 にします。テーマが投稿者ページへのリンクを出している場合、そのリンクが「ページが見つかりません」になるので、既定は OFF です。オンにする前に、サイトの投稿で投稿者名をクリックし、アドレスに /author/ を含むページが開くか(テーマが投稿者ページへリンクしているか)を確かめてください。ログイン中は従来どおり表示されるので、結果はブラウザーのプライベートウィンドウで確かめてください |
OFF |
同じタブに、表示名またはニックネームがログイン名と同じユーザーの一覧を出します(フィードの dc:creator などにそのまま出るため)。
自動では変えません。一覧の各行からユーザーの編集画面を開き、ニックネームと「ブログ上の表示名」を変えてください。
できること(アクセス制限・IP 制限)
「設定 > ETBS Account Guard」の「アクセス制限」タブで、権限ごと・ユーザーごとに IP 制限を求められます。 administrator は権限単位では常に制限なしです(特定の管理者を制限したいときは、そのユーザーの編集画面で設定します)。 ユーザー自身の設定は権限の設定より優先し、複数の権限を持ち食い違う場合は、求められているものを全部課します。
| 場面 | 動作 |
|---|---|
| ログイン時(wp-login.php・XML-RPC など) | 一覧外の IP からの対象ユーザーは、誤ったパスワードと同じ文言で拒否します。理由は明かしません。画像認証プラグイン(SiteGuard WP Plugin など)の判定より後で行うため、画像認証の失敗と IP 制限の拒否は見分けが付きません |
| ログイン後の毎回のアクセス(管理画面・admin-ajax.php・admin-post.php・フロント・REST API) | 一覧外の IP からのアクセスは、そのセッションだけ破棄して未ログインとして続けます。エラー画面で止めないので、ログイン不要の公開ページやフォームは訪問者と同じように使えます |
| アプリケーションパスワード | 対象ユーザーでは使えなくします。REST API のリクエストごとにも判定します |
IP の一覧は、サイトに1つの一覧と、ユーザーごとに追加した一覧を合わせたものです。1行に1つ、IPv4・IPv6の単独のアドレスまたは CIDR の範囲を書けます。# の後ろはメモです。
判定はサーバーから見えている接続元(REMOTE_ADDR)だけで行い、X-Forwarded-For などのヘッダーは使いません(訪問者自身が書き換えられるため)。
「アクセス制限」タブの保存や、ユーザー編集画面での本人の設定変更は、制限されていない管理者(または設定を管理できる他のユーザー)が1人もいなくなる設定や、保存する本人が今の接続元では満たせない設定を、理由付きで拒否します。
「拒否の記録」タブに、直近100件の拒否を表示します。
アクセス制限自身が想定外の状態になったときは、制限を止めて通し、「アクセス制限」タブとダッシュボードのウィジェットに警告を出します(締め出しを避けるため)。
非常用スイッチ
アクセス制限で誰も入れなくなった場合は、wp-config.php に define( 'ACGD_DISABLE_RESTRICTION', true ); を追加すると止められます。止まるのはアクセス制限だけで、ログイン名の保護は動作し続けます。
やらないこと
二段階認証・ログイン試行の回数制限・画像認証・WAF は含みません。専用のセキュリティプラグインをお使いください。
?author= の転送とログイン画面の文言は、それらのプラグインと重なることがありますが、両方入れても害はありません。
BASIC 認証(「制限なし」「IP 制限」に続く3つ目のモード)は今後の更新で追加予定で、まだ選べません。
既知の限界
- WooCommerce のマイアカウントの「パスワード再発行」フォームは独自の文言を出すので、1.0.0 の対象外です。 マイアカウントのログインフォームは対象です。
- テーマが出す投稿者ページへのリンク(
/author/<名前>/)には、URL 用の名前がそのまま入ります。 - SiteGuard WP Plugin と併用するときは、SiteGuard の「ログイン詳細エラーメッセージの無効化」を ON のままにしてください(単一サイトでの SiteGuard の既定は ON です)。 OFF にすると、SiteGuard の画像認証のエラーの文言が、存在するアカウントにだけ、また別に、IP 制限の対象アカウントにだけ出ます。これは SiteGuard 自身の挙動で、このプラグインでは変えられません。
- パスワード再発行で、存在するアカウントへのメールを送れなかったとき(メール送信の失敗)は、そのエラーをそのまま出します。サイトのメール送信の不具合に気付けるようにするためです。 このエラーと、メールを送るかどうかで生じる応答時間の差は残ります。
- ログインでは、WordPress がアカウントのあるときだけパスワードを照合するため、アカウントがあるときと無いときで応答時間に差が出ます。パスワード再発行の応答時間の差と同じく、まだ塞いでいません。
- BASIC 認証はまだ使えません。選べるのは「制限なし」と「IP 制限」だけです。
削除したとき
設定(ログイン名の保護のスイッチ、アクセス制限の権限ごと・ユーザーごとのモードと IP 一覧)は消しません。入れ直したときに、それまでの設定がそのまま戻ります。 同梱の更新チェッカーが保存する更新確認の状態(次の確認で作り直される一時的なもの)と、アクセス制限の拒否の記録は消します。 このプラグイン自身は、独自のテーブルや cron を持ちません。
動作要件
WordPress・PHP のバージョンの下限は設けていません。