用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;
}
?>
|
阅读(1799) | 评论(0) | 转发(0) |