Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1999220
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: 系统运维

2007-09-14 23:39:15

用iptables命令逐条加载防火墙规则,当规则的数量比较大的时候,因为每调用一次iptables,iptables命令都会锁定防火墙,将相应表的所有规则全部取出,再做更改,最后再次锁定防火墙将规则全部加载到内核中。

可以预见,这种方式效率是比较低下的,所以出现了作为补充,他们能一次下载/加载多条规则,极大地提高了效率。

iptables-restore对于静态规则支持比较好,如果规则需要动态改变,那么它就显得欠缺灵活度了,如果把它和编程语言结合起来,两者相得益彰,优势互补,善哉!

所以我针对php设计了一个类IptablesCache,它可以解析iptables命令,这样修改以前的规则代码将比较容易,最后调用sync()将规则最终一次性加载进内核:

<?php
$iptc = new IptablesCache(true);
$iptc->execute("iptables -t mangle -F PREROUTING");
$iptc->execute("iptables -t mangle -A PREROUTING -d 192.168.2.66 -j ACCEPT");
$iptc->execute("iptables -t mangle -I PREROUTING -d 192.168.2.2 -j ACCEPT");
$iptc->sync();
?>


类的具体实现代码如下(注意:此代码只是用来测试设计思想,如果想用于实际应用,还需要很多改进,它目前也只是支持-A -I 和 -F操作):

<?php

class IptablesChain
{
        function IptablesChain($name) {
                $this->m_name = $name;
                $this->m_rules = array();
                $this->m_policy = null;
        }

        function name() {
                return $this->m_name;
        }

        function policy() {
                return $this->m_policy;
        }

        function dumpRules(&$output) {
                foreach ($this->m_rules as $r) {
                        $output .= "-A $this->m_name $r\n";
                }

                return $output;
        }

        function setPolicy($policy) {
                $this->m_policy = $policy;
        }

        function execute($action, $rule) {
                switch ($action) {
                case "A":
                        array_push($this->m_rules, $rule);
                        break;
                case "I":
                        array_unshift($this->m_rules, $rule);
                        break;
                case "F":
                        $this->m_rules = array();
                        break;
                default:
                }
        }

        var $m_name;
        var $m_rules;
        var $m_policy;
}

class IptablesTable
{
        function IptablesTable($name) {
                $this->m_name = $name;
                $this->m_chains = array();
        }

        function name() {
                return $this->m_name;
        }

        function dump(&$output) {
                // dump policies

                foreach ($this->m_chains as $r) {
                        $output .= ":" . $r->name() . " " . $r->policy() . " [0:0]\n";
                }

                // dump rules

                foreach ($this->m_chains as $r) {
                        $r->dumpRules($output);
                }

                return $output;
        }

        function _parsePolicy($policyStr) {
                $r = sscanf($policyStr, "%s %s [%d:%d]");
                list($chain, $policy) = $r;
                $this->m_chains[$chain] = new IptablesChain($chain);
                $this->m_chains[$chain]->setPolicy($policy);
        }

        function _parse($ruleStr) {
                $r = explode(" ", $ruleStr);
                $action = "";
                $chain = "";
                $left = "";
                for ($i = 0; $i < count($r); $i ++) {
                        $seg = $r[$i];
                        switch ($seg) {
                        case "-A":
                                $action = "A";
                                $chain = $r[++ $i];
                                break;
                        case "-I":
                                $action = "I";
                                $chain = $r[++ $i];
                                break;
                        case "-F":
                                $action = "F";
                                $chain = $r[++ $i];
                                break;
                        default:
                                $left .= " $seg";
                        }
                }
                $this->m_chains[$chain]->execute($action, trim($left));
        }

        var $m_name;
        var $m_chains;
}

class IptablesCache
{
        // Get the iptables rules from the kernel.

        function IptablesCache($load = false) {
                $this->m_tables = array();
                if ($load)
                        $this->load();
        }

        function load() {
                exec("iptables-save", $output, $retval);
                if ($retval != 0)
                        return false;
                $this->_parse($output);
        }

        function dump(&$output) {
                foreach ($this->m_tables as $table) {
                        $output .= "*" . $table->name() . "\n";
                        $table->dump($output);
                        $output .= "COMMIT\n";
                }

                return $output;
        }

        function sync() {
                $output = "";
                $output = $this->dump($output);
                $p = popen("iptables-restore", "w");
                fwrite($p, $output);
                pclose($p);
        }

        function execute($cmdStr) {
                $r = explode(" ", trim($cmdStr));
                $t = "filter";
                $left = "";
                // I am sure the first one must be term `iptables'

                for ($i = 1; $i < count($r); $i ++) {
                        $seg = $r[$i];
                        if ($seg == "-t")
                                $t = $r[++$i];
                        else
                                $left .= " $seg";
                }
                $left = trim($left);
                $this->m_tables[$t]->_parse($left);
        }

        // Parse result of command iptables-save

        function _parse($output) {
                $table;

                $m_tables = array();
                foreach ($output as $line) {
                        $line = trim($line);
                        if ($line[0] == "#")
                                continue;
                        else if ($line[0] == "*")
                                $table = new IptablesTable(substr($line, 1));
                        else if ($line[0] == ":")
                                $table->_parsePolicy(substr($line, 1));
                        else if ($line == "COMMIT")
                                $this->m_tables[$table->name()] = $table;
                        else
                                $table->_parse($line);
                }
        }

        var $m_tables;
}
?>

阅读(1712) | 评论(0) | 转发(0) |
0

上一篇:秋高

下一篇:内嵌式双向链表

给主人留下些什么吧!~~