sync
[Pman.Admin] / Iptables.php
index 2852880..a88c246 100644 (file)
@@ -32,6 +32,8 @@ class Pman_Admin_Iptables extends Pman {
     
     function getAuth()
     {
+        // add locking here..
+        
         if (!$this->bootLoader->cli) {
             die("cli only");
         }
@@ -45,7 +47,7 @@ class Pman_Admin_Iptables extends Pman {
         return '/tmp/run_pman_admin_iptables-'.$db;
     }
     
-    function get($opt = '')
+    function get($opt = '', $opts = Array())
     {
         
         // monitor file
@@ -82,9 +84,9 @@ class Pman_Admin_Iptables extends Pman {
         
         
         */
+        //DB_DataObject::debugLevel(1);
         
-        
-        $p = DB_DataObject::Factory('Person');
+        $p = DB_DataObject::Factory('core_person');
         $p->autoJoin();
         $p->whereAdd("join_company_id_id.comptype = 'OWNER'");
         $p->selectAdd();
@@ -93,28 +95,44 @@ class Pman_Admin_Iptables extends Pman {
         $peps = $p->fetchAll('id');
         
         
-        $e = DB_DataObject::factory('Events');
-        $e->action = 'LOGIN';
-        $e->selectAdd();
-        $e->selectAdd('distinct(ipaddr) as ipaddr');
-        $e->person_table = DB_DataObject::factory('person')->tableName();
-        $e->whereAddIn('person_id', $peps, 'int');
-        switch( $e->getDatabaseConnection()->phptype) {
+        switch( $p->getDatabaseConnection()->phptype) {
             case 'mysql':
-                $e->whereAdd("event_when > NOW() - INTERVAL 1 DAY");
+                $interval = "INTERVAL 1 DAY";
                 break;
             case 'pgsql':
-                $e->whereAdd("event_when > NOW() - INTERVAL '1 DAY'");
-                break;   
+                $interval = " INTERVAL '1 DAY'";
+                break;
+            default:
+                die("database NOT SUPPORTED?!");
         }
-        $ips = $e->fetchAll('ipaddr');
+        
+        $e = DB_DataObject::factory('Events');
+        $e->action = 'LOGIN';
+        $e->selectAdd();
+        $e->selectAdd(" 
+            distinct(ipaddr) as ipaddr,
+            max(event_when) + $interval as expires
+                     
+        ");
+        $e->person_table = DB_DataObject::factory('core_person')->tableName();
+        $e->whereAddIn('person_id', $peps, 'int');
+        $e->groupBy('ipaddr');
+        $e->whereAdd("event_when > NOW() - $interval");
+                
+       
+        $ips = $e->fetchAll('ipaddr','expires');
 
+        require_once 'System.php';
         //inet addr:202.67.151.28  Bcast:202.67.151.255  Mask:255.255.255.0
+        $ifconfig = System::which('ifconfig','/sbin/ifconfig');
+        
+        if (!$ifconfig || !file_exists($ifconfig)) {
+            $this->jerr("ifconfig could not be found.");
+        }
 
-
-        // local ips..
-        $if = `/sbin/ifconfig`;
+        $if = $this->exec($ifconfig);
         
+         
         foreach(explode("\n", $if) as $l) {
             //var_dump($l);
             if (!preg_match('/inet addr/', $l)) {
@@ -122,7 +140,7 @@ class Pman_Admin_Iptables extends Pman {
             }
             $match = array();
             preg_match('/\s*inet addr:([0-9.]+)\s+/', $l, $match);
-             $ips[] = $match[1];
+            $ips[$match[1]] = ''; // no expiry...
             
         }
         $this->ips = $ips;
@@ -134,31 +152,34 @@ class Pman_Admin_Iptables extends Pman {
         exit;
 
     }
-    function updateTables()
+    
+    function readChain($chain)
     {
-       
-        require_once 'System.php';
         
-        $iptables = System::which('iptables');
+        static $iptables;
         
-         if (!$iptables) {
-            $this->jerr("iptables could not be found.");
+        if (!$iptables) {
+            require_once 'System.php';
+            
+            $iptables = System::which('iptables', '/sbin/iptables');
+            
+            if (!$iptables || !file_exists($iptables)) {
+                $this->jerr("iptables could not be found.");
+            }
         }
         // this should have been set up already..
         // in the base firewall code.
        
-        
-        // -A INPUT -p udp -m udp --dport 5432 -j postgres
-        // -A INPUT -p tcp -m tcp --dport 5432 -j postgres
+        $res = $this->exec("{$iptables} -L {$chain} -v -n --line-numbers");   
         
         
-        // /sbin/iptables -L postgres -v -n --line-numbers
         
-        $res = $this->exec("{$iptables} -L postgres -v -n --line-numbers");   
-       
+        $lastrulenum = 1;
        
         $remove = array();
-       
+        $cur = array();
+        $head = false;
+        
         foreach(explode("\n", $res) as $i => $line) {
             if ($i == 1) {
                 $head = preg_split('/\s+/', $line);
@@ -177,33 +198,112 @@ class Pman_Admin_Iptables extends Pman {
             foreach($head as $k=>$v) {
                 $row[$v] = $ar[$k];
             }
-            print_r($row);
+           // print_r($row);
+            //var_dump($row['target']);
+             
             
-            if ($row['target'] != 'INPUT') {
-                continue;
-            }
             // got input rules now..
-            if (!empty($row['comment'])) {
-                foreach((array)json_decode($row['comment']) as $k=>$v) {
+            if (!empty($row['comments'])) {
+                
+                $row['comments'] = preg_replace('#^/\*#', '', trim($row['comments']) );
+                $row['comments'] = preg_replace('#\*/$#', '', $row['comments'] );
+                foreach((array)json_decode($row['comments']) as $k=>$v) {
                     $row[$k] = $v;
                 }
             }
+            $rows[] = $row;
+                          
+             
+        }
+        if (empty($head)) {
+            return false;
+        }
+        
+        return  $rows;
+    
+    }
+    
+    
+    
+    function updateTables()
+    {
+        static $iptables;
+        
+        if (!$iptables) {
+            require_once 'System.php';
+            
+            $iptables = System::which('iptables', '/sbin/iptables');
+            
+            if (!$iptables || !file_exists($iptables)) {
+                $this->jerr("iptables could not be found.");
+            }
+        }
+        // this should have been set up already..
+        // in the base firewall code.
+       
+       
+        $rows = $this->readChain('INPUT');
+        $gotpg = false;
+        foreach($rows as $r) {
+            if ($r['target'] == 'postgres') {
+                $gotpg = true;
+            }
+        }
+        if (!$gotpg) {
+            $this->exec("{$iptables} -A INPUT -p udp -m udp --dport 5432 -j postgres");
+            $this->exec("{$iptables} -A INPUT -p tcp -m udp --dport 5432 -j postgres");
+        }
+        
+        
+        $rows = $this->readChain('postgres');
+        if ($rows === false) {
+            $this->createBase();
+            $rows = array();
+        }
+         
+        $lastrulenum = 1;
+       
+        $remove = array();
+        $cur = array();
+         
+        foreach($rows as $row) {
+             
+           // print_r($row);
+            //var_dump($row['target']);
+            if ($row['target'] != 'ACCEPT') {
+                continue;
+            }
+            
+             
             if (!empty($row['expires'])) {
                 if (strtotime($row['expires']) < time()) {
                     $remove[ $row['source'] ] = $row;
                 }
             }
-            $old[ $row['source'] ] = $row;
+            
+            $cur[ $row['source'] ] = $row;
+            
+            $lastrulenum = $row['num'];
             
         }
-        exit;
+         
+        
+        //print_r($cur);
         //--comment
         
           
          
         foreach($this->ips as $ip=>$expires) {
+            $comment = strlen($expires) ?
+                    ('-m comment --comment ' . escapeshellarg(json_encode(array('expires'=>$expires))) ) :
+                    '';
+
+            
             $old = isset($cur[$ip]) ? $cur[$ip] : false;
             if ($old) {
+                if (empty($old['expires'])) {
+                    continue;
+                }
                 if (strtotime($expires) <= strtotime($old['expires'])) {
                     // expires time is the same..
                     //?? make sure it's not flagged for removal..
@@ -213,8 +313,7 @@ class Pman_Admin_Iptables extends Pman {
             }
             
             if ($old) {
-                $this->exec("{$iptables} -R postgres {$old['num']} -s {$ip}/32 -j ACCEPT --comment ".
-                    escapeshellarg(json_encode(array('expires'=>$expires)))) ;
+                $this->exec("{$iptables} -R postgres {$old['num']} -s {$ip}/32 -j ACCEPT   $comment");
                 
                 if (isset($remove[$ip])) {
                     unset($remove[$ip]);
@@ -222,38 +321,72 @@ class Pman_Admin_Iptables extends Pman {
                 continue;
             }
             
-            $this->exec("{$iptables} -I postgres {$lastrulenum} -s {$ip}/32 -j ACCEPT --comment ".
-                    escapeshellarg(json_encode(array('expires'=>$expires))));
+            $this->exec("{$iptables} -I postgres {$lastrulenum} -s {$ip}/32 -j ACCEPT  $comment");
+                    
             
                                    
         }
         
         // remove rules that need deleting..
         foreach($remove as $ip => $r) {
-            $this->exec("{$iptables} -d postgres {$r['num']} ");
+            
+            $this->removeIp($ip);
+             
             
         }
         
+        $this->exec("{$iptables} -L postgres -v -n --line-numbers");   
+       
+  
         
-        $this->exec($iptables. ' -A postgres -m limit --limit 2/min -j LOG '.
-                        '--log-prefix "IPTables-Dropped: " --log-level 4');
-        $this->exec("$iptables -A postgres -j DROP");  
-
+    }
+    
+    function removeIp($ip)
+    {
+        static $iptables;
         
+        if (!$iptables) {
+            require_once 'System.php';
+            
+            $iptables = System::which('iptables', '/sbin/iptables');
+            
+            if (!$iptables || !file_exists($iptables)) {
+                $this->jerr("iptables could not be found.");
+            }
+        }    
+        // we need to scan the list each time, as the order get's renumbered when we remove wone...
+        $ar = $this->readChain('postgres');
+        foreach($ar as $row) {
+            if ($row['target'] != 'ACCEPT') {
+                continue;
+            }
+            
+            if ($row['source'] != $ip) {
+                continue;
+            }
+            $this->exec("{$iptables} -D postgres {$row['num']} ");
+            break;
+        }
     }
     
     
+    
     function createBase()
     {
         
-        $iptables = System::which('iptables');
-        if (!$iptables) {
+         require_once 'System.php';
+        
+        $iptables = System::which('iptables', '/sbin/iptables');
+        
+         if (!$iptables || !file_exists($iptables)) {
             $this->jerr("iptables could not be found.");
         }
         
         
         
-        $this->exec("{$iptables} -F postgres"); // flush old
+        //$this->exec("{$iptables} -F postgres"); // flush old
+        $this->exec("{$iptables} -X postgres"); // flush old
+        
         $this->exec("{$iptables} -N postgres");  // create new..
         
         $this->exec($iptables. ' -A postgres -m limit --limit 2/min -j LOG '.