有没有Python接口可以使用iptables?

14 投票
2 回答
10050 浏览
提问于 2025-04-16 17:01

我想通过Python获取系统上当前配置的iptables链。如果我跟踪iptables命令,它会输出:

strace iptables -L INPUT
socket(PF_INET, SOCK_RAW, IPPROTO_RAW)  = 3
getsockopt(3, SOL_IP, 0x40 /* IP_??? */, "filter\0\377`\2\351\1\0\210\377\377\210}\313\276\0\210\377\377\354\206\0\201\377\377\377\377"..., [84]) = 0

完整输出在这里:http://pastebin.com/e7XEsaZV

在Python中,我创建了一个socket对象,并尝试调用getsockopt,但出现了错误:

>>> s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
>>> s.getsockopt(socket.SOL_IP, 0x40)
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    s.getsockopt(socket.SOL_IP, 0x40)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 22] Invalid argument
>>>
>>> s = socket.socket(2, socket.SOCK_RAW, socket.IPPROTO_RAW)
>>> s.getsockopt(socket.SOL_IP, 0x41)
Traceback (most recent call last):
  File "<pyshell#48>", line 1, in <module>
    s.getsockopt(socket.SOL_IP, 0x41)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 22] Invalid argument
>>> 

这难道就不可能吗?

2 个回答

0

错误22的原因很明显。调用getsockopt()时,类型IPT_SO_GET_INFO需要第三个参数是一个指向struct ipt_getinfo的指针。在我的Linux系统中,这个结构体的定义文件在/usr/include/linux/netfilter_ipv4/ip_tables.h

此外,还有更多的要求。传给getsockopt()的缓冲区大小必须和结构体的大小一致,在我的机器上是84字节。这个调用失败的原因在于结构体成员.name必须明确指出你想查询哪个表。如果表名的大小没有指定,或者是随机的字节,就会导致错误22。

在Python中,最终这一切都失败了,因为没有API可以让你输入用户定义的字节作为getsockopt()的参数。假设IPT_SO_GET_INFO可以工作,接下来的自然步骤是用IPT_SO_GET_ENTRIES读取一个表的所有链,但在Python中这也是不可能的。Python的getsockopt()不允许缓冲区超过1024字节。而在真实的Linux系统中,使用IPtables时,链规则很容易就会超过这个1 KiB的限制。

一个很好的C语言示例,展示了如何读取IPtables规则,可以参考这个链接:https://github.com/mozilla/rr/blob/master/src/test/netfilter.c

18

你见过 python-iptables 吗?

python-iptables 是一个可以让你在 Linux 系统上用 Python 语言操作 iptables 的工具。它是通过使用一些 C 语言写的库(比如 libiptc、libxtables 和 iptables 扩展)来实现的,而不是直接调用 iptables 程序并解析它的输出结果。

撰写回答