Linux 如何以编程方式动态管理iptables规则?
我需要查询现有的规则,以及能够轻松地添加和删除规则。我还没有找到做这件事的API。有什么我遗漏的吗 我最接近的解决方案是使用Linux 如何以编程方式动态管理iptables规则?,linux,api,kernel,iptables,netfilter,Linux,Api,Kernel,Iptables,Netfilter,我需要查询现有的规则,以及能够轻松地添加和删除规则。我还没有找到做这件事的API。有什么我遗漏的吗 我最接近的解决方案是使用iptables save | iptables xml查询并手动调用iptables命令本身来添加/删除规则。我考虑过的另一个解决方案是从应用程序的数据库中重新生成整个规则集,刷新整个链,然后再次应用它。但我想避免这种情况,因为我不想丢弃任何数据包——除非有一种方法可以实现原子化。我想知道是否有更好的办法 用C语言编写一个API就好了;但是,由于我计划将其构建到一个独立的
iptables save | iptables xml
查询并手动调用iptables命令本身来添加/删除规则。我考虑过的另一个解决方案是从应用程序的数据库中重新生成整个规则集,刷新整个链,然后再次应用它。但我想避免这种情况,因为我不想丢弃任何数据包——除非有一种方法可以实现原子化。我想知道是否有更好的办法
用C语言编写一个API就好了;但是,由于我计划将其构建到一个独立的suid程序中,用任何语言执行此操作的库也很好。故意没有API来管理这些规则。你不应该这么做。或者别的什么 如果您需要足够动态的规则,您需要关心执行/sbin/iptables的性能,那么还有其他方法可以做到这一点:
- 使用“最近”匹配或ip集匹配之类的方法,您可以在不更改规则集的情况下从黑/白列表中添加/删除ip地址
- 您可以将数据包传递到用户空间,以便使用NFQUEUE进行过滤
- 马克是对的,你不应该这样做。最简单的方法是从脚本调用iptables,或者编写iptables配置并“还原”它
不过,如果您愿意,请阅读iptables的源代码。iptables使用匹配项和表作为共享对象。您可以使用源代码,也可以使用它们
Linux netfilter在/usr/include/netfilter*下还有一些include文件。这些都是一些低级功能。这就是iptables的用途。这是在没有iptables的情况下最接近API的
但是这个API是“混乱的”。请记住,它是专为iptables设计的。它没有很好的文档记录,您可以遇到非常具体的问题,API可以在没有任何警告的情况下快速更改,因此升级可能会破坏您的代码,等等。据我所知(尽管似乎没有参考文献提及),
iptables restore
是原子的。最后,当读取COMMIT
行时,iptables
调用libiptc
中的iptc\u COMMIT
(在内部接口中您不应该使用它),然后用新规则集调用setsockopt(SO\u SET\u REPLACE)
这听起来就像你能得到的原子一样:只需要一个内核调用。但是,请更多知识渊博的各方对此提出争议。:-)
编辑:
我可以确认你的描述是正确的<代码>iptables还原作为内核中的原子操作完成
更具体地说,“仅”操作是基于每个CPU的原子操作。因为我们每个CPU存储整个规则集blob(由于缓存优化)。来自:
不幸的是,答案是:没有
现在你可能会想,‘但是libiptc呢?’。正如在邮件列表中多次指出的那样,libiptc从来没有打算用作公共接口。我们不能保证有一个稳定的接口,计划在下一代linux包过滤中删除它。libiptc层太低,无论如何都无法合理使用
我们清楚地意识到,根本缺乏这样一种API,我们正在努力改善这种情况。在此之前,建议使用system()或在iptables restore的stdin中打开管道。后者将为您提供更好的性能
使用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
您可以使用IPSET,而不是每次您想要更改哪些端口可以访问端口22时都替换这些规则(例如,端口敲门)。即:
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地址,并且在其记录上有超时。(有没有只想在一个小时内添加一些内容?)
甚至还有一种原子方式可以将一个集合与另一个集合进行交换,因此刷新意味着创建一个新的临时集合,然后将其作为现有集合的名称进行交换。今天早上我醒来发现,该集合遭到了来自俄罗斯的拒绝服务(DOS)攻击。他们从几十个IP块打我。他们必须拥有大量IP或某种代理列表/服务。每次我屏蔽一个IP,就会弹出另一个。最后,我寻找了一个脚本,发现我需要编写自己的解决方案。下面的内容有点过火,但他们把我的最高负载水平提高到了200以上 下面是我编写的一个快速脚本,用于实时阻止DOS
cat **"output of the logs"** | php ipchains.php **"something unique in the logs"**
==>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.
这是一个使用bash和iptables动态阻止黑客在CentOS上滥用sshd的示例。在本例中,我将sshd配置为不允许密码登录(允许密钥)。我在/var/log/secure中查找“再见”的条目,这是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=$(awk'/Bye-Bye/{print$9}'/var/log/secure|
sed's/://g'| sort-u | head-n1)
[[“$IP”<“123”]||{
echo“找到$IP-阻止它…”>/var/log/hacker.log
/sbin/iptables-输入-s$IP-j下降
服务iptables保存
sed-i“/$IP/d”/var/log/secure
}
我每隔一秒、每一分钟或任何让我高兴的事情都会做一个循环。我测试$IP的值以验证它是否找到了一个有用的值,如果是这样,我调用iptables删除它,并使用sed清除$IP的日志文件,以便不再添加条目
我对白名单做了一些预处理(未显示)
PUT /drop/input/eth0/11.22.33.44
iptables -I INPUT -i eth0 -s 11.22.33.44 -j DROP
GET /list/input