如何以编程方式动态管理 iptables 规则?
我需要查询现有规则,以及能够轻松添加和删除规则。 我还没有找到任何 API 来执行此操作。 我缺少什么吗?
我最接近的解决方案是使用 iptables-save | iptables-xml用于查询并手动调用iptables命令本身来添加/删除规则。 我考虑过的另一个解决方案是简单地从应用程序的数据库中重新生成整个规则集并刷新整个链,然后再次应用它。 但我想避免这种情况,因为我不想丢弃任何数据包——除非有一种方法可以原子地做到这一点。 我想知道是否有更好的方法。
如果有 C 语言的 API 就太好了; 然而,由于我计划将其构建为独立的 suid 程序,因此以任何语言执行此操作的库也很好。
I need to query existing rules, as well as being able to easily add and delete rules. I haven't found any API's for doing this. Is there something that I'm missing?
The closest I've come to a solution is using iptables-save | iptables-xml
for querying and manually calling the iptables command itself to add/delete rules. Another solution I've considered is simply regenerating the entire ruleset out of my application's database and flushing the whole chain, then applying it again. But I want to avoid this as I don't want to drop any packets -- unless there's a way to atomically do this. I'm wondering if there's a better way.
An API in C would be great; however, as I'm planning to build this into a stand-alone suid program, libraries that do this in ANY language are fine too.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我知道它是一个短期解决方案,根据 netfilter 的讨论,但在短期内,您可以使用包含在 python 中的 iptc :
https://github.com/ldx/python-iptables
我在最近的一个项目中使用了它,发现它非常有效。
I know its a short term solution, per the netfilter discussion, but in the short term you can use iptc wrapped in python with this:
https://github.com/ldx/python-iptables
I played with it some in a recent project of mine and found it quite effective.
MarkR 是对的,你不应该这样做。 最简单的方法是从脚本调用 iptables 或编写 iptables 配置并“恢复”它。
不过,如果您愿意,请阅读 iptables 的源代码。 iptables 使用匹配和表作为共享对象。 您可以使用来源或它们。
Linux netfilter 在 /usr/include/netfilter* 下还有一些包含文件。 这些是一些低级功能。 这就是 iptables 使用的。 这是在没有 iptables 的情况下可以获得的最接近的 API。
但这个 API 很“混乱”。 请记住,它被设计为仅供 iptables 使用。 它没有很好的文档记录,您可能会遇到非常具体的问题,API 可以相当快地更改而不会发出任何警告,因此升级可能会破坏您的代码等。
MarkR's right, you're not supposed to do this. The easiest way is to call iptables from the script or to write the iptables config and 'restore' it.
Still, if you want to, read the source of iptables. iptables uses matches and tables as shared objects. You can use the source or them.
The Linux netfilter also has some include files under /usr/include/netfilter*. These are somewhat low-level functions. It is what iptables uses. This is as near an API as one can get without iptables.
But this API is 'messy'. Bear in mind that it was designed to be used only by iptables. It's not very well documented, you can hit very specific problems, the API can change fairly quick without any warning, so an upgrade propably will break your code, etc.
这是在 CentOS 上使用 bash 和 iptables 动态阻止黑客滥用 sshd 的示例。 在本例中,我将 sshd 配置为禁止密码登录(允许密钥)。 我在 /var/log/secure 中查找“Bye Bye”的条目,这是 sshd 礼貌地说“f-off”的方式...
我每秒、每分钟或任何让我高兴的事情都循环运行它。 我测试 $IP 的值以验证它是否找到了有用的值,如果是,我调用 iptables 将其删除,然后使用 sed 清除 $IP 的日志文件,以便不会再次添加该条目。
我做了一些预处理(未显示),将一些重要的 IP 列入白名单,这些 IP 始终有效,但可能在连接时遇到问题(由于用户错误)。
我时不时地对 iptables 过滤器列表进行排序,并从中创建 IP 范围(使用不同的脚本 - 检查时,它们通常是来自印度、中国和俄罗斯的 IP 范围)。 因此,我的总体 iptables 过滤规则集保持在 50 到 500 个条目之间; ipset 在这么短的列表上并没有真正改进太多。
This is an example of using bash and iptables to dynamically block hackers abusing sshd on CentOS. In this case, I configured sshd to disallow password login (allows keys). I look in /var/log/secure for entries of "Bye Bye", which is sshd's polite way of saying f-off...
I run this in a loop every second, or minute, or whatever makes me happy. I test the value of $IP to verify it found a useful value, if so I invoke iptables to drop it, and I use sed to purge the log file of $IP so the entry doesn't get added again.
I do a little pre-processing (not shown) to white list some important IPs that are always valid and that might have had trouble connecting (due to user error).
From time-to-time I sort the iptables filter list and create IP ranges from them (using a different script - and when checked, they are usually IP ranges from india, china and russia). Thus, my overall iptables filter rule set stays between 50 and 500 entries; ipset doesn't really improve much on a list that short.
使用 iptables-save 和 iptables-restore 来查询和重新生成规则无疑是最有效的方法。 这些曾经是 shell 脚本,但现在它们是工作效率非常高的 C 程序。
不过,我应该指出,您可以使用一个工具,它可以使维护 iptables 变得更加容易。 大多数动态规则集实际上是重复多次的相同规则,例如:
您可以使用 ipsets,而不是每次想要更改可以访问端口 22 的端口时都替换这些规则(对于端口敲门很有用)。 即:
集合可以保存 IP 地址、网络、端口、MAC 地址,并在其记录中设置超时。 (曾经想在一个小时内添加一些东西吗?)。
甚至还有一种原子方式将一个集合与另一个集合交换,因此刷新意味着创建一个新的临时集合,然后将其交换为现有集合的名称。
Using iptables-save and iptables-restore to query and regenerate rules is easily the most efficient way of doing it. These used to, once, be shell scripts, but now they are C programs that work very efficiently.
However, I should point out that there is a tool that you can use which will make maintaining iptables much easier. Most dynamic rulesets are really the same rule repeated many times, such as:
Instead of replacing those rules every time you want to change what ports can access port 22 (useful for say, port knocking), you can use ipsets. Viz:
Sets can hold ip addresses, networks, ports, mac addresses, and have timeouts on their records. (Ever wanted to add something for just an hour?).
There is even an atomic way of swapping one set with another, so a refresh means creating a new temporary set, then swapping it in as the name of the existing set.
您可以考虑使用 rfw 这是 iptables 的 REST API。
它序列化来自各种潜在并发源的 iptables 命令,并动态远程执行 iptables。
rfw 专为尝试更新多个机器上的防火墙规则的分布式系统而设计,但它也可以在本地主机接口上的单台计算机上运行。 然后它可以避免 SSL 和身份验证开销,因为在这种情况下它可以在纯 HTTP 上运行。
示例命令:
对应于:
您可以插入和删除规则以及查询当前状态以获取 JSON 格式的现有规则:
免责声明:我启动了该项目。 它是在 MIT 许可下开源的。
You may consider using rfw which is the REST API for iptables.
It is serializing iptables commands from various potentially concurrent sources and remotely executes iptables on the fly.
rfw is designed for distributed systems that try to update firewall rules on multiple boxes but it can be run also on a single machine on localhost interface. Then it allows avoiding the SSL and authentication overhead as it can be run on plain HTTP in this case.
Sample command:
which corresponds to:
You can insert and delete rules as well as query for current status to get the existing rules in JSON format:
Disclaimer: I started that project. It's open source under the MIT license.
据我了解(尽管没有参考文献似乎提到它), iptables-restore 是原子的。 最后,当读取
COMMIT
行时,iptables
调用libiptc
中的iptc_commit
(在内部接口中)您不应该使用),然后使用您的新规则集调用setsockopt(SO_SET_REPLACE)
。这听起来就像你能得到的最原子的一样:通过一个内核调用。 然而,请更多有知识的人士对此提出异议。 :-)
编辑:
我可以确认你的描述是正确的。 iptables-restore 作为内核中的原子操作完成。
更具体地说,“仅”操作在每个 CPU 上是原子的。 因为我们存储每个 CPU 的整个规则集 blob(由于缓存优化)。
As far as I understand (although no reference seems to mention it),
iptables-restore
is atomic. At the end, when theCOMMIT
line is read,iptables
callsiptc_commit
inlibiptc
(which in an internal interface you aren't supposed to use), which then callssetsockopt(SO_SET_REPLACE)
with your new rulesets.That sounds about as atomic as you can get: with one kernel call. However, more knowledgeable parties are invited to dispute this. :-)
Edit:
I can confirm that your description is correct.
iptables-restore
is done as an atomic operation in the kernel.To be even more specific the operation "only" is atomic on a per CPU basis. As we store the entire ruleset blob per CPU (due to cache optimizations).
故意没有 API 来管理这些规则。 你不应该想这样做。 或者其他的东西。
如果您需要足够动态的规则,并且关心执行 /sbin/iptables 的性能,则还有其他方法可以实现:
There is deliberately no API to manage these rules. You're not supposed to want to do so. Or something.
If you need rules which are sufficiently dynamic you care about the performance of executing /sbin/iptables, there are other ways to do it:
今天早上我醒来发现正在遭受来自俄罗斯的拒绝服务(DOS)攻击。 他们从几十个 IP 区块中攻击我。 他们必须拥有大量 IP 或某种代理列表/服务。 每次我封锁一个IP,就会弹出另一个IP。 最后,我寻找了一个脚本,发现我需要编写自己的解决方案。 下面的内容有点激进,但他们将我的最高负载级别运行到了 200 以上。
这是我编写的用于实时阻止 DOS 的快速脚本。
==> PHP 脚本:
假设:
This morning I woke up to find that was getting a Denial Of Service (DOS) attack from Russia. They were hitting me from dozens of IP blocks. They must have either had a large pool of IPs or some sort of proxy list/service. Every time I blocked an IP, another one popped up. Finally, I looked for a script, and found I needed to write my own solution. The following is a bit agressive, but they were running my TOP LOAD LEVEL to over 200.
Here is a quick script I wrote to block the DOS in realtime.
==> PHP Script:
Assumptions:
来自 netfilter 常见问题解答:
From the netfilter FAQ: