Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug - target.to_destination need to be inoked otherise issue happen in iptc/ip4tc.py #241

Open
hetii opened this issue May 16, 2018 · 6 comments

Comments

@hetii
Copy link

hetii commented May 16, 2018

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
@ldx
Copy link
Owner

ldx commented May 24, 2018

Did you install python-iptables via pip? Can you check what version it is?

@hetii
Copy link
Author

hetii commented Aug 7, 2018

I install it always by pipenv in latest version, no clue now on with version it was when I put this issue here... :/

@hheennrryy21
Copy link

hheennrryy21 commented Sep 5, 2018

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

@hheennrryy21
Copy link

hheennrryy21 commented Sep 5, 2018

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.

@jllorente
Copy link
Collaborator

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

@hheennrryy21
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants