3
votes

Trying to go from older allow, deny, order syntax to the new one to secure WordPress admin section, but I can't get it to recognize my IP.

This is what my .htaccess file contains in /wp-admin folder.

ErrorDocument 401 default
ErrorDocument 403 default

# Disallow access for everyone except these IPs
<RequireAny>
    Require ip 50.153.218.4
</RequireAny>

# Allow plugin access to admin-ajax.php around password protection
<Files admin-ajax.php>
    <RequireAll>
        Require all granted
    </RequireAll>
</Files>

And this is what I have in .htaccess in the root under the WordPress mod rewrite info.

# Protect WordPress
ErrorDocument 401 default
ErrorDocument 403 default

<Files wp-login.php>
    <RequireAny>
        Require ip 50.153.218.4
    </RequireAny>
</Files>

But I just keep getting 403 Forbidden error. When I add Require All Granted under the IP, it works fine, but that opens it up to every user. It seems like apache is just not reading my ip correctly? Anyone have any idea what I'm doing wrong?

1
β€œIt seems like apache is just not reading my ip correctly?” – well, have you checked what IP is used for your requests? Maybe the connection is made via IPv6 instead of IPv4 or something? - CBroe
@CBroe I've checked my IP in PHP and Apache logs and it seems correct so that part doesn't seem to be the issue. - zen
so, does it work with the old "deny from all, allow ..." syntax? - Sebastian Schmid
@SebastianSchmid surprisingly, it does not work with old syntax either. That's how I knew I had to fix it. Because it used to work with old syntax, but once I upgraded apache, it stopped working so I figured I had to use the new syntax. I also installed remoteip module thinking that might be the fix, but no go. :( - zen

1 Answers

8
votes

Your syntax looks perfectly fine to me.

The only reason I can think that apache might not be reading the user's IP correctly is if you're behind a proxy or load balancer. If that is the case you would use X-Forwarded-For instead of ip. In PHP, you can confirm if you're behind a proxy by comparing $_SERVER['REMOTE_ADDR'] and $_SERVER['HTTP_X_FORWARDED_FOR'].

If that is not the issue so you might have better luck finding an answer at ServerFault.

I can offer you some workarounds though. The easiest solution may be to use one of several WordPress security plugins that allow you to restrict access to the backend by IP address.

Alternatively, in your theme or in a plugin you can implement this same sort of authentication logic:

add_action('init', function() {
    $allowed_ips = array('50.153.218.4');
    if(is_admin() || $GLOBALS['pagenow'] == 'wp-login.php') {
        if( !DOING_AJAX && !in_array($_SERVER['REMOTE_ADDR'], $allowed_ips) ) {
            wp_die('', 'Forbidden' array(
                'response' => 403
            ));
        }
    }
});

Update: From the comments it looks like there is a proxy involved. This should work:

ErrorDocument 401 default
ErrorDocument 403 default

SetEnvIF X-Forwarded-For "50.153.218.4" AllowIP

# Disallow access for everyone except these IPs
<RequireAny>
    Require env AllowIP
</RequireAny>

# Allow plugin access to admin-ajax.php around password protection
<Files admin-ajax.php>
    <RequireAll>
        Require all granted
    </RequireAll>
</Files>

and

# Protect WordPress
ErrorDocument 401 default
ErrorDocument 403 default

SetEnvIF X-Forwarded-For "50.153.218.4" AllowIP

<Files wp-login.php>
    <RequireAny>
         Require env AllowIP
    </RequireAny>
</Files>

You should also be able to use a similar method using the "Allow, Deny" syntax.