如何以编程方式动态管理iptables规则?

时间:2008-09-20 21:57:50

标签: linux api kernel iptables netfilter

我需要查询现有规则,以及能够轻松添加和删除规则。我没有找到任何API来做这件事。有什么东西我不见了吗?

我最接近解决方案是使用iptables-save | iptables-xml进行查询并手动调用iptables命令本身来添加/删除规则。我考虑过的另一个解决方案是简单地从我的应用程序数据库中重新生成整个规则集并刷新整个链,然后再次应用它。但我想避免这种情况,因为我不想丢弃任何数据包 - 除非有一种方法可以原子地执行此操作。我想知道是否有更好的方法。

C中的API会很棒;但是,因为我打算将它构建成一个独立的suid程序,所以用任何语言执行此操作的库都可以。

9 个答案:

答案 0 :(得分:18)

来自netfilter FAQ

  

不幸的是答案是:否。

     

现在你可能会想'但是libiptc呢?'正如已经在邮件列表上多次指出的那样,libiptc NEVER 意味着用作公共接口。我们不保证一个稳定的接口,并计划在下一个linux数据包过滤的版本中将其删除。 libiptc太低层,无论如何都无法合理使用。

     

我们非常清楚这种API基本缺乏,我们正在努力改善这种状况。在此之前,建议使用system()或打开管道进入iptables-restore的stdin。后者将为您提供更好的表现。

答案 1 :(得分:12)

使用iptables-save和iptables-restore查询和重新生成规则很容易就是最有效的方法。这些过去曾经是shell脚本,但现在它们是非常有效的C程序。

但是,我应该指出,您可以使用一种工具,这将使维护iptables变得更加容易。大多数动态规则集实际上是重复多次的规则,例如:

iptables -A INPUT -s 1.1.1.1 -p tcp -m --dport 22 -j ACCEPT
iptables -A INPUT -s 2.2.2.0/24 -p tcp -m --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j REJECT

每次要更改哪些端口可以访问端口22(对端口敲门很有用)时,您可以使用ipsets,而不是替换这些规则。即:

ipset -N ssh_allowed nethash
iptables -A ssh_allowed -m set --set ssh_allowed src -p tcp -m --dport 22 -j ACCEPT
ipset -A ssh_allowed 1.1.1.1
ipset -A ssh_allowed 2.2.2.0/24

设置可以保存IP地址,网络,端口,mac地址,并在其记录中保留超时。 (曾经想在一小时内添加东西吗?)。

甚至有一种原子方式可以将一个集合与另一个集合进行交换,因此刷新意味着创建一个新的临时集合,然后将其作为现有集合的名称进行交换。

答案 2 :(得分:7)

您可以考虑使用rfw这是iptables的REST API。 它是从各种可能并发的源序列化iptables命令,并在运行中远程执行iptables。

rfw专为尝试在多个盒子上更新防火墙规则的分布式系统而设计,但也可以在localhost接口上的单个机器上运行。然后,它允许避免SSL和身份验证开销,因为在这种情况下它可以在纯HTTP上运行。

示例命令:

PUT /drop/input/eth0/11.22.33.44

对应于:

iptables -I INPUT -i eth0 -s 11.22.33.44 -j DROP

您可以插入和删除规则以及查询当前状态,以获取JSON格式的现有规则:

GET /list/input

免责声明:我开始了这个项目。它是麻省理工学院许可下的开源。

答案 3 :(得分:4)

据我所知(尽管似乎没有提及它),iptables-restore是原子的。最后,当COMMIT行被读取时,iptables调用iptc_commit中的libiptc(在您不应使用的内部接口中),然后调用setsockopt(SO_SET_REPLACE)使用您的新规则集。

这听起来像你可以得到的原子:一个内核调用。但是,邀请知识渊博的各方对此提出异议。 : - )

编辑: 我可以确认您的描述是正确的。 iptables-restore在内核中作为原子操作完成。

要更加特定,“仅”操作在每个CPU的基础上是原子的。因为我们存储每个CPU的整个规则集blob(由于缓存优化)。

答案 4 :(得分:3)

故意没有API来管理这些规则。你不应该这样做。或者其他什么。

如果你需要足够动态的规则你关心执行/ sbin / iptables的性能,还有其他方法可以做到:

  • 使用类似“最近”匹配或ip集匹配的内容,您可以在不更改规则集的情况下添加/删除黑/白名单中的IP地址。
  • 您可以使用NFQUEUE
  • 将数据包传递到用户空间以进行过滤

答案 5 :(得分:2)

今天早上醒来发现俄罗斯遭到了拒绝服务(DOS)攻击。他们从几十个IP块中击中了我。他们必须拥有大量的IP池或某种代理列表/服务。每次我阻止IP,另一个弹出。最后,我找了一个脚本,发现我需要编写自己的解决方案。以下是有点激进,但他们运行我的TOP LOAD LEVEL超过200.

这是我写的一个快速脚本,用于实时阻止DOS。

cat  **"output of the logs"** | php ipchains.php **"something unique in the logs"**

<强> ==&GT; PHP脚本:

<?php

$ip_arr = array();

while(1)
{
   $line = trim(fgets(STDIN)); // reads one line from STDIN
   $ip = trim( strtok( $line, " ") );

   if( !array_key_exists( $ip, $ip_arr ) )
      $ip_arr[$ip] = 0;

   $regex = sprintf( "/%s/", $argv[1] );

   $cnt = preg_match_all( $regex, $line );

   if( $cnt < 1 ) continue;

   $ip_arr[$ip] += 1;

   if( $ip_arr[$ip] == 1  )
     {
//     printf( "%s\n", $argv[1] );
//     printf( "%d\n", $cnt );
//     printf( "%s\n", $line );

       printf( "-A BLOCK1 -s %s/24 -j DROP\n", $ip );

       $cmd = sprintf( "/sbin/iptables  -I BLOCK1  -d %s/24 -j DROP", $ip );
       system( $cmd );
     }
}

?>

<强>假设:

1) BLOCK1 is a Chain already created. 
2) BLOCK1 is a Chain that is run/called from the INPUT CHAIN 
3) Periodically you will need to run "ipchains -S BLOCK1" and put output in /etc/sysconfig file. 
4) You are familiar with PHP 
5) You understand web log line items/fields and output.

答案 6 :(得分:1)

这是一个使用bash和iptables动态阻止黑客在CentOS上滥用sshd的例子。在这种情况下,我配置sshd禁止密码登录(允许密钥)。我在/ var / log / secure中查看“Bye Bye”的条目,这是sshd说f-off的礼貌方式......

IP=$(awk '/Bye Bye/{print $9}' /var/log/secure |
     sed 's/://g' |sort -u | head -n 1)

[[ "$IP" < "123" ]] || {

  echo "Found $IP - blocking it..." >> /var/log/hacker.log

  /sbin/iptables -A INPUT -s $IP -j DROP

  service iptables save

  sed -i "/$IP/d" /var/log/secure

}

我每隔一秒钟,或每分钟,或任何让我开心的事情都会循环播放。我测试了$ IP的值以验证它是否找到了有用的值,如果是这样我调用iptables来删除它,并且我使用sed来清除$ IP的日志文件,这样条目就不会再次添加。

我做了一些预处理(未显示)白名单,列出了一些有效且可能连接有问题的重要IP(由于用户错误)。

我不时地对iptables过滤器列表进行排序并从中创建IP范围(使用不同的脚本 - 当选中时,它们通常是来自印度,中国和俄罗斯的IP范围)。因此,我的整体iptables过滤规则集保持在50到500个条目之间;在短名单上,ipset并没有真正改善。

答案 7 :(得分:0)

MarkR是对的,你不应该这样做。最简单的方法是从脚本中调用iptables或编写iptables配置并“恢复”它。

但是,如果你愿意,请阅读iptables的来源。 iptables使用匹配和表作为共享对象。您可以使用源或它们。

Linux netfilter在/ usr / include / netfilter *下也有一些包含文件。这些是一些低级别的功能。这是iptables使用的。这就像没有iptables一样可以获得API。

但是这个API是'凌乱'。请记住,它的设计仅供iptables使用。它没有很好的文档记录,您可以解决非常具体的问题,API可以在没有任何警告的情况下快速更改,因此升级可能会破坏您的代码等。

答案 8 :(得分:0)

根据netfilter的讨论,我知道它是一个短期解决方案,但是在短期内,您可以使用包裹在python中的iptc来实现此目的:

https://github.com/ldx/python-iptables

我在我最近的一个项目中玩过它,发现它非常有效。