2026年8月18日

2026年8月18日

WordPressの管理画面URLを変更してセキュリティを強化する方法

はじめに

WordPressの管理画面URL(/wp-admin//wp-login.php)は攻撃者に広く知られており、Botが自動的にスキャンしてきます。URLを変更することで攻撃の対象になりにくくなります。ただし、URL変更だけではセキュリティの根本的な解決策にはならず、他の対策と組み合わせることが重要です。

症状・原因

  • アクセスログにPOST /wp-login.phpが毎日大量に記録されている
  • ログイン試行制限によって正規の管理者がロックされることがある
  • 見知らぬIPからのwp-admin/wp-loginへのアクセスが大量にある

解決手順

ステップ1:Nginxでログインページをリダイレクトする

# /etc/nginx/sites-available/example.com
# 新しいログインURL: /secret-door-2024

server {
    # 新しいログインURLの設定
    location = /secret-door-2024 {
        # 内部的にwp-login.phpとして処理
        rewrite ^ /wp-login.php last;
    }

    # wp-login.phpへの直接アクセスをブロック
    location = /wp-login.php {
        # Refererが新しいURLからのリクエストのみ許可
        if ($http_referer !~ "^https://example.com/(secret-door-2024|wp-admin)") {
            return 403;
        }
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/wp-login.php;
    }

    # /wp-admin/への直接アクセスは許可(ログイン後のリダイレクト先のため)
    location /wp-admin/ {
        try_files $uri $uri/ /index.php$is_args$args;
    }
}

ステップ2:WordPressコードでログインURLを変更する

// functions.php: ログインURLを動的に変更
define('CUSTOM_LOGIN_SLUG', 'my-login-2024'); // 変更するスラッグ

// カスタムログインURLへのルーティング
add_action('init', function(): void {
    $slug = CUSTOM_LOGIN_SLUG;

    // カスタムURLへのアクセス: wp-login.phpとして処理
    if (isset($_SERVER['REQUEST_URI'])
        && str_ends_with(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), "/{$slug}")) {
        // wp-login.phpを読み込む
        global $pagenow;
        $pagenow = 'wp-login.php';
        do_action('login_init');
        require ABSPATH . 'wp-login.php';
        die;
    }

    // wp-login.phpへの直接アクセスをブロック
    if (!is_admin()
        && str_ends_with($_SERVER['REQUEST_URI'] ?? '', 'wp-login.php')
        && !isset($_REQUEST['action'])) {
        wp_redirect(home_url('/404'), 302);
        die;
    }
}, 1);

// ログインURLを新しいスラッグに書き換え
add_filter('login_url', function(string $login_url, string $redirect, bool $force_reauth): string {
    return home_url(CUSTOM_LOGIN_SLUG . ($redirect ? '?redirect_to=' . urlencode($redirect) : ''));
}, 10, 3);

// 管理者バー・メールのURLも変更
add_filter('logout_url', function(string $logout_url): string {
    return str_replace('/wp-login.php', '/' . CUSTOM_LOGIN_SLUG, $logout_url);
});

ステップ3:wp-adminへのアクセスを制限する

// 未ログインユーザーのwp-adminアクセスをリダイレクト
add_action('admin_init', function(): void {
    // WordPressの自動Ajaxリクエストは除外
    if (defined('DOING_AJAX') && DOING_AJAX) return;

    // ログイン済みユーザーのみ許可
    if (!is_user_logged_in()) {
        wp_redirect(home_url('/'), 302);
        die;
    }
}, 1);

// wp-adminへのリクエストをIPでフィルタリング
add_action('admin_init', function(): void {
    $allowed_ips = get_option('admin_allowed_ips', []);

    if (empty($allowed_ips)) return; // IP制限未設定なら全員許可

    $client_ip = sanitize_text_field(
        $_SERVER['HTTP_CF_CONNECTING_IP']
        ?? $_SERVER['REMOTE_ADDR']
        ?? ''
    );

    if (!in_array($client_ip, $allowed_ips, true)) {
        wp_die('Access Denied - Your IP is not authorized.', 403);
    }
});

// 設定ページで許可IPを管理
add_action('admin_menu', function(): void {
    add_options_page('管理者IP設定', '管理者IP設定', 'manage_options', 'admin-ip-settings', function(): void {
        if ($_POST['save_ips'] ?? false) {
            check_admin_referer('save_admin_ips');
            $ips = array_filter(array_map('trim', explode("\n", $_POST['admin_ips'] ?? '')));
            update_option('admin_allowed_ips', $ips);
            echo '<div class="notice notice-success"><p>保存しました</p></div>';
        }

        $current_ips = implode("\n", get_option('admin_allowed_ips', []));
        echo '<div class="wrap"><h1>管理者IPホワイトリスト</h1>';
        echo '<form method="post">';
        wp_nonce_field('save_admin_ips');
        echo '<textarea name="admin_ips" rows="10" cols="40">' . esc_textarea($current_ips) . '</textarea><br>';
        echo '<p>現在のIP: ' . esc_html($_SERVER['REMOTE_ADDR'] ?? '') . '</p>';
        submit_button('保存', 'primary', 'save_ips');
        echo '</form></div>';
    });
});

ステップ4:ロックアウト時の緊急アクセス方法を準備する

# 緊急時: WP-CLIで管理者パスワードをリセット
wp user update 1 --user_pass="new-secure-password"

# カスタムログインURLを忘れた場合: wp-config.phpを確認
grep -n "CUSTOM_LOGIN_SLUG" /var/www/html/wp-config.php

# FTP/SSH経由でfunctions.phpを一時的に無効化
mv /var/www/html/wp-content/themes/mytheme/functions.php \
   /var/www/html/wp-content/themes/mytheme/functions.php.bak

# カスタムログインURLをwp-config.phpに移動(より安全)
# wp-config.php に追記
define('CUSTOM_LOGIN_SLUG', 'my-login-2024');

ステップ5:設定を確認する

# 新しいログインURLにアクセスできるか確認
curl -I https://example.com/my-login-2024
# HTTP/2 200 が返れば成功

# 旧URLがブロックされているか確認
curl -I https://example.com/wp-login.php
# HTTP/2 403 または 301 が返れば成功

# wp-adminのリダイレクト確認(未ログイン時)
curl -I https://example.com/wp-admin/
# HTTP/2 302 → / にリダイレクトされれば成功

# アクセスログでボットアクセスが減ったか確認
grep "wp-login.php" /var/log/nginx/access.log | wc -l

注意事項

  • ロックアウトリスク: URLを変更後は必ず新しいURLにアクセスできることを確認してください。SSH/FTPアクセスを失うと回復困難です
  • キャッシュのクリア: ページキャッシュやブラウザキャッシュが古いURLを保持している場合があります
  • メールリンク: パスワードリセットメールのURLが正しく新しいログインURLを指しているか確認してください
  • セキュリティ本質: URLの難読化は「Security through Obscurity(隠蔽によるセキュリティ)」です。強力なパスワード・2FA・試行回数制限と必ず組み合わせてください

まとめ

管理画面URLの変更は「Nginxでのリダイレクト設定→WordPressのlogin_urlフィルター変更→wp-adminのIP制限→緊急アクセス手段の準備」の順で実装します。単独では効果が限定的なため、reCAPTCHAや試行回数制限と組み合わせてください。関連記事:ログイン試行回数制限の設定方法

お気軽にご相談ください

お見積りへ お問い合わせへ