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 = '')
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('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('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');
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 readTable($chain)
159 require_once 'System.php';
161 $iptables = System::which('iptables');
164 $this->jerr("iptables could not be found.");
166 // this should have been set up already..
167 // in the base firewall code.
169 $res = $this->exec("{$iptables} -L {$chain} -v -n --line-numbers");
179 foreach(explode("\n", $res) as $i => $line) {
181 $head = preg_split('/\s+/', $line);
182 $head[10] = 'comments';
188 $ar = preg_split('/\s+/', $line);
189 if (count($ar) < 3) {
192 $ar[10] = implode(' ',array_slice($ar, 10));
194 foreach($head as $k=>$v) {
198 //var_dump($row['target']);
201 // got input rules now..
202 if (!empty($row['comments'])) {
204 $row['comments'] = preg_replace('#^/\*#', '', trim($row['comments']) );
205 $row['comments'] = preg_replace('#\*/$#', '', $row['comments'] );
206 foreach((array)json_decode($row['comments']) as $k=>$v) {
224 function updateTables()
227 require_once 'System.php';
229 $iptables = System::which('iptables');
232 $this->jerr("iptables could not be found.");
234 // this should have been set up already..
235 // in the base firewall code.
238 $rows = $this->readChain('INPUT');
240 foreach($rows as $r) {
241 if ($r['target'] == 'postgres') {
246 $this->exec("{$iptables} -A INPUT -p udp -m udp --dport 5432 -j postgres");
247 $this->exec("{$iptables} -A INPUT -p tcp -m udp --dport 5432 -j postgres");
251 $rows = $this->readChain('postgres');
254 // -A INPUT -p udp -m udp --dport 5432 -j postgres
255 // -A INPUT -p tcp -m tcp --dport 5432 -j postgres
258 // /sbin/iptables -L postgres -v -n --line-numbers
260 $res = $this->exec("{$iptables} -L postgres -v -n --line-numbers");
269 foreach(explode("\n", $res) as $i => $line) {
271 $head = preg_split('/\s+/', $line);
272 $head[10] = 'comments';
278 $ar = preg_split('/\s+/', $line);
279 if (count($ar) < 3) {
282 $ar[10] = implode(' ',array_slice($ar, 10));
284 foreach($head as $k=>$v) {
288 //var_dump($row['target']);
289 if ($row['target'] != 'ACCEPT') {
293 // got input rules now..
294 if (!empty($row['comments'])) {
296 $row['comments'] = preg_replace('#^/\*#', '', trim($row['comments']) );
297 $row['comments'] = preg_replace('#\*/$#', '', $row['comments'] );
298 foreach((array)json_decode($row['comments']) as $k=>$v) {
303 if (!empty($row['expires'])) {
304 if (strtotime($row['expires']) < time()) {
305 $remove[ $row['source'] ] = $row;
309 $cur[ $row['source'] ] = $row;
311 $lastrulenum = $row['num'];
315 // then there was no chain.
324 foreach($this->ips as $ip=>$expires) {
325 $comment = strlen($expires) ?
326 ('-m comment --comment ' . escapeshellarg(json_encode(array('expires'=>$expires))) ) :
330 $old = isset($cur[$ip]) ? $cur[$ip] : false;
332 if (empty($old['expires'])) {
335 if (strtotime($expires) <= strtotime($old['expires'])) {
336 // expires time is the same..
337 //?? make sure it's not flagged for removal..
344 $this->exec("{$iptables} -R postgres {$old['num']} -s {$ip}/32 -j ACCEPT $comment");
346 if (isset($remove[$ip])) {
352 $this->exec("{$iptables} -I postgres {$lastrulenum} -s {$ip}/32 -j ACCEPT $comment");
358 // remove rules that need deleting..
359 foreach($remove as $ip => $r) {
360 $this->exec("{$iptables} -d postgres {$r['num']} ");
364 $this->exec("{$iptables} -L postgres -v -n --line-numbers");
371 function createBase()
374 $iptables = System::which('iptables');
376 $this->jerr("iptables could not be found.");
381 //$this->exec("{$iptables} -F postgres"); // flush old
382 $this->exec("{$iptables} -X postgres"); // flush old
384 $this->exec("{$iptables} -N postgres"); // create new..
386 $this->exec($iptables. ' -A postgres -m limit --limit 2/min -j LOG '.
387 '--log-prefix "IPTables-Dropped: " --log-level 4');
388 $this->exec("$iptables -A postgres -j DROP");