python-iptables
python-iptables copied to clipboard
Bug - target.to_destination need to be inoked otherise issue happen in iptc/ip4tc.py
Hi. I use such prerouting method to set my rule. There is odd issue that happens in iptc/ip4tc.py when I don`t invoke target.to_destination by print() or type(), whatever.
Otherwise in function get_all_parameters() of iptc/ip4tc.py res.pop() return None and that`s why required key is undefined.
This issue happen just on my centos system.
def set_prerouting(in_interface, protocol, dst_ip, dst_port):
table = iptc.Table(iptc.Table.NAT, autocommit = False)
chain = iptc.Chain(table, "PREROUTING")
rule = iptc.Rule()
## rule.in_interface = in_interface
rule.protocol = protocol
match = iptc.Match(rule, protocol)
match.dport = dst_port
rule.add_match(match)
target = iptc.Target(rule, "DNAT")
target.to_destination = "%s:%s" % (dst_ip, dst_port.replace(':','-'))
#type(target.to_destination)
rule.target = target
table.refresh()
table.commit()
table.autocommit = True
if not rule in chain.rules:
chain.insert_rule(rule)
File "/root/workspace/myapp/src/dnat_tunnel.py", line 28, in set_port_forwarding
set_prerouting(in_interface, protocol, dst_ip, dst_port)
File "/root/workspace/myapp/src/dnat_tunnel.py", line 58, in set_prerouting
chain.insert_rule(rule)
File "/root/.local/share/virtualenvs/myapp-HrmQp8ck/lib/python3.6/site-packages/iptc/ip4tc.py", line 1470, in insert_rule
rule.final_check()
File "/root/.local/share/virtualenvs/myapp-HrmQp8ck/lib/python3.6/site-packages/iptc/ip4tc.py", line 984, in final_check
self.target.final_check()
File "/root/.local/share/virtualenvs/myapp-HrmQp8ck/lib/python3.6/site-packages/iptc/ip4tc.py", line 339, in final_check
self._update_parameters()
File "/root/.local/share/virtualenvs/myapp-HrmQp8ck/lib/python3.6/site-packages/iptc/ip4tc.py", line 441, in _update_parameters
params = self.get_all_parameters().items()
File "/root/.local/share/virtualenvs/myapp-HrmQp8ck/lib/python3.6/site-packages/iptc/ip4tc.py", line 437, in get_all_parameters
params[key].append(x) # This is a parameter value.
UnboundLocalError: local variable 'key' referenced before assignment
Did you install python-iptables via pip? Can you check what version it is?
I install it always by pipenv in latest version, no clue now on with version it was when I put this issue here... :/
Hey everyone,
I have the same error when creating a nat rule using target.to_destination for the prerouting chain
UnboundLocalError: local variable 'key' referenced before assignment
python-iptables version: 0.13.0 Kernel: 4.13.0-46-generic
So I just looked at it a bit more. After multiple attempts to debug it. I started to a see a clue.
I saw bits and pieces of my stdout in the python-iptables variable x (line 423, ip4tc.py).
My parent program, which called on python-itpables, was writing to stdout. I had hundreds of print statement, and other stdout related activity. I ran my parent program with unbuffered print, and now python-iptables now magically works.
I noticed in ip4tc.py that function __get_saved_buf reads from stdout. So I am not wrong at all. Something is getting overwritten.
Can someone else confirm this?
Thanks
Update
Still having the issue. stdout is being pushed into variables in ip4tc.py. Unbuffered print didn't do anything. Though it is much less common now.
@hheennrryy21 I couldn't reproduce your issue on my test installation from my ipython3 interpreter.
OS: Debian GNU/Linux 9.9 (stretch) Kernel: 4.19.0-0.bpo.4-amd64 #1 SMP Debian 4.19.28-2~bpo9+1 (2019-03-27) x86_64 GNU/Linux python-iptables version: 0.13.0
If I may ask, in your script you first disable autocommit on the table, then without doing any alterations to the table/chain, you then refresh(), commit() and enable autocommit again, before attempting to insert your rule, why is that?
On another note, there is a new module added in master, iptc.easy that would allow you to do something like this:
def set_prerouting_easy(in_interface, protocol, dst_ip, dst_port):
to_destination = '{}:{}'.format(dst_ip, dst_port)
rule_d = {'in-interface':in_interface, 'protocol':protocol, protocol:{'dport':dst_port},
'target': {'DNAT': {'to-destination': to_destination}}}
if not iptc.easy.has_rule('nat', 'PREROUTING', rule_d):
iptc.easy.insert_rule('nat', 'PREROUTING', rule_d)
Hi jllorente,
There is no reason why I had autocommit=False in the beginning. I was assuming this was the default when the iptc.Table object gets created. I wanted to let the team know that I've still been seeing this stdout issue for some time now since this ticket was created. Occasionally, when my program runs I am able to cause iptc to interpret an stdout message from my program as a valid entry. When I get a chance I will build a script that will replicate this problem. I am using python2.7, so I don't know what kind of issue that can cause. I may be looking at two different errors. I will be a bit more descriptive when I come back to this.