Search code examples
phpmysqliptables

Blocked ip's from iptables to mysql


Dealing with iptables and php / mysql but no luck, I'm trying to find an solution to add blocked ip's ( yes, more than one at once ) from iptables to mysql. Is anyone able to help with this issue?

<?php
    $hostname = gethostname();
    $name = permanent;
    require_once("/etc/blocked/inc/config.inc.php");

    $output = shell_exec('iptables -S permanent');
    $lines=explode("\n",$output);
    $fail=array();
    $r="/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/";
    foreach($lines as $line){

      $t=array();
      preg_match($r,$line,$t);
      $ip=$t[0];
      $fail[0]=$ip;

      if ($fail[0] == '') {
      }
      else {

        #echo "$hostname,$fail[0],$name \n";

        $query = "INSERT INTO blockedips (hostname,ip,name) VALUES ('$hostname','$fail[0]','$name')" ;

        $result = mysqli_query($link,$query) or die('Query failed: ' .       mysqli_error($link));

        mysqli_close($link);
        exit;
      }
    }
?> 

Solution

  • Alright, I've got some time to kill. I suggest you read up on how to use preg_match(), as well as reconsider how you're treating your database connection. I also corrected a bunch of other small mistakes and needless code.

    <?php
    $hostname = gethostname();
    // this needs to be quoted
    $name = "permanent";
    require_once("/etc/blocked/inc/config.inc.php");
    // specify the full path to your binary
    $output = exec("/sbin/iptables -S permanent", $lines);
    // exec will create an array
    //$lines=explode("\n",$output);
    // you weren't capturing the IP address here
    $r="/((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/";
    foreach($lines as $line){
        // this can create itself
        // $t=array();
        // why aren't you checking the results of this call?
        if (preg_match($r, $line, $t)) {
            // $t[0] is the whole string, $t[1] is the first match
            $ip = $t[1];
            // I don't know why you were re-assigning this to another array
            // $fail[0]=$ip;
            #echo "$hostname,$ip,$name \n";
            $query = "INSERT INTO blockedips (hostname,ip,name) VALUES ('$hostname','$ip','$name')";
            $result = mysqli_query($link,$query)
                or die('Query failed: ' . mysqli_error($link));
            // why close your database? your second query isn't going to work too well
            // mysqli_close($link);
            // oh, will never be a second value. is this intentional? why have a loop then?
            // exit;
        }
    }
    ?>
    

    But wait! Prepared statements are made to be prepared once and executed repeatedly, while reducing system overhead. I'd also strongly suggest migrating to PDO, or at least use the mysqli object-oriented interface.

    <?php
    $hostname = gethostname();
    $name = "permanent";
    require_once("/etc/blocked/inc/config.inc.php");
    $output = exec("/sbin/iptables -S $name", $lines);
    $stmt = $link->prepare("INSERT INTO blockedips (hostname,ip,name) VALUES (?, ?, ?)";
    $octet = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
    $ip = "$octet\.$octet\.$octet\.$octet";
    foreach($lines as $line){
        if (preg_match("/($ip)/", $line, $t)) {
            $ip = $t[1];
            $stmt->bind_param("sss", $hostname, $ip, $name);
            if ($stmt->execute() === false) {
                echo 'Query failed: ' . $link->error();
                $link->close();
                exit;
            }
        }
    }
    ?>