管理画面のログイン試行が並んだアクセスログを見ながら、アクセス制限をかけようと落ち着いて考えている一人運用の保守担当者

管理画面のアクセス制限|IP制限とBasic認証の基本と使い分け

深夜、なんとなくアクセスログを眺めていて、wp-login.php/admin に見覚えのないログイン試行がずらりと並んでいるのを見つける。実害は出ていない。パスワードも一応強くしてある。でも、なんだか落ち着かない——そんな夜、ありませんか。

そのモヤモヤは、正しい感覚です。管理画面は、URLさえ分かれば世界中の誰でもログイン画面を開けてしまう場所だからです。パスワードが強くても、「試し続けられる入口が開いている」こと自体が、じわじわ気力を削ってきます。

この記事では、その入口の手前にもう一枚の扉を置く方法——IP制限Basic認証を、それぞれの向き・不向きと、一人運用でも自分を締め出さずに入れる順番で、一緒に整理していきます。

結論:管理画面の守りは、①固定IPの拠点からしか触らないなら「IP制限」→ ②外出先やリモートからも触るなら「Basic認証」→ ③両方あるなら「社内IPは素通り・それ以外はパスワード」(satisfy any / RequireAny の3択で考えます。どれも本来のログイン認証の代わりではなく、その手前に置く一枚目の扉です。まず1か所、/adminwp-login.php に入れてみるところからで十分です。

設定ファイルの書式(nginx / Apache / .htaccess)や置き場所は、環境やバージョンで違います。この記事の考え方と順番を土台に、細かい記述は必ず自分の環境の公式情報で確認してください。

なぜ管理画面は狙われやすいのか

責める話ではなく、理由が分かると落ち着いて手を動かせるので、一言だけ。

管理画面のURLは、たいてい決め打ちできます。WordPressなら /wp-login.php/wp-admin/、よくある管理システムなら /admin/administrator/manage。攻撃側は、狙う相手を探す必要すらありません。世界中のサーバーに対して、その決まったURLを自動で叩いて回るだけです。

つまり、あなたのサイトが狙われているというより、「開いている管理画面」が機械的に片っ端から拾われている状態です。ログに並ぶ大量のログイン失敗は、あなたの落ち度ではありません。

だからこそ、効くのはシンプルな一手です。ログイン画面にたどり着く手前で止める。パスワードを試す土俵にすら上がらせない。これがアクセス制限の役割です。

3つの守り方と、その使い分け

管理画面のアクセス制限を、IP制限・Basic認証・両方の併用の3つに分けて使い分けを示した図
触る場所が固定ならIP制限、どこからでも触るならBasic認証、両立させたいなら併用

どれが正解、という話ではありません。「その管理画面を、誰が・どこから触るか」で決まります。

① IP制限:触る場所が決まっているなら、これが一番強い

「管理画面は社内からしか触らない」。そう言い切れるなら、IP制限がもっともシンプルで、もっとも効きます。パスワードを盗まれても、そもそも接続元が違えば入れないからです。

nginx なら、対象の場所に許可するIPを並べて、それ以外を落とします。

location /admin/ {
    allow 203.0.113.10;      # 事務所の固定IP
    allow 198.51.100.0/24;   # 範囲で許可する場合
    deny  all;               # 上記以外はすべて拒否
}

Apache 2.4 なら Require ip を使います。

<Location "/admin">
    Require ip 203.0.113.10 198.51.100.0/24
</Location>

(Apache 2.2 までの Order allow,deny 形式は 2.4 では非推奨です。今から書くなら Require 系で揃えておくと、後で困りません。)

向いているとき:事務所や拠点の固定IPからしか作業しない場合。 向かないとき:リモートワークやモバイル回線など、接続元IPが変わる場合。ここで無理にIP制限をかけると、自分が入れなくなります。

② Basic認証:どこからでも触るなら、手前にもう一枚

接続元が固定できないなら、Basic認証(ブラウザに小さなログイン窓が出る、あの仕組み)で手前に一枚かぶせます。本来のログイン画面にたどり着く前に、別のIDとパスワードを求める形です。

nginx の例です。

location /admin/ {
    auth_basic           "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

パスワードファイルは htpasswd コマンドで作ります(保存先は、公開ディレクトリのに置きます)。

# 新規作成(-c は初回のみ。既存ファイルに -c を付けると中身が消えます)
htpasswd -c /etc/nginx/.htpasswd admin
# 2人目以降を追加するときは -c を付けない
htpasswd /etc/nginx/.htpasswd staff

大事な前提:Basic認証のID・パスワードは、暗号化ではなくbase64でエンコードされているだけです。読める形で流れると思ってください。ですから、HTTPS(TLS)が有効な場所でだけ使う。これは条件というより、前提です。

向いているとき:接続元が変わる、外出先からも触る、協力会社にも渡したい。 向かないとき:これ単体を「本気の認証」として頼ること。あくまで自動化された無差別アクセスを、ログイン画面の手前で振り落とすためのものです。

③ 併用:社内は素通り、外からはパスワード

実務でいちばん収まりがいいのが、これです。「事務所からは今まで通りサッと入れて、それ以外の場所からはBasic認証を求める」。

nginx なら satisfy any(どちらか一方を満たせばOK)で書けます。

location /admin/ {
    satisfy any;             # IPか、パスワードか、どちらか通ればOK

    allow 203.0.113.10;
    deny  all;

    auth_basic           "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Apache 2.4 なら <RequireAny> が同じ考え方です。

<Location "/admin">
    <RequireAny>
        Require ip 203.0.113.10
        Require valid-user
    </RequireAny>
</Location>

日々の作業のじゃまをせず、外からの無差別アクセスだけを止められます。「厳しくすると自分がつらい」を回避できるのが、この形の良いところです。

つまずきやすいところ(先に知っておくと安心)

ここが、実際に入れてみたときに「あれ?」となりやすい場所です。先に知っておくと、慌てずに済みます。

プロキシやCDNの後ろだと、IP制限が効かない(一番多い落とし穴)

ロードバランサー、リバースプロキシ、CDN——何かを挟んでいる場合、サーバーから見た接続元IPは「そのプロキシのIP」になります。つまり、allow に書いた事務所のIPは一致せず、全員が拒否されるか、逆に全員が通ってしまいます。

この場合、本当の接続元は X-Forwarded-For ヘッダに入っています。それを接続元として扱うには、nginx なら ngx_http_realip_module、Apache なら mod_remoteip を使います。

set_real_ip_from 10.0.0.0/8;      # 信頼するプロキシの範囲だけを書く
real_ip_header   X-Forwarded-For;

ここは慎重にX-Forwarded-For は、クライアントが自由に付けられるヘッダです。信頼できるプロキシの範囲を正しく限定せずに設定すると、接続元IPを詐称されて、IP制限そのものが素通しになります。信頼する範囲は、自分が挟んでいるプロキシのIPだけに絞ってください。

なお、IP制限はもっと手前でかけられるなら、そのほうが確実です。クラウドのセキュリティグループ、ファイアウォール、CDN側のWAFやアクセス制御。Webサーバーまで届く前に落とせるなら、そちらを優先しましょう。

Basic認証をかけると、思わぬものが壊れる

/wp-admin/ にBasic認証をかけたら、サイトの表側(フロント)の一部が動かなくなった——これはWordPressで定番のつまずきです。原因は /wp-admin/admin-ajax.php。名前は管理画面の下にありますが、フロント側の機能からも呼ばれます。ここまで一緒にブロックしてしまうと、表側が壊れます。

だから、admin-ajax.php は認証の対象から外します。

location = /wp-admin/admin-ajax.php {
    auth_basic off;   # ここだけ素通しにする
}

同じ理屈で、こんなものも巻き込まれがちです。

「管理画面を守ったら、別のところが静かに止まっていた」が一番つらいパターンです。かけた直後に、表側とAPI連携をひと通り触って確認するところまでをセットにしておきましょう。

固定IPがない、でもIP制限したい

「リモートだから固定IPがない」。よくある悩みですが、選択肢はあります。

一度に理想形を目指さなくて大丈夫です。今日は「誰でも開ける」状態から一歩出る。それで十分効きます。

影響:この一手で、何が変わるか

小さな設定ですが、変わることははっきりしています。

逆に、開いたままにしていると、実害が出ていなくても「試され続ける入口」を抱えたままになります。今日ひとつ閉じておくと、その落ち着かなさを減らせます。

明日やること:1か所だけ、締め出されない順番で

全部の管理画面を一度に設定する必要はありません。明日できる、いちばん小さくて安全な一歩です。

  1. 守る場所を1か所だけ決める。いちばん気になっているURL(/wp-login.php/admin)で十分です。
  2. 今の接続元IPを確認する。自分が今どのIPで出ているかを調べます(curl ifconfig.me など)。プロキシやCDNを挟んでいるなら、サーバーのアクセスログに実際に記録されているIPを見るのが確実です。
  3. 設定ファイルのバックアップを取る。戻すときの命綱です。
  4. 文法チェックしてから反映する。nginx なら nginx -t、Apache なら apachectl configtest。ここでエラーを潰しておくと、反映で足をすくわれません。
  5. 別のブラウザ(またはシークレットウィンドウ)で、実際に開いて確認する。自分が入れること、そして表側とAPI連携が壊れていないことを、両方見ます。

もし締め出されても大丈夫です。Webサーバーの設定は、SSHやコンソールから元に戻せます。SSHの入口まで一度に絞らなければ、戻る道は残ります。アクセス制限は、一度にひとつずつ。これが安全のコツです。

うまくいったら、その手順を自分の環境用のメモに1枚残しておきましょう。2か所目からは、なぞるだけになります。

「管理画面のアクセス制限」チェックリスト

コピーして、自分の環境に当ててみてください。

最低ラインは、「管理画面が、誰でも開ける状態ではない」——ここさえ超えていれば、無差別のログイン試行はほぼ止まります。

全部に○が付かなくても大丈夫です。まずは1か所、扉を一枚置くところから始めましょう。

よければ、こちらも

アクセス制限は、サーバーの「入口を絞る」話の一部です。あわせて整理しておくと、次の点検がぐっと楽になります。

管理画面のアクセス制限を設定し終えて、椅子に背を預けて安心して一息ついている一人運用の保守担当者

管理画面のアクセス制限は、後回しにしがちなわりに、設定そのものは数行で終わります。重かったのは作業量ではなく、「触って壊したらどうしよう」という迷いのほうだったと思います。

戻せる形で、1か所ずつ。それだけで、ログに並んでいた大量のログイン試行は、静かに意味を失っていきます。今日は1か所に扉を一枚置けたら、それで十分な前進です。あの落ち着かない夜が、少し減りますように。

ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。