ldx / python-iptables

Python bindings for iptables
731 stars 183 forks source link

Can't set port parameter to DNAT target #291

Closed zkryakgul closed 4 years ago

zkryakgul commented 5 years ago

Using normal iptables commands you can do something like that:

iptables -t nat -A PREROUTING -p tcp -m tcp -d 192.168.0.1 --dport 80 -j DNAT --to-destination 192.168.0.100:443

But when i create a new Target and try to set parameter to it it raises an error:

target = iptc.Target(rule_obj, "PREROUTING")
target.to_destination = "192.168.0.100" # It's ok
target.to_destination = "192.168.0.100:443" # It's raises error

Traceback:

---------------------------------------------------------------------------
XTablesError                              Traceback (most recent call last)
<ipython-input-8-48f0ef46e163> in <module>
----> 1 target.to_destination = "192.168.1.1:443"

/usr/local/lib/python3.5/dist-packages/iptc/ip4tc.py in __setattr__(self, name, value)
    453     def __setattr__(self, name, value):
    454         if not name.startswith('_') and name not in dir(self):
--> 455             self.parse(name.replace("_", "-"), value)
    456         else:
    457             object.__setattr__(self, name, value)

/usr/local/lib/python3.5/dist-packages/iptc/ip4tc.py in parse(self, parameter, value)
    330         entry = self._rule.entry and ct.pointer(self._rule.entry) or None
    331 
--> 332         self._parse(argv, inv, entry)
    333 
    334     def _parse(self, argv, inv, entry):

/usr/local/lib/python3.5/dist-packages/iptc/ip4tc.py in _parse(self, argv, inv, entry)
    791         self._xt.parse_target(argv, inv, self._module, entry,
    792                               ct.cast(self._ptrptr, ct.POINTER(ct.c_void_p)),
--> 793                               self._orig_parse, self._orig_options)
    794         self._target_buf = ct.cast(self._module.t, ct.POINTER(ct.c_ubyte))
    795         if self._buffer.buffer != self._target_buf:

/usr/local/lib/python3.5/dist-packages/iptc/xtables.py in new(*args)
    867         xtobj = args[0]
    868         xtables._xtables_set_nfproto(xtobj.proto)
--> 869         return fn(*args)
    870     return new
    871 

/usr/local/lib/python3.5/dist-packages/iptc/xtables.py in parse_target(self, argv, invert, t, fw, ptr, x6_parse, x6_options)
   1121             if rv != 0:
   1122                 raise XTablesError("%s: parameter error %d (%s)" % (t.name, rv,
-> 1123                                                                     argv[1]))
   1124             t.tflags |= cb.xflags
   1125             return

XTablesError: b'DNAT': parameter error -2 (b'192.168.1.1:443')
ldx commented 4 years ago

I suspect something's not quite right when you create your rule. This should work if you want the add the same rule as you did via the command line:

import iptc
t = iptc.Table('nat')
c = iptc.Chain(t, 'PREROUTING')
r = iptc.Rule()
r.protocol = 'tcp'
r.dst = '192.168.0.1'
r.match = r.create_match('tcp')
r.match.dport = '80'
r.target = r.create_target('DNAT')
r.target.to_destination = '192.168.0.100:443'
c.insert_rule(r)
zkryakgul commented 4 years ago

yes it's works. I checked my code again and realize i forgot the set protocol parameter to my rule. I think that was the problem. Thanks!