ldx / python-iptables

Python bindings for iptables
731 stars 183 forks source link

Match_set invalid value b'ipset_name' #337

Closed M1chael closed 1 year ago

M1chael commented 1 year ago
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import iptc
>>> print(iptc.version.__version__)
1.0.1
>>> rule = iptc.Rule()
>>> match = rule.create_match('set')
>>> match.match_set = ['ipset_name', 'src']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "python3.10/site-packages/iptc/ip4tc.py", line 460, in __setattr__
    self.parse(name.replace("_", "-"), value)
  File "python3.10/site-packages/iptc/ip4tc.py", line 332, in parse
    self._parse(argv, inv, entry)
  File "python3.10/site-packages/iptc/ip4tc.py", line 601, in _parse
    self._xt.parse_match(argv, inv, self._module, entry,
  File "python3.10/site-packages/iptc/xtables.py", line 869, in new
    return fn(*args)
  File "python3.10/site-packages/iptc/xtables.py", line 1166, in parse_match
    self._parse(m, argv, invert, flags, fw, ptr)
  File "python3.10/site-packages/iptc/xtables.py", line 1073, in _parse
    raise ValueError("invalid value %s" % (argv[1]))
ValueError: invalid value b'ipset_name'

Should I downgrade Python to 3.4 or is it a python-iptables bug that could be fixed?

jllorente commented 1 year ago

I believe you need to use "match-set" and then give it the match as below. Note this is a dictionary representation of a rule with iptc.easy module.

{
   "table":"raw",
   "chain":"PREROUTING",
   "rule":{
      "set":{
         "match-set":[
            "IPS_FILTER_BLACKLIST",
            "src"
         ]
      },
      "comment":{
         "comment":"Early drop blacklisted sources"
      },
      "target":"DROP"
   }
}

You can find many more examples over here.

M1chael commented 1 year ago

How can I use match-set and give it the match? I use examples from this documentation.

jllorente commented 1 year ago

In the documentation you linked there is this example:


However, when a match or a target takes multiple parameter values, that needs to be passed in as a list. Let’s assume you have created and set up an ipset called blacklist via the ipset command. To create a rule with a match for this set:

>>> rule = iptc.Rule()
>>> m = rule.create_match("set")
>>> m.match_set = ['blacklist', 'src']

Note how this time a list was used for the parameter value, since the set match match_set parameter expects two values. See the iptables manpages to find out what the extensions you use expect. See ipset for more information.

M1chael commented 1 year ago

Which corresponds exactly to my code, isn't it? Sorry, but I still don't see my mistake and don't understand how you suggest fixing it.

jllorente commented 1 year ago

Does your ipset exist before you try to add the rule?

M1chael commented 1 year ago

Bingo! That was the reason. Thanks a lot @jllorente! As a small wish for the developer: it would be great to get a more clear error message in that case.

jllorente commented 1 year ago

Great to hear! I believe that's more of an iptables core behaviour than this library itself. What error do you get if you try to add the rule via terminal?

# iptables -A ...
M1chael commented 1 year ago

It says something I would like to hear from python-iptables too in this situation: iptables v1.8.7 (nf_tables): Set ipset_name doesn't exist.