Hi everyone,

I am trying to create a code where I want to allow or deny certain host names and/or IP-addresses to be allowed to execute a code within an if-statement.

The problem is that I am not quite sure how I can accomplish this in coding.

If I have a variable that looks like this:

$allowed_hosts = "127.0.0.1|cmt|192.169.|169..121.";

Then I want the following to be allowed to access and run the code:

  • 127.0.0.1
  • cmt ( is a wildcard, as long as the hostname starts on cmt it should be allowed access)
  • 192.169.* (all IP's that starts with 192.169 are allowed access)
  • 169..121. (all IP's according to: 169.(0-255).121.(0-255) should be allowed)

Now... How can I solve this with a good looking code snippet which doesn't take too long to run?

What I did so far is to get the variable ´$allowed_hosts´ in to an array by exploding it using the following code:

$allowed_hosts_array = explode('|', $allowed_hosts);

Thank you in advance for all your help!

    wouldnt it just be easier in apache to set the network access level on a file that includes that if/else code... if the user's IP/HOST doesnt pass the test the include will fail and you can handle that within PHP easily

      scrupul0us;10932893 wrote:

      wouldnt it just be easier in apache to set the network access level on a file that includes that if/else code... if the user's IP/HOST doesnt pass the test the include will fail and you can handle that within PHP easily

      Thank you for your tip, but this will be a cross-platform system and parts of it will be run on a different HTTP-servern than Apache so this is not an option unfortunately.

      I would prefer to solve this from within my PHP application.

      Thank you.

        $allowed = array(
        '/(127)\.(0)\.(0)\.(1)/',
        '/^(192)\.(169)\./',
        '/^(cmt)\./',
        '/^(169)\.([0-255])?\.(121)\.([0-255])?/'
        );
        

        Something along those lines can be used with preg_match against your $_server variable holding the IP/Host of the client

          n.forsberg,

          I have to agree with scrupul0us on this one, but I have wrote a quick & dirty method. Please keep in mind - this may be very buggy and isn't tested, but it SHOULD work.

          It takes into consideration IP and Hostname variables.

          This is overkill and the apache method would work quite a bit better... but here it goes:

          <?php
          
          $allowed_hosts = "127.0.0.1|cmt*|192.169.*|169.*.121.*";
          $allowed_hosts_array = explode('|', $allowed_hosts);
          
          $current_ip = $_SERVER['REMOTE_ADDR'];
          
          // Comment Above & Uncomment Below for testing of various hosts
          //$current_ip = "127.0.1.1"; 
          
          $remote_ip_array = explode('.',$current_ip);
          
          foreach ($allowed_hosts_array as $host_spec) {
            $allowed = false;
            $allowed_split = explode('.',$host_spec);
            foreach ($allowed_split as $key => $section) {
              if (!is_numeric($section)) {
                $hostname = explode('*',strtolower($section));
                foreach ($hostname as $host) {
                  if (trim($host) != "") {
                    $allowed[] = (strtolower(substr($current_ip,0,strlen($host))) == $host) ? 1 : 0;
                  }
                }
              } else {
                $allowed[] = (($remote_ip_array[$key] == $section) || $section == "*") ? 1: 0;
              }
            }
            $allowed_spec[] = (!in_array(0,$allowed)) ? 1 : 0;
          }
          
          if (in_array(1,$allowed_spec)) {
            echo "Allowed";
          } else {
            echo "Denied";
          }
          ?>
          

          Best of luck...

            big.nerd;10932904 wrote:

            n.forsberg,

            I have to agree with scrupul0us on this one, but I have wrote a quick & dirty method. Please keep in mind - this may be very buggy and isn't tested, but it SHOULD work.

            It takes into consideration IP and Hostname variables.

            ...

            Best of luck...

            Thank you sir! Works like a charm for the IP-address, but not at all for the hostname.
            I know that is because we are only compairing against the IP-address, but how can I also get the hostname in to concideration using your code?

            For example:

            My hostname is "tmgsselhd4828" and by adding "tmg*" to var $allowed_cllients, I will allow myself to run the code.

            Look at this psuedo-code for exact match to understand what I need:

            <?php
                 $allowed_clients = "localhost|127.0.0.1|10.*|tmg*|cmt*|uca*|bes*|gde*";
            
             $client_hostname = $_SERVER['HTTP_HOST'];
             $client_ipaddress = $_SERVER['REMOTE_ADDR'];
            
             $cms_allowinternal = explode('|', $allowed_clients);
            
             if ((in_array($client_hostname, $cms_allowinternal) OR (in_array($client_ipaddress, $cms_allowinternal)))) {
                  echo "Allow access.";
             }
             else {
                  echo "Deny access.";
             }
            

            But as I said, this will only match exact IP-addresses and hostnames and will not concider any wildcards as your code does.

            Thank you in advance.

              [man]fnmatch[/man] might be useful in this situation.

                Weedpacket;10932961 wrote:

                [man]fnmatch[/man] might be useful in this situation.

                OP stated it had to work across multiple OS's presumably including Windows which fnmatch isn't available for unless OP is using 5.3.0

                  Ok I have now solved this issue by using fnmatch (custom function for Win).

                  First of all, I create function ´fnmatch´ if it does not already exist (found in the manual page for this function).

                  if(!function_exists('fnmatch')) {
                       /** Create function ´fnmatch´ if not already exists (if runned on a Windows platform). */
                       function fnmatch($pattern, $string) {
                            /** Match string in var ´$string´ against pattern in var ´$pattern´ using regular expression.
                            *   Returns True if string matches pattern, or False if not. */
                            return preg_match("#^".strtr(preg_quote($pattern, '#'), array('\*' => '.*', '\?' => '.'))."$#i", $string);
                       }
                  }
                  

                  And then I also created this small function to check whether or not the given hostname or IP-address is valid or not:

                  function allowhost($hostname, $ipaddress, $allowed_host) {
                       /** Call function ´fnmatch´ to see if var ´$hostname´ and/or var ´$ipaddress´ matches the var ´$allowed_host´. */
                       if ((fnmatch($allowed_host, $hostname)) OR (fnmatch($allowed_host, $ipaddress))) {
                            return true;
                       }
                       else {
                            return false;
                       }
                  }
                  

                  This is where I check the entire string of allowed hosts and IP-addresses (which may also contain wildcards):

                       /** Get string of allowed hostnames and IP-addresses from configuration
                       *   directive ´CMS_internalnet´ in to array ´$cms_allowinternal. */
                       $cms_allowinternal = explode('|', $_CMSCONFIG['CMS_internalnet']);
                  
                   /** Loop through each hostname and IP-address in array ´$cms_allowinternal´ and match
                   *   them against the string of allowed hosts in var ´$cms_allowinternal´. */
                   foreach ($cms_allowinternal as $allowed_host) {
                        if (allowhost($client_hostname, $client_ipaddress, strtolower($allowed_host))) {
                             echo "Access granted.";
                        }
                   }
                  

                  Thanks everyone for your superiour help!

                    Good Job with the fnmatch, I actually like that MUCH better than my rather inadequate solution (by comparison)

                    But for all that it matters,

                    $client_hostname = $_SERVER['HTTP_HOST'];
                    $client_ipaddress = $_SERVER['REMOTE_ADDR']; 
                    $current_ip = $client_hostname."|".$client_ipaddress;
                    

                    Combining the two strings into one should still yield correct results with the function I wrote..

                    (since way above you did mention it).

                      Write a Reply...