WordPress の管理画面を IP アドレスで制限することは Brute Force Attack に対して有効です。
たとえば Nginx を使っている場合、以下のような設定で許可された IP アドレス以外からのログインを拒否することができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
location /wp-admin {
allow 192.168.0.1;
deny all;
:
}
location = /wp-admin/admin-ajax.php {
allow all;
:
}
location = /wp-login.php {
allow 192.168.0.1;
deny all;
:
}
}
また、IP アドレスによるログイン制限を行うプラグインもいくつかあるようです。
ただし、これらの方法だとリバースプロキシ配下のサーバの場合、期待した動作になりません。
# リバースプロキシサーバからは、実際にアクセスしてきたクライアントの IP アドレスは http ヘッダ X-Forwarded-For にセットされて来るため
そこで、簡単な PHP スクリプトを書いて対応しました。
IP アドレスをチェックする PHP スクリプト
同じディレクトリにある .allowed_ip ファイルを読み込んで、許可されている IP アドレスからのアクセスかどうかをチェックするスクリプトを gist で公開しました。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php
class ip_check {
const ALLOWED_IP_FILE = '.allowed_ip';
static function get_remote_ip() {
$remote_addr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
if ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
$forwarded_ips = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
$remote_addr = $forwarded_ips[0];
unset( $forwarded_ips );
}
return $remote_addr;
}
static function get_allowed_ip( $file_name = '' ) {
if ( empty($file_name) )
$file_name = dirname(__FILE__) . '/' . self::ALLOWED_IP_FILE;
if ( !file_exists($file_name) )
return false;
$allowed_ips = explode("\n", file_get_contents( $file_name ));
return $allowed_ips;
}
static function is_allowed_ip( $file_name = '' ) {
$remote_addr = self::get_remote_ip();
if ( ($allowed_ips = self::get_allowed_ip($file_name)) && is_array($allowed_ips) ) {
foreach( $allowed_ips as $allowed_ip ) {
if ( empty($allowed_ip) )
continue;
if ( self::is_ip_range($remote_addr, $allowed_ip) )
return true;
}
}
return false;
}
static function is_ip_range( $ip, $range ) {
$ip = trim($ip);
$range = trim($range);
if ( !($ip = ip2long($ip)) )
return false;
if( strchr($range, '/') ){
list($net, $mask) = split('/', $range);
if ( !($net = ip2long($net)) )
return false;
if ( is_numeric($mask) )
$mask = long2ip(bindec(str_repeat('1', $mask) . str_repeat('0', 32 - $mask)));
if ( !($mask = ip2long($mask)) )
return false;
return ( ($ip & $mask) === ($net & $mask) ) ? true : false;
} elseif ( strchr($range, '-') ) {
$range = split('-', $range);
if ( !($range[0] = ip2long($range[0])) )
return false;
if ( !($range[1] = ip2long($range[1])) )
return false;
return ( $range[0] <= $ip && $ip <= $range[1] ) ? true : false;
} elseif ( $range = ip2long($range) ) {
return ( $range === $ip ) ? true : false;
}
return false;
}
}
View the code on Gist .
.allowed_ip には、以下のように許可したい IP アドレスを列挙します。
IP アドレスはマスク指定もできます。
1
2
3
192.168.0.1
192.168.1.0/24
192.168.2.1-192.168.2.254
これらを wp-config.php の先頭で読み込んで、ダッシュボードへのリクエストの場合は IP アドレスのチェックを行ってください。
こんな感じです。