Closed plwhite closed 9 years ago
Good recap!
One way to work around the problem is something like this:
iptc.Rule().create_match("conntrack")
iptc.Rule6().create_match("conntrack")
somewhere at the beginning of your script. This will make sure conntrack
is loaded, and then python-iptables can find it via its state
alias.
The real solution would be to do it like iptables does, loading all extensions at start-up time.
Hello, It looks like this issue still occurs for external kernel modules like jool/jool_siit
>>> import iptc
>>> iptc.Rule6().create_target("JOOL_SIIT")
<iptc.ip4tc.Target object at 0x7f106a25ab80>
>>> iptc.Rule().create_target("JOOL_SIIT")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/.local/share/virtualenvs/qualia-gdQNZkWv/lib/python3.8/site-packages/iptc/ip4tc.py", line 1002, in create_target
target = Target(self, name=name, revision=revision, goto=goto)
File "/root/.local/share/virtualenvs/qualia-gdQNZkWv/lib/python3.8/site-packages/iptc/ip4tc.py", line 728, in __init__
raise XTablesError("can't find target %s" % (name))
iptc.errors.XTablesError: can't find target JOOL_SIIT
use-case:
import iptc
rule={'target': {'JOOL_SIIT': {'instance': 'test1'}}}
def _iptables_easy_insert(table: str, chain: str, rule: dict, pos: int = 0, ipv6: bool = False):
if ipv6:
iptc_table = iptc.easy.Table6(table, autocommit=False)
else:
iptc_table = iptc.easy.Table(table, autocommit=False)
iptc_chain = iptc.Chain(iptc_table, chain)
iptc_chain.insert_rule(iptc.easy.encode_iptc_rule(rule, ipv6), pos)
iptc_table.commit()
iptc_table.refresh()
_iptables_easy_insert("mangle", "PREROUTING", rule, 0, False)
_iptables_easy_insert("mangle", "PREROUTING", rule, 0, True)
jool/jool_siit modules: https://www.jool.mx/en/index.html Python 3.8.5 Ubuntu 20.04.1 LTS (5.4.0-1028-gcp) iptables v1.8.4 (legacy)
@ApoXalvation I tried to reproduce it after installing Jool from the deb packages, but the process gets stuck in kernel, and only reboot helps:
8607 pts/10 S+ 0:00 | \_ sudo /home/vilmos/.virtualenvs/iptc/bin/python issue112.py
8608 pts/10 D+ 0:02 | \_ /home/vilmos/.virtualenvs/iptc/bin/python issue112.py
Code:
import iptc
t6 = iptc.Rule6().create_target("JOOL_SIIT")
t = iptc.Rule().create_target("JOOL_SIIT")
@ldx After package installation sudo apt install jool-dkms jool-tools
ensure that You have enabled kernel module /sbin/modprobe jool_siit
To check if jool_siit is installed properly You can issue few commands:
jool_siit instance display
should give You empty table
+--------------------+-----------------+-----------+
| Namespace | Name | Framework |
+--------------------+-----------------+-----------+
+--------------------+-----------------+-----------+
jool_siit instance add "vlan3400" --iptables --pool6 fd8f:bda5:3400::/96
This create new siit instance (this should not break anything, and disappear after reboot), use above command to check if new jool_siit instance created successfully.
ip6tables -t mangle -A PREROUTING -j JOOL_SIIT --instance "vlan3400"
and
iptables -t mangle -A PREROUTING -j JOOL_SIIT --instance "vlan3400"
should create related iptables rules which We are trying to create using iptc module.
Thanks, that helped!
This code works for me:
import iptc
rule6 = iptc.Rule6()
target6 = rule6.create_target("JOOL_SIIT")
print(rule6.nfproto, target6.name)
rule = iptc.Rule()
target = rule.create_target("JOOL_SIIT")
print(rule.nfproto, target.name)
Output:
10 JOOL_SIIT
2 JOOL_SIIT
Using:
$ iptables --version
iptables v1.8.2 (nf_tables)
So it might be a problem with iptables version. I'll check this tommorow but this is good news for me. Thank You for Your time. @ldx
No worries, let me know how it goes. Another thing to check is your python-iptables version.
with: python-iptables==1.0.0 and iptables v1.8.4 (nf_tables) I still get the same error... Which os do You use?
It works fine on centos 8 but not on ubuntu 20.04 (tested with "v1.8.4 (nf_tables)" and "v1.8.4 (legacy)"
I use Debian 10. I also booted up an Ubuntu 20.04 VM, and the same, the sample code above works fine.
@ldx The last attempt with python-iptables==1.0.0
on centos 8 (the same thing on Ubuntu 20.04) and honestly this error looks different than previous, but I am trying to achieve the same thing and faced every time different issues on various OSes:
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import iptc
>>> iptc.easy.add_rule("nat", "PREROUTING", {"protocol": "udp","udp": {"dport": "51821"},"target": {"DNAT": {"to-destination": "10.34.07.2:51821"}}}, 0, False)
>>> iptc.easy.add_rule("mangle", "PREROUTING", {"target": {"JOOL_SIIT": {"instance": "3407"}}}, 0, True)
>>> iptc.easy.add_rule("mangle", "PREROUTING", {"target": {"JOOL_SIIT": {"instance": "3407"}}}, 0, False)
python-iptables: target "JOOL_SIIT" already registered
@ApoXalvation I tried both Ubuntu 20.04 and CentOS8, same result:
Python 3.8.3 (default, Aug 31 2020, 16:03:14)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import iptc
>>> iptc.easy.add_rule("nat", "PREROUTING", {"protocol": "udp","udp": {"dport": "51821"},"target": {"DNAT": {"to-destination": "10.34.07.2:51821"}}}, 0, False)
>>> iptc.easy.add_rule("mangle", "PREROUTING", {"target": {"JOOL_SIIT": {"instance": "3407"}}}, 0, True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/python-iptables/iptc/easy.py", line 74, in add_rule
iptc_chain.append_rule(iptc_rule)
File "/root/python-iptables/iptc/ip4tc.py", line 1476, in append_rule
raise ValueError("invalid rule")
ValueError: invalid rule
>>> iptc.easy.add_rule("mangle", "PREROUTING", {"target": {"JOOL_SIIT": {"instance": "3407"}}}, 0, False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/python-iptables/iptc/easy.py", line 74, in add_rule
iptc_chain.append_rule(iptc_rule)
File "/root/python-iptables/iptc/ip4tc.py", line 1476, in append_rule
raise ValueError("invalid rule")
ValueError: invalid rule
>>>
(I guess invalid rule
is what is expected?)
I just spent a few hours figuring out how to filter on state using python-iptables when there are both IPv6 and IPv4 rules. Since this was painful, it seems worth raising as an issue in case anybody hits the same problem, perhaps so a warning can go in the docs.
Some trivial sample code below showing the problem. The underlying issue seems to be that, although I can use state matching for either IPv4 or IPv6, I cannot do both in the same program. The resolution was to use match type "conntrack" and "ctstate" for the IPv6 rules (only) (i.e.
rule.create_match("conntrack")
followed bymatch.ctstate=["INVALID"]
).