如何以编程方式即时管理iptables规则?

时间:2020-03-06 14:29:40  来源:igfitidea点击:

我需要查询现有规则,以及能够轻松添加和删除规则。我还没有找到执行此操作的任何API。有什么我想念的吗?

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

用C编写的API会很棒。但是,当我计划将其构建为独立的suid程序时,以任何语言进行此操作的库也可以。

解决方案

故意没有API来管理这些规则。我们不应该这样做。或者其他的东西。

如果我们需要足够动态的规则,那么我们在乎执行/ sbin / iptables的性能,还有其他方法可以执行:

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

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

不过,如果我们愿意,请阅读iptables的源代码。 iptables使用匹配项和表作为共享对象。我们可以使用源或者它们。

Linux netfilter在/ usr / include / netfilter *下也有一些包含文件。这些是一些底层功能。这就是iptables的用途。这与没有iptables可以获得的API一样。

但是这个API是"混乱"的。请记住,它仅设计用于iptables。它的文档记录不是很好,我们可能遇到非常具体的问题,API可以在没有任何警告的情况下快速更改,因此升级很可能会破坏代码,等等。

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

这听起来像是我们获得的原子:一个内核调用。但是,邀请更多知识渊博的政党对此提出异议。 :-)

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

更具体而言,"仅"操作在每个CPU上都是原子的。当我们存储每个CPU的整个规则集Blob时(由于缓存优化)。

从netfilter常见问题解答:

The answer unfortunately is: No.
  
  Now you might think 'but what about libiptc?'. As has been pointed out numerous times on the mailinglist(s), libiptc was NEVER meant to be used as a public interface. We don't guarantee a stable interface, and it is planned to remove it in the next incarnation of linux packet filtering. libiptc is way too low-layer to be used reasonably anyway.
  
  We are well aware that there is a fundamental lack for such an API, and we are working on improving that situation. Until then, it is recommended to either use system() or open a pipe into stdin of iptables-restore. The latter will give you a way better performance.

使用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时替换这些规则(对于说端口敲门很有用),而是使用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地址,并在其记录上具有超时。 (是否只想添加一个小时?)。

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