• I’m trying to set up a site that allows certain IPs to access it regardless, and if a client is connecting from an IP not in that range, to force authentication. The problem is that the plugin appears not to be detecting the client IP address properly, even though it’s provided to the server via an X-Forwarded-For: header.

    My network architecture is a bit more complicated than some — clients connect to a load-balancer (an F5 hardware device), which connects to a Varnish cache, which then finally connects to the Web server (pretty standard Apache on Red Hat), which then passes the request to php-fpm). The IP info appears to be making it back to the Web server — $_SERVER[‘REMOTE_ADDR’] correctly reflects the IP of the Varnish cache that’s actually doing the connecting (this is the IP I don’t want to use), and $_SERVER[‘HTTP_X_FORWARDED_FOR’] correctly reflects the client IP, before any firewalling, NAT, and so on. (This came from creating a page inside the wp-admin/ directory that just calls phpinfo() and verifying that its contents look correct. If there’s a scenario where WordPress thinks things are different from vanilla PHP, I wouldn’t know about it.)

    My read of the code in the Restricted Site Access plugin’s get_client_ip_address() function is that the plugin should see the HTTP_X_FORWARDED_FOR header first, and use the contents of that server variable as the perceived client IP address. Unfortunately, it appears not to be doing so — I don’t know if it’s reading the headers in the wrong order (and thus pulling, say, REMOTE_ADDR), or if all these headers are being ignored (and thus probably defaulting to the “real” IP-level client info, which would be the same as REMOTE_ADDR in this case).

    In the plugin-specific management settings, when I click “Add My Current IP Address”, the IP used is the Varnish IP, not the correct client IP. This would seem to verify that get_client_ip_address() is ultimately responsible, since that button just calls it and uses its output to populate the box.

    Unfortunately, I’m not really sure how to further debug this. Any suggestions on how to dig into this function, or how to override the IP detection, would be greatly appreciated.

Viewing 4 replies - 1 through 4 (of 4 total)
  • Tung Du

    (@dinhtungdu)

    Hi @desmith, in the get_client_ip_address() method, the headers listed there are processed one by one, and it returns the first valid IP immediately. So if HTTP_X_FORWARDED_FOR contains the correct and valid IP, the only value can take over it comes from HTTP_CLIENT_IP. REMOTE_ADDR has the least priority when detecting client IP. Can you check if HTTP_CLIENT_IP has value?

    It’s impossible to cover all network architecture, so I will discuss with our team to see if we should add a filter to the headers in get_client_ip_address(). I think it will be the most flexible solution for complicated networks.

    Tung Du

    (@dinhtungdu)

    @desmith, for your issue, you can fix temporarily by removing the HTTP_CLIENT_IP or unset it.

    Or you can create a mu-plugin to avoid modifying the main plugin, mu-plugin is loaded first so you can use it to alter $_SERVER, like this:

    $_SERVER['HTTP_CLIENT_IP'] = $_SERVER['HTTP_X_FORWARDED_FOR'];

    • This reply was modified 5 years ago by Tung Du.
    Thread Starter David E. Smith

    (@desmith)

    I think I’ve found the real problem.

    When the plugin looks through the headers, to identify the apparent client IP address, it does so with the FILTER_FLAG_NO_PRIV_RANGE flag, to exclude private IP addresses. Which is most of my users, as the site I’m trying to restrict is primarily an intranet site. So all the validations fail, and I end up getting the REMOTE_ADDR value as it’s the last one in the list. And in my case, REMOTE_ADDR is the IP of a cache server in front of the Web server. (Clients connect to a load-balancer, which connects to Varnish, which connects to Apache when necessary.)

    It’s easy enough to edit the plugin to disable those checks, but that’s not a long-term solution. Any chance for a “I know what I’m doing” checkbox that disables that (and maybe FILTER_FLAG_NO_RES_RANGE, in case a site is being accessed via loopback)?

    Thread Starter David E. Smith

    (@desmith)

    This is the un-tested two-minute implementation — basically, add a define() if you know you have users in private IP space, and ignore those flags in that case. This should prevent the change from adversely affecting any existing users, as it would require an affirmative action (editing wp-config.php) for there to be a change in the plugin’s behaviour.

    diff -ru /home/davidsmith/wordpress-shared/plugins-shared/restricted-site-access/restricted_site_access.php ./restricted_site_access.php
    --- /home/davidsmith/wordpress-shared/plugins-shared/restricted-site-access/restricted_site_access.php	2019-12-26 08:10:47.513527000 -0600
    +++ ./restricted_site_access.php	2020-02-19 14:34:09.183198200 -0600
    @@ -1484,7 +1484,12 @@
     			) as $ip ) {
     				$ip = trim( $ip ); // just to be safe.
     
    -				if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
    +				$filter_flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ;
    +				if ( defined( 'RSA_ACCEPT_PRIVATE_IPS' ) && RSA_ACCEPT_PRIVATE_IPS === true ) {
    +					$filter_flags = 0;
    +				}
    +
    +				if ( filter_var( $ip, FILTER_VALIDATE_IP, $filter_flags ) !== false ) {
     					return $ip;
     				}
     			}
    
Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘How to troubleshoot client IP detection?’ is closed to new replies.