XF 2.1 IP wildcard and CIDR range

Ozzy47

Well-known member
So I have a option in my addon to whitelist IP addresses. It works great, but I want to add the ability to add wildcard and CIDR ranges.

This is what I have now in my PHP file:
PHP:
    public function actionForm()
    {
          //Set parent
          $parent = parent::actionForm();
      
          // Get Options
        $options = \XF::options();

        // Option enabled
        $enable = $options->ozzmodzAdvancedACPipFirewall['enableFirewall'];
      
          // Allowed IP option
        $allowed = $options->ozzmodzAdvancedACPipFirewallip['AllowedIP'];
      
          // Let's get the users IP
        if (!empty($_SERVER['HTTP_CLIENT_IP']))
        {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }
        elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        else
        {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
      
        if($enable)
        {
            if(!$ip)
            {
                  return $this->noPermission();
            }

            $allowedIPs = preg_split('#\s+|,|;|(\r\n|\n|\r)#s', $allowed, -1, PREG_SPLIT_NO_EMPTY);
          
          if (!in_array($ip, $allowedIPs)) 
          {
              return $this->noPermission();
          }
        }

        return $parent;
    }

Now what I would like to be able to do is add a wildcard or a CIDR range like so in my option, Wildcard format 99.89.123.* and CIDR format 99.89.123/24


How would I go about that in my PHP file?
 
Well I looked at it, and just as I had feared, it is beyond my understanding on how to use/access it in my PHP file.
 
In use section of code..
Code:
use XF\Util\IP;

In your function..
Code:
$ip = IP::convertIpStringToBinary('192.168.32.62');
$rangeIp = IP::convertIpStringToBinary('192.168.32.0');
$cidr = 24;

// JUST ECHO TRUE OR FALSE, USE CODE TO DO WHAT YOU WANT
echo IP::ipMatchesCidrRange($ip, $rangeIp, $cidr);
die();

That equates to checking 192.168.32.0/24
 
Last edited:
Well I looked at it, and just as I had feared, it is beyond my understanding on how to use/access it in my PHP file.

Let's say you want to allow all IPs in the range of 10.0.0.0 to 10.0.0.255 (i.e. the range 10.0.0.0/24), you could use it something like this:

Code:
$match = \XF\Util\Ip::ipMatchesCidrRange($ipToTestEncodedToBinary, $firstIpInRangeEncodedToBinary, 24)
 
Regardless of what to use in this case, $_SERVER['HTTP_CLIENT_IP'] and $_SERVER['HTTP_X_FORWARDED_FOR'] can be spoofed, so they should never be used for essential checks that rely on correct information. $_SERVER['REMOTE_ADDR'] is the only one of the three that is actually populated by your server based on where the request is coming from (even that could be spoofed in theory, but very unlikely).
 
Regardless of what to use in this case, $_SERVER['HTTP_CLIENT_IP'] and $_SERVER['HTTP_X_FORWARDED_FOR'] can be spoofed
Hmm, that purely depends on the server configuration. If incoming X-Forwarded-For headers are stripped if the request is not coming from a trusted proxy (which has the responsibility to set this correctly) I don't see much potential to spoof that.

In fact, $_SERVER['REMOTE_ADDR'] will be identical to $_SERVER['HTTP_X_FORWARDED_FOR'] in many common reverse proxy setups if modules like mod_remoteip (Apache) or ngx_http_realip_module (nginx) are being used.
 
You should probably just use $this->app()->request()->getIp(), which is what the internals use and will automatically handle certain situations like Cloudflare reverse-proxying and guests browsing with Google Data Saver. If you're absolutely sure you can trust proxies, you can pass true as an argument (but you should never make that assumption if it's a distributed add-on).
 
Hmm, that purely depends on the server configuration. If incoming X-Forwarded-For headers are stripped if the request is not coming from a trusted proxy (which has the responsibility to set this correctly) I don't see much potential to spoof that.

In fact, $_SERVER['REMOTE_ADDR'] will be identical to $_SERVER['HTTP_X_FORWARDED_FOR'] in many common reverse proxy setups if modules like mod_remoteip (Apache) or ngx_http_realip_module (nginx) are being used.

As we're talking add-on development here, the base assumption is that you don't have control over server configuration. The pure fact that it can be falsified should always be enough to avoid it on distributed software. Maybe it shouldn't happen, but then again administrators also shouldn't reuse their passwords or write them on stick-it notes and pin them to their monitors either.
 
As we're talking add-on development here, the base assumption is that you don't have control over server configuration.
Yes, but still your statement (which, at least to me, suggests that this is always the case) isn't correct - it can be spoofed if the server isn't configured properly; not so much if it is.
 
Yes, but still your statement (which, at least to me, suggests that this is always the case) isn't correct - it can be spoofed if the server isn't configured properly; not so much if it is.

Don't see where my statement isn't correct. I said they can be spoofed, which you agreed is the case, therefor my statement is valid. Saying they should never be used doesn't imply that there isn't a countermeasure to make them spoof-proof, just that the pure fact that they could be should be enough to not use them.
 
As I don't want to (further) flood this thread was kinda OT dicusssion we should agree to disagree then.
 
Top Bottom