3 * how this might work..
5 * a) login - if it's a new IP not seen that day
6 * --> touch /tmp/run_pman_admin_iptables
8 * cron every minute... ?? << could do some kind of IPC?!?
10 * if file exists -> run this code.
12 * This code finds all the IP's used in the last 24 hours.
13 * and opens the firew all for them.
25 require_once 'Pman.php';
27 class Pman_Admin_Iptables extends Pman {
29 static $cli_desc = "Read ip addresses that have been used to log in, and add them to the iptables list..";
37 if (!$this->bootLoader->cli) {
42 function monitorFile()
44 $ev = DB_DataObject::Factory('Events');
45 $db = $ev->database();
47 return '/tmp/run_pman_admin_iptables-'.$db;
50 function get($opt = '', $opts = Array())
55 $mf = $this->monitorFile();
57 $fe = file_exists($mf);
67 // find IP's that have been used to log in.
68 // dump them to the iptables file.
69 // if it's different - apply it...
70 //DB_DataObject::debugLevel(1);
71 // need to get a list of users who have Admin.Iptables rights..
72 /*$gr = DB_DataObject::factory('group_rights');
73 $grps = $gr->groupsWithRights('Admin.Iptables', 'S');
75 $gr = DB_DataObject::factory('groups');
76 $gr->get('name', 'Administrators');
79 $gm = DB_DataObject::factory('group_members');
80 $gm->whereAddIn('group_id', $grps, 'int');
82 $gm->selectAdd('distinct(user_id) as user_id');
83 $peps = $gm->fetchAll('user_id');
87 //DB_DataObject::debugLevel(1);
89 $p = DB_DataObject::Factory('core_person');
91 $p->whereAdd("join_company_id_id.comptype = 'OWNER'");
93 $p->selectAdd("{$p->tableName()}.id as id");
95 $peps = $p->fetchAll('id');
98 switch( $p->getDatabaseConnection()->phptype) {
100 $interval = "INTERVAL 1 DAY";
103 $interval = " INTERVAL '1 DAY'";
106 die("database NOT SUPPORTED?!");
109 $e = DB_DataObject::factory('Events');
110 $e->action = 'LOGIN';
113 distinct(ipaddr) as ipaddr,
114 max(event_when) + $interval as expires
117 $e->person_table = DB_DataObject::factory('core_person')->tableName();
118 $e->whereAddIn('person_id', $peps, 'int');
119 $e->groupBy('ipaddr');
120 $e->whereAdd("event_when > NOW() - $interval");
123 $ips = $e->fetchAll('ipaddr','expires');
125 require_once 'System.php';
126 //inet addr:202.67.151.28 Bcast:202.67.151.255 Mask:255.255.255.0
127 $ifconfig = System::which('ifconfig','/sbin/ifconfig');
129 if (!$ifconfig || !file_exists($ifconfig)) {
130 $this->jerr("ifconfig could not be found.");
133 $if = $this->exec($ifconfig);
136 foreach(explode("\n", $if) as $l) {
138 if (!preg_match('/inet addr/', $l)) {
142 preg_match('/\s*inet addr:([0-9.]+)\s+/', $l, $match);
143 $ips[$match[1]] = ''; // no expiry...
147 $cache = ini_get('session.save-path') . '/pman_admin_iptables.cache';
149 $this->updateTables();
156 function readChain($chain)
162 require_once 'System.php';
164 $iptables = System::which('iptables', '/sbin/iptables');
166 if (!$iptables || !file_exists($iptables)) {
167 $this->jerr("iptables could not be found.");
170 // this should have been set up already..
171 // in the base firewall code.
173 $res = $this->exec("{$iptables} -L {$chain} -v -n --line-numbers");
183 foreach(explode("\n", $res) as $i => $line) {
185 $head = preg_split('/\s+/', $line);
186 $head[10] = 'comments';
192 $ar = preg_split('/\s+/', $line);
193 if (count($ar) < 3) {
196 $ar[10] = implode(' ',array_slice($ar, 10));
198 foreach($head as $k=>$v) {
202 //var_dump($row['target']);
205 // got input rules now..
206 if (!empty($row['comments'])) {
208 $row['comments'] = preg_replace('#^/\*#', '', trim($row['comments']) );
209 $row['comments'] = preg_replace('#\*/$#', '', $row['comments'] );
210 foreach((array)json_decode($row['comments']) as $k=>$v) {
228 function updateTables()
233 require_once 'System.php';
235 $iptables = System::which('iptables', '/sbin/iptables');
237 if (!$iptables || !file_exists($iptables)) {
238 $this->jerr("iptables could not be found.");
241 // this should have been set up already..
242 // in the base firewall code.
245 $rows = $this->readChain('INPUT');
247 foreach($rows as $r) {
248 if ($r['target'] == 'postgres') {
253 $this->exec("{$iptables} -A INPUT -p udp -m udp --dport 5432 -j postgres");
254 $this->exec("{$iptables} -A INPUT -p tcp -m udp --dport 5432 -j postgres");
258 $rows = $this->readChain('postgres');
259 if ($rows === false) {
269 foreach($rows as $row) {
272 //var_dump($row['target']);
273 if ($row['target'] != 'ACCEPT') {
278 if (!empty($row['expires'])) {
279 if (strtotime($row['expires']) < time()) {
280 $remove[ $row['source'] ] = $row;
284 $cur[ $row['source'] ] = $row;
286 $lastrulenum = $row['num'];
296 foreach($this->ips as $ip=>$expires) {
297 $comment = strlen($expires) ?
298 ('-m comment --comment ' . escapeshellarg(json_encode(array('expires'=>$expires))) ) :
302 $old = isset($cur[$ip]) ? $cur[$ip] : false;
304 if (empty($old['expires'])) {
307 if (strtotime($expires) <= strtotime($old['expires'])) {
308 // expires time is the same..
309 //?? make sure it's not flagged for removal..
316 $this->exec("{$iptables} -R postgres {$old['num']} -s {$ip}/32 -j ACCEPT $comment");
318 if (isset($remove[$ip])) {
324 $this->exec("{$iptables} -I postgres {$lastrulenum} -s {$ip}/32 -j ACCEPT $comment");
330 // remove rules that need deleting..
331 foreach($remove as $ip => $r) {
333 $this->removeIp($ip);
338 $this->exec("{$iptables} -L postgres -v -n --line-numbers");
344 function removeIp($ip)
349 require_once 'System.php';
351 $iptables = System::which('iptables', '/sbin/iptables');
353 if (!$iptables || !file_exists($iptables)) {
354 $this->jerr("iptables could not be found.");
357 // we need to scan the list each time, as the order get's renumbered when we remove wone...
358 $ar = $this->readChain('postgres');
359 foreach($ar as $row) {
360 if ($row['target'] != 'ACCEPT') {
364 if ($row['source'] != $ip) {
367 $this->exec("{$iptables} -D postgres {$row['num']} ");
374 function createBase()
377 require_once 'System.php';
379 $iptables = System::which('iptables', '/sbin/iptables');
381 if (!$iptables || !file_exists($iptables)) {
382 $this->jerr("iptables could not be found.");
387 //$this->exec("{$iptables} -F postgres"); // flush old
388 $this->exec("{$iptables} -X postgres"); // flush old
390 $this->exec("{$iptables} -N postgres"); // create new..
392 $this->exec($iptables. ' -A postgres -m limit --limit 2/min -j LOG '.
393 '--log-prefix "IPTables-Dropped: " --log-level 4');
394 $this->exec("$iptables -A postgres -j DROP");