14

Im trying to retrieve the current iptables chains configured on the system via python. If I strace the iptables command, it outputs:

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

full output here: http://pastebin.com/e7XEsaZV

In python I create the socket obj and try to call getsockopt and it errors:

>>> 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
>>> 

Is this just not possible?

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
tMC
  • 18,105
  • 14
  • 62
  • 98
  • Since your question is regarding `python`, I removed the `C` tag. – BMitch May 05 '11 at 01:48
  • I seem to be missing the relationship between `iptables` and your python socket... perhaps a dumb question, but would you mind elaborating on the relationship between the two? – Mike Pennington May 05 '11 at 02:07
  • @Mike I might be missing something major I'm just trying to emulate the iptables command in Python and looking at the strace on the iptables command, I assumed (im not really a developer) that the getsockopt is how the current iptables configured in the kernel are retrieved. I might be WAY wrong, but i didn't see any ioctls etc. – tMC May 05 '11 at 02:11
  • when you say emulate iptables, what specifically are you trying to emulate in python? – Mike Pennington May 05 '11 at 02:13

2 Answers2

18

Have you seen python-iptables?

Python-iptables provides python bindings to iptables under Linux. Interoperability with iptables is achieved via using the iptables C libraries (libiptc, libxtables, and the iptables extensions), not calling the iptables binary and parsing its output.

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
  • i SWEAR i looked for this before trying to reinvent the wheel. Again, thank you. – tMC May 05 '11 at 02:20
0

The reason for error 22 is obvious. getsockopt() call with type IPT_SO_GET_INFO requires third argument of a pointer to struct ipt_getinfo. The struct has include file in my Linux at /usr/include/linux/netfilter_ipv4/ip_tables.h.

Further, there are more requirements. The buffer size given for getsockopt() call needs to match the size of struct, in my machine that is 84 bytes. Why this call really fails is the requirement of struct member .name must indicate which table you're interested in querying. Unspecified size and random bytes a table name will result in this error 22.

With Python, ultimately all this fails as there is no API for entering user defined bytes as an argument for getsockopt(). Assuming IPT_SO_GET_INFO would work, the natural next step would be to read all the chains of a table with a IPT_SO_GET_ENTRIES, which in Python is also impossible. Python's getsockopt() won't allow buffers larger than 1024 bytes. In any real Linux using IPtables, the chain rules can easily exceed that 1 KiB limit.

A good C example on how to read IPtables rules is at https://github.com/mozilla/rr/blob/master/src/test/netfilter.c

Jari Turkia
  • 1,184
  • 1
  • 21
  • 37