"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/salt/modules/iptables.py" (18 Nov 2020, 58612 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "iptables.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3002.1_vs_3002.2.

    1 """
    2 Support for iptables
    3 
    4 Configuration Options
    5 ---------------------
    6 
    7 The following options can be set in the minion config, grains, pillar, or
    8 master config. The configuration is read using :py:func:`config.get
    9 <salt.modules.config.get>`.
   10 
   11 - ``iptables.save_filters``: List of REGEX strings to FILTER OUT matching lines
   12 
   13   This is useful for filtering out chains, rules, etc that you do not wish to
   14   persist, such as ephemeral Docker rules.
   15 
   16   The default is to not filter out anything.
   17 
   18   .. code-block:: yaml
   19 
   20       iptables.save_filters:
   21         - "-j CATTLE_PREROUTING"
   22         - "-j DOCKER"
   23         - "-A POSTROUTING"
   24         - "-A CATTLE_POSTROUTING"
   25         - "-A FORWARD"
   26 """
   27 
   28 import logging
   29 import os
   30 import re
   31 import string
   32 import sys
   33 import uuid
   34 
   35 import salt.utils.args
   36 import salt.utils.files
   37 import salt.utils.path
   38 from salt.exceptions import SaltException
   39 from salt.state import STATE_INTERNAL_KEYWORDS as _STATE_INTERNAL_KEYWORDS
   40 
   41 log = logging.getLogger(__name__)
   42 
   43 
   44 def __virtual__():
   45     """
   46     Only load the module if iptables is installed
   47     """
   48     if not salt.utils.path.which("iptables"):
   49         return (
   50             False,
   51             "The iptables execution module cannot be loaded: iptables not installed.",
   52         )
   53 
   54     return True
   55 
   56 
   57 def _iptables_cmd(family="ipv4"):
   58     """
   59     Return correct command based on the family, e.g. ipv4 or ipv6
   60     """
   61     if family == "ipv6":
   62         return salt.utils.path.which("ip6tables")
   63     else:
   64         return salt.utils.path.which("iptables")
   65 
   66 
   67 def _has_option(option, family="ipv4"):
   68     """
   69     Return truth of whether iptables has `option`.  For example:
   70 
   71     .. code-block:: python
   72 
   73         _has_option('--wait')
   74         _has_option('--check', family='ipv6')
   75     """
   76     cmd = "{} --help".format(_iptables_cmd(family))
   77     if option in __salt__["cmd.run"](cmd, output_loglevel="quiet"):
   78         return True
   79     return False
   80 
   81 
   82 def _conf(family="ipv4"):
   83     """
   84     Some distros have a specific location for config files
   85     """
   86     if __grains__["os_family"] == "RedHat":
   87         if family == "ipv6":
   88             return "/etc/sysconfig/ip6tables"
   89         else:
   90             return "/etc/sysconfig/iptables"
   91     elif __grains__["os_family"] == "Arch":
   92         if family == "ipv6":
   93             return "/etc/iptables/ip6tables.rules"
   94         else:
   95             return "/etc/iptables/iptables.rules"
   96     elif __grains__["os_family"] == "Debian":
   97         if family == "ipv6":
   98             return "/etc/iptables/rules.v6"
   99         else:
  100             return "/etc/iptables/rules.v4"
  101     elif __grains__["os"] == "Gentoo":
  102         if family == "ipv6":
  103             return "/var/lib/ip6tables/rules-save"
  104         else:
  105             return "/var/lib/iptables/rules-save"
  106     elif __grains__["os_family"] == "Suse":
  107         # SuSE does not seem to use separate files for IPv4 and IPv6
  108         return "/etc/sysconfig/scripts/SuSEfirewall2-custom"
  109     elif __grains__["os_family"] == "Void":
  110         if family == "ipv4":
  111             return "/etc/iptables/iptables.rules"
  112         else:
  113             return "/etc/iptables/ip6tables.rules"
  114     elif __grains__["os"] == "Alpine":
  115         if family == "ipv6":
  116             return "/etc/iptables/rules6-save"
  117         else:
  118             return "/etc/iptables/rules-save"
  119     elif __grains__["os_family"] == "NILinuxRT":
  120         if family == "ipv6":
  121             return "/etc/natinst/share/ip6tables.conf"
  122         else:
  123             return "/etc/natinst/share/iptables.conf"
  124     else:
  125         raise SaltException(
  126             "Saving iptables to file is not"
  127             + " supported on {}.".format(__grains__["os"])
  128             + " Please file an issue with SaltStack"
  129         )
  130 
  131 
  132 def _conf_save_filters():
  133     """
  134     Return array of strings from `save_filters` in config.
  135 
  136     This array will be pulled from minion config, minion grains,
  137     minion pillar, or master config.  The default value returned is [].
  138 
  139     .. code-block:: python
  140 
  141         _conf_save_filters()
  142     """
  143     config = __salt__["config.option"]("iptables.save_filters", [])
  144     return config
  145 
  146 
  147 def _regex_iptables_save(cmd_output, filters=None):
  148     """
  149     Return string with `save_filter` regex entries removed.  For example:
  150 
  151     If `filters` is not provided, it will be pulled from minion config,
  152     minion grains, minion pillar, or master config. Default return value
  153     if no filters found is the original cmd_output string.
  154 
  155     .. code-block:: python
  156 
  157         _regex_iptables_save(cmd_output, ['-A DOCKER*'])
  158     """
  159     # grab RE compiled filters from context for performance
  160     if "iptables.save_filters" not in __context__:
  161         __context__["iptables.save_filters"] = []
  162         for pattern in filters or _conf_save_filters():
  163             try:
  164                 __context__["iptables.save_filters"].append(re.compile(pattern))
  165             except re.error as e:
  166                 log.warning("Skipping regex rule: '%s': %s", pattern, e)
  167                 continue
  168 
  169     if __context__["iptables.save_filters"]:
  170         # line by line get rid of any regex matches
  171         _filtered_cmd_output = [
  172             line
  173             for line in cmd_output.splitlines(True)
  174             if not any(reg.search(line) for reg in __context__["iptables.save_filters"])
  175         ]
  176         return "".join(_filtered_cmd_output)
  177 
  178     return cmd_output
  179 
  180 
  181 def version(family="ipv4"):
  182     """
  183     Return version from iptables --version
  184 
  185     CLI Example:
  186 
  187     .. code-block:: bash
  188 
  189         salt '*' iptables.version
  190 
  191         IPv6:
  192         salt '*' iptables.version family=ipv6
  193     """
  194     cmd = "{} --version".format(_iptables_cmd(family))
  195     out = __salt__["cmd.run"](cmd).split()
  196     return out[1]
  197 
  198 
  199 def build_rule(
  200     table="filter",
  201     chain=None,
  202     command=None,
  203     position="",
  204     full=None,
  205     family="ipv4",
  206     **kwargs
  207 ):
  208     """
  209     Build a well-formatted iptables rule based on kwargs. A `table` and `chain`
  210     are not required, unless `full` is True.
  211 
  212     If `full` is `True`, then `table`, `chain` and `command` are required.
  213     `command` may be specified as either a short option ('I') or a long option
  214     (`--insert`). This will return the iptables command, exactly as it would
  215     be used from the command line.
  216 
  217     If a position is required (as with `-I` or `-D`), it may be specified as
  218     `position`. This will only be useful if `full` is True.
  219 
  220     If `state` is passed, it will be ignored, use `connstate`.
  221     If `connstate` is passed in, it will automatically be changed to `state`.
  222 
  223     To pass in jump options that doesn't take arguments, pass in an empty
  224     string.
  225 
  226     .. note::
  227 
  228         Whereas iptables will accept ``-p``, ``--proto[c[o[l]]]`` as synonyms
  229         of ``--protocol``, if ``--proto`` appears in an iptables command after
  230         the appearance of ``-m policy``, it is interpreted as the ``--proto``
  231         option of the policy extension (see the iptables-extensions(8) man
  232         page).
  233 
  234     CLI Examples:
  235 
  236     .. code-block:: bash
  237 
  238         salt '*' iptables.build_rule match=state \\
  239             connstate=RELATED,ESTABLISHED jump=ACCEPT
  240 
  241         salt '*' iptables.build_rule filter INPUT command=I position=3 \\
  242             full=True match=state connstate=RELATED,ESTABLISHED jump=ACCEPT
  243 
  244         salt '*' iptables.build_rule filter INPUT command=A \\
  245             full=True match=state connstate=RELATED,ESTABLISHED \\
  246             source='127.0.0.1' jump=ACCEPT
  247 
  248         .. Invert Rules
  249         salt '*' iptables.build_rule filter INPUT command=A \\
  250             full=True match=state connstate=RELATED,ESTABLISHED \\
  251             source='!127.0.0.1' jump=ACCEPT
  252 
  253         salt '*' iptables.build_rule filter INPUT command=A \\
  254             full=True match=state connstate=RELATED,ESTABLISHED \\
  255             destination='not 127.0.0.1' jump=ACCEPT
  256 
  257         IPv6:
  258         salt '*' iptables.build_rule match=state \\
  259             connstate=RELATED,ESTABLISHED jump=ACCEPT \\
  260             family=ipv6
  261         salt '*' iptables.build_rule filter INPUT command=I position=3 \\
  262             full=True match=state connstate=RELATED,ESTABLISHED jump=ACCEPT \\
  263             family=ipv6
  264     """
  265     if "target" in kwargs:
  266         kwargs["jump"] = kwargs.pop("target")
  267 
  268     # Ignore name and state for this function
  269     kwargs.pop("name", None)
  270     kwargs.pop("state", None)
  271 
  272     for ignore in list(_STATE_INTERNAL_KEYWORDS) + ["chain", "save", "table"]:
  273         if ignore in kwargs:
  274             del kwargs[ignore]
  275 
  276     rule = []
  277     protocol = False
  278     bang_not_pat = re.compile(r"(!|not)\s?")
  279 
  280     def maybe_add_negation(arg):
  281         """
  282         Will check if the defined argument is intended to be negated,
  283         (i.e. prefixed with '!' or 'not'), and add a '! ' to the rule.
  284 
  285         The prefix will be removed from the value in the kwargs dict.
  286         """
  287         value = str(kwargs[arg])
  288         if value.startswith("!") or value.startswith("not"):
  289             kwargs[arg] = re.sub(bang_not_pat, "", value)
  290             return "! "
  291         return ""
  292 
  293     if "if" in kwargs:
  294         rule.append("{}-i {}".format(maybe_add_negation("if"), kwargs["if"]))
  295         del kwargs["if"]
  296 
  297     if "of" in kwargs:
  298         rule.append("{}-o {}".format(maybe_add_negation("of"), kwargs["of"]))
  299         del kwargs["of"]
  300 
  301     if "proto" in kwargs and kwargs.get("match") != "policy":
  302         kwargs["protocol"] = kwargs["proto"]
  303         del kwargs["proto"]
  304         # Handle the case 'proto' in kwargs and kwargs.get('match') == 'policy' below
  305     if "protocol" in kwargs:
  306         if not protocol:
  307             rule.append(
  308                 "{}-p {}".format(maybe_add_negation("protocol"), kwargs["protocol"])
  309             )
  310             protocol = True
  311         del kwargs["protocol"]
  312 
  313     if "match" in kwargs:
  314         match_value = kwargs["match"]
  315         if not isinstance(match_value, list):
  316             match_value = match_value.split(",")
  317         for match in match_value:
  318             rule.append("-m {}".format(match))
  319             if "name_" in kwargs and match.strip() in ("pknock", "quota2", "recent"):
  320                 rule.append("--name {}".format(kwargs["name_"]))
  321                 del kwargs["name_"]
  322         if "proto" in kwargs and kwargs.get("match") == "policy":
  323             rule.append(
  324                 "{}--proto {}".format(maybe_add_negation("proto"), kwargs["proto"])
  325             )
  326             del kwargs["proto"]
  327         del kwargs["match"]
  328 
  329     if "match-set" in kwargs:
  330         if isinstance(kwargs["match-set"], str):
  331             kwargs["match-set"] = [kwargs["match-set"]]
  332         for match_set in kwargs["match-set"]:
  333             negative_match_set = ""
  334             if match_set.startswith("!") or match_set.startswith("not"):
  335                 negative_match_set = "! "
  336                 match_set = re.sub(bang_not_pat, "", match_set)
  337             rule.append("-m set {}--match-set {}".format(negative_match_set, match_set))
  338         del kwargs["match-set"]
  339 
  340     if "connstate" in kwargs:
  341         if "-m state" not in rule:
  342             rule.append("-m state")
  343 
  344         rule.append(
  345             "{}--state {}".format(maybe_add_negation("connstate"), kwargs["connstate"])
  346         )
  347 
  348         del kwargs["connstate"]
  349 
  350     if "dport" in kwargs:
  351         rule.append("{}--dport {}".format(maybe_add_negation("dport"), kwargs["dport"]))
  352         del kwargs["dport"]
  353 
  354     if "sport" in kwargs:
  355         rule.append("{}--sport {}".format(maybe_add_negation("sport"), kwargs["sport"]))
  356         del kwargs["sport"]
  357 
  358     for multiport_arg in ("dports", "sports"):
  359         if multiport_arg in kwargs:
  360             if "-m multiport" not in rule:
  361                 rule.append("-m multiport")
  362                 if not protocol:
  363                     return "Error: protocol must be specified"
  364 
  365             mp_value = kwargs[multiport_arg]
  366             if isinstance(mp_value, list):
  367                 if any(
  368                     i
  369                     for i in mp_value
  370                     if str(i).startswith("!") or str(i).startswith("not")
  371                 ):
  372                     mp_value = [
  373                         re.sub(bang_not_pat, "", str(item)) for item in mp_value
  374                     ]
  375                     rule.append("!")
  376                 dports = ",".join(str(i) for i in mp_value)
  377             else:
  378                 if str(mp_value).startswith("!") or str(mp_value).startswith("not"):
  379                     dports = re.sub(bang_not_pat, "", mp_value)
  380                     rule.append("!")
  381                 else:
  382                     dports = mp_value
  383 
  384             rule.append("--{} {}".format(multiport_arg, dports))
  385             del kwargs[multiport_arg]
  386 
  387     if "comment" in kwargs:
  388         if "-m comment" not in rule:
  389             rule.append("-m comment")
  390 
  391         rule.append('--comment "{}"'.format(kwargs["comment"]))
  392         del kwargs["comment"]
  393 
  394     # --set in ipset is deprecated, works but returns error.
  395     # rewrite to --match-set if not empty, otherwise treat as recent option
  396     if "set" in kwargs and kwargs["set"]:
  397         rule.append("{}--match-set {}".format(maybe_add_negation("set"), kwargs["set"]))
  398         del kwargs["set"]
  399 
  400     # Jumps should appear last, except for any arguments that are passed to
  401     # jumps, which of course need to follow.
  402     after_jump = []
  403     # All jump arguments as extracted from man iptables-extensions, man iptables,
  404     # man xtables-addons and http://www.iptables.info/en/iptables-targets-and-jumps.html
  405     after_jump_arguments = (
  406         "j",  # j and jump needs to be first
  407         "jump",
  408         # IPTABLES
  409         "add-set",
  410         "and-mark",
  411         "and-tos",
  412         "checksum-fill",
  413         "clamp-mss-to-pmtu",
  414         "clustermac",
  415         "ctevents",
  416         "ctmask",
  417         "del-set",
  418         "ecn-tcp-remove",
  419         "exist",
  420         "expevents",
  421         "gateway",
  422         "hash-init",
  423         "hashmode",
  424         "helper",
  425         "label",
  426         "local-node",
  427         "log-ip-options",
  428         "log-level",
  429         "log-prefix",
  430         "log-tcp-options",
  431         "log-tcp-sequence",
  432         "log-uid",
  433         "mask",
  434         "new",
  435         "nfmask",
  436         "nflog-group",
  437         "nflog-prefix",
  438         "nflog-range",
  439         "nflog-threshold",
  440         "nodst",
  441         "notrack",
  442         "on-ip",
  443         "on-port",
  444         "or-mark",
  445         "or-tos",
  446         "persistent",
  447         "queue-balance",
  448         "queue-bypass",
  449         "queue-num",
  450         "random",
  451         "rateest-ewmalog",
  452         "rateest-interval",
  453         "rateest-name",
  454         "reject-with",
  455         "restore",
  456         "restore-mark",
  457         #'save',  # no arg, problematic name: How do we avoid collision with this?
  458         "save-mark",
  459         "selctx",
  460         "set-class",
  461         "set-dscp",
  462         "set-dscp-class",
  463         "set-mark",
  464         "set-mss",
  465         "set-tos",
  466         "set-xmark",
  467         "strip-options",
  468         "timeout",
  469         "to",
  470         "to-destination",
  471         "to-ports",
  472         "to-source",
  473         "total-nodes",
  474         "tproxy-mark",
  475         "ttl-dec",
  476         "ttl-inc",
  477         "ttl-set",
  478         "type",
  479         "ulog-cprange",
  480         "ulog-nlgroup",
  481         "ulog-prefix",
  482         "ulog-qthreshold",
  483         "xor-mark",
  484         "xor-tos",
  485         "zone",
  486         # IPTABLES-EXTENSIONS
  487         "dst-pfx",
  488         "hl-dec",
  489         "hl-inc",
  490         "hl-set",
  491         "hmark-dport-mask",
  492         "hmark-dst-prefix",
  493         "hmark-mod",
  494         "hmark-offset",
  495         "hmark-proto-mask",
  496         "hmark-rnd",
  497         "hmark-spi-mask",
  498         "hmark-sport-mask",
  499         "hmark-src-prefix",
  500         "hmark-tuple",
  501         "led-always-blink",
  502         "led-delay",
  503         "led-trigger-id",
  504         "queue-cpu-fanout",
  505         "src-pfx",
  506         # WEB
  507         "to-port",
  508         # XTABLES
  509         "addr",
  510         "and-mask",
  511         "delude",
  512         "honeypot",
  513         "or-mask",
  514         "prefix",
  515         "reset",
  516         "reuse",
  517         "set-mac",
  518         "shift",
  519         "static",
  520         "tarpit",
  521         "tname",
  522         "ttl",
  523     )
  524     for after_jump_argument in after_jump_arguments:
  525         if after_jump_argument in kwargs:
  526             value = kwargs[after_jump_argument]
  527             if value in (None, ""):  # options without arguments
  528                 after_jump.append("--{}".format(after_jump_argument))
  529             elif any(ws_char in str(value) for ws_char in string.whitespace):
  530                 after_jump.append('--{} "{}"'.format(after_jump_argument, value))
  531             else:
  532                 after_jump.append("--{} {}".format(after_jump_argument, value))
  533             del kwargs[after_jump_argument]
  534 
  535     for key in kwargs:
  536         negation = maybe_add_negation(key)
  537         # don't use .items() since maybe_add_negation removes the prefix from
  538         # the value in the kwargs, thus we need to fetch it after that has run
  539         value = kwargs[key]
  540         flag = "-" if len(key) == 1 else "--"
  541         value = "" if value in (None, "") else " {}".format(value)
  542         rule.append("{}{}{}{}".format(negation, flag, key, value))
  543 
  544     rule += after_jump
  545 
  546     if full:
  547         if not table:
  548             return "Error: Table needs to be specified"
  549         if not chain:
  550             return "Error: Chain needs to be specified"
  551         if not command:
  552             return "Error: Command needs to be specified"
  553 
  554         if command in "ACDIRLSFZNXPE":
  555             flag = "-"
  556         else:
  557             flag = "--"
  558 
  559         wait = "--wait" if _has_option("--wait", family) else ""
  560 
  561         return "{} {} -t {} {}{} {} {} {}".format(
  562             _iptables_cmd(family),
  563             wait,
  564             table,
  565             flag,
  566             command,
  567             chain,
  568             position,
  569             " ".join(rule),
  570         )
  571 
  572     return " ".join(rule)
  573 
  574 
  575 def get_saved_rules(conf_file=None, family="ipv4"):
  576     """
  577     Return a data structure of the rules in the conf file
  578 
  579     CLI Example:
  580 
  581     .. code-block:: bash
  582 
  583         salt '*' iptables.get_saved_rules
  584 
  585         IPv6:
  586         salt '*' iptables.get_saved_rules family=ipv6
  587     """
  588     return _parse_conf(conf_file=conf_file, family=family)
  589 
  590 
  591 def get_rules(family="ipv4"):
  592     """
  593     Return a data structure of the current, in-memory rules
  594 
  595     CLI Example:
  596 
  597     .. code-block:: bash
  598 
  599         salt '*' iptables.get_rules
  600 
  601         IPv6:
  602         salt '*' iptables.get_rules family=ipv6
  603 
  604     """
  605     return _parse_conf(in_mem=True, family=family)
  606 
  607 
  608 def get_saved_policy(table="filter", chain=None, conf_file=None, family="ipv4"):
  609     """
  610     Return the current policy for the specified table/chain
  611 
  612     CLI Examples:
  613 
  614     .. code-block:: bash
  615 
  616         salt '*' iptables.get_saved_policy filter INPUT
  617         salt '*' iptables.get_saved_policy filter INPUT \\
  618             conf_file=/etc/iptables.saved
  619 
  620         IPv6:
  621         salt '*' iptables.get_saved_policy filter INPUT family=ipv6
  622         salt '*' iptables.get_saved_policy filter INPUT \\
  623             conf_file=/etc/iptables.saved family=ipv6
  624 
  625     """
  626     if not chain:
  627         return "Error: Chain needs to be specified"
  628 
  629     rules = _parse_conf(conf_file, family=family)
  630     try:
  631         return rules[table][chain]["policy"]
  632     except KeyError:
  633         return None
  634 
  635 
  636 def get_policy(table="filter", chain=None, family="ipv4"):
  637     """
  638     Return the current policy for the specified table/chain
  639 
  640     CLI Example:
  641 
  642     .. code-block:: bash
  643 
  644         salt '*' iptables.get_policy filter INPUT
  645 
  646         IPv6:
  647         salt '*' iptables.get_policy filter INPUT family=ipv6
  648     """
  649     if not chain:
  650         return "Error: Chain needs to be specified"
  651 
  652     rules = _parse_conf(in_mem=True, family=family)
  653     try:
  654         return rules[table][chain]["policy"]
  655     except KeyError:
  656         return None
  657 
  658 
  659 def set_policy(table="filter", chain=None, policy=None, family="ipv4"):
  660     """
  661     Set the current policy for the specified table/chain
  662 
  663     CLI Example:
  664 
  665     .. code-block:: bash
  666 
  667         salt '*' iptables.set_policy filter INPUT ACCEPT
  668 
  669         IPv6:
  670         salt '*' iptables.set_policy filter INPUT ACCEPT family=ipv6
  671     """
  672     if not chain:
  673         return "Error: Chain needs to be specified"
  674     if not policy:
  675         return "Error: Policy needs to be specified"
  676 
  677     wait = "--wait" if _has_option("--wait", family) else ""
  678     cmd = "{} {} -t {} -P {} {}".format(
  679         _iptables_cmd(family), wait, table, chain, policy
  680     )
  681     out = __salt__["cmd.run"](cmd)
  682     return out
  683 
  684 
  685 def save(filename=None, family="ipv4"):
  686     """
  687     Save the current in-memory rules to disk
  688 
  689     CLI Example:
  690 
  691     .. code-block:: bash
  692 
  693         salt '*' iptables.save /etc/sysconfig/iptables
  694 
  695         IPv6:
  696         salt '*' iptables.save /etc/sysconfig/iptables family=ipv6
  697     """
  698     if _conf() and not filename:
  699         filename = _conf(family)
  700 
  701     log.debug("Saving rules to %s", filename)
  702 
  703     parent_dir = os.path.dirname(filename)
  704     if not os.path.isdir(parent_dir):
  705         os.makedirs(parent_dir)
  706     cmd = "{}-save".format(_iptables_cmd(family))
  707     ipt = __salt__["cmd.run"](cmd)
  708 
  709     # regex out the output if configured with filters
  710     if _conf_save_filters():
  711         ipt = _regex_iptables_save(ipt)
  712 
  713     out = __salt__["file.write"](filename, ipt)
  714     return out
  715 
  716 
  717 def check(table="filter", chain=None, rule=None, family="ipv4"):
  718     """
  719     Check for the existence of a rule in the table and chain
  720 
  721     This function accepts a rule in a standard iptables command format,
  722         starting with the chain. Trying to force users to adapt to a new
  723         method of creating rules would be irritating at best, and we
  724         already have a parser that can handle it.
  725 
  726     CLI Example:
  727 
  728     .. code-block:: bash
  729 
  730         salt '*' iptables.check filter INPUT \\
  731             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT'
  732 
  733         IPv6:
  734         salt '*' iptables.check filter INPUT \\
  735             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT' \\
  736             family=ipv6
  737     """
  738     if not chain:
  739         return "Error: Chain needs to be specified"
  740     if not rule:
  741         return "Error: Rule needs to be specified"
  742     ipt_cmd = _iptables_cmd(family)
  743 
  744     if _has_option("--check", family):
  745         cmd = "{} -t {} -C {} {}".format(ipt_cmd, table, chain, rule)
  746         out = __salt__["cmd.run"](cmd, output_loglevel="quiet")
  747     else:
  748         _chain_name = hex(uuid.getnode())
  749 
  750         # Create temporary table
  751         __salt__["cmd.run"]("{} -t {} -N {}".format(ipt_cmd, table, _chain_name))
  752         __salt__["cmd.run"](
  753             "{} -t {} -A {} {}".format(ipt_cmd, table, _chain_name, rule)
  754         )
  755 
  756         out = __salt__["cmd.run"]("{}-save".format(ipt_cmd))
  757 
  758         # Clean up temporary table
  759         __salt__["cmd.run"]("{} -t {} -F {}".format(ipt_cmd, table, _chain_name))
  760         __salt__["cmd.run"]("{} -t {} -X {}".format(ipt_cmd, table, _chain_name))
  761 
  762         for i in out.splitlines():
  763             if i.startswith("-A {}".format(_chain_name)):
  764                 if i.replace(_chain_name, chain) in out.splitlines():
  765                     return True
  766 
  767         return False
  768 
  769     if not out:
  770         return True
  771     return out
  772 
  773 
  774 def check_chain(table="filter", chain=None, family="ipv4"):
  775     """
  776     .. versionadded:: 2014.1.0
  777 
  778     Check for the existence of a chain in the table
  779 
  780     CLI Example:
  781 
  782     .. code-block:: bash
  783 
  784         salt '*' iptables.check_chain filter INPUT
  785 
  786         IPv6:
  787         salt '*' iptables.check_chain filter INPUT family=ipv6
  788     """
  789 
  790     if not chain:
  791         return "Error: Chain needs to be specified"
  792 
  793     cmd = "{}-save -t {}".format(_iptables_cmd(family), table)
  794     out = __salt__["cmd.run"](cmd).find(":{} ".format(chain))
  795 
  796     if out != -1:
  797         out = True
  798     else:
  799         out = False
  800 
  801     return out
  802 
  803 
  804 def new_chain(table="filter", chain=None, family="ipv4"):
  805     """
  806     .. versionadded:: 2014.1.0
  807 
  808     Create new custom chain to the specified table.
  809 
  810     CLI Example:
  811 
  812     .. code-block:: bash
  813 
  814         salt '*' iptables.new_chain filter CUSTOM_CHAIN
  815 
  816         IPv6:
  817         salt '*' iptables.new_chain filter CUSTOM_CHAIN family=ipv6
  818     """
  819 
  820     if not chain:
  821         return "Error: Chain needs to be specified"
  822 
  823     wait = "--wait" if _has_option("--wait", family) else ""
  824     cmd = "{} {} -t {} -N {}".format(_iptables_cmd(family), wait, table, chain)
  825     out = __salt__["cmd.run"](cmd)
  826 
  827     if not out:
  828         out = True
  829     return out
  830 
  831 
  832 def delete_chain(table="filter", chain=None, family="ipv4"):
  833     """
  834     .. versionadded:: 2014.1.0
  835 
  836     Delete custom chain to the specified table.
  837 
  838     CLI Example:
  839 
  840     .. code-block:: bash
  841 
  842         salt '*' iptables.delete_chain filter CUSTOM_CHAIN
  843 
  844         IPv6:
  845         salt '*' iptables.delete_chain filter CUSTOM_CHAIN family=ipv6
  846     """
  847 
  848     if not chain:
  849         return "Error: Chain needs to be specified"
  850 
  851     wait = "--wait" if _has_option("--wait", family) else ""
  852     cmd = "{} {} -t {} -X {}".format(_iptables_cmd(family), wait, table, chain)
  853     out = __salt__["cmd.run"](cmd)
  854 
  855     if not out:
  856         out = True
  857     return out
  858 
  859 
  860 def append(table="filter", chain=None, rule=None, family="ipv4"):
  861     """
  862     Append a rule to the specified table/chain.
  863 
  864     This function accepts a rule in a standard iptables command format,
  865         starting with the chain. Trying to force users to adapt to a new
  866         method of creating rules would be irritating at best, and we
  867         already have a parser that can handle it.
  868 
  869     CLI Example:
  870 
  871     .. code-block:: bash
  872 
  873         salt '*' iptables.append filter INPUT \\
  874             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT'
  875 
  876         IPv6:
  877         salt '*' iptables.append filter INPUT \\
  878             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT' \\
  879             family=ipv6
  880     """
  881     if not chain:
  882         return "Error: Chain needs to be specified"
  883     if not rule:
  884         return "Error: Rule needs to be specified"
  885 
  886     wait = "--wait" if _has_option("--wait", family) else ""
  887     returnCheck = check(table, chain, rule, family)
  888     if isinstance(returnCheck, bool) and returnCheck:
  889         return False
  890     cmd = "{} {} -t {} -A {} {}".format(_iptables_cmd(family), wait, table, chain, rule)
  891     out = __salt__["cmd.run"](cmd)
  892     return not out
  893 
  894 
  895 def insert(table="filter", chain=None, position=None, rule=None, family="ipv4"):
  896     """
  897     Insert a rule into the specified table/chain, at the specified position.
  898 
  899     This function accepts a rule in a standard iptables command format,
  900         starting with the chain. Trying to force users to adapt to a new
  901         method of creating rules would be irritating at best, and we
  902         already have a parser that can handle it.
  903 
  904     If the position specified is a negative number, then the insert will be
  905         performed counting from the end of the list. For instance, a position
  906         of -1 will insert the rule as the second to last rule. To insert a rule
  907         in the last position, use the append function instead.
  908 
  909     CLI Examples:
  910 
  911     .. code-block:: bash
  912 
  913         salt '*' iptables.insert filter INPUT position=3 \\
  914             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT'
  915 
  916         IPv6:
  917         salt '*' iptables.insert filter INPUT position=3 \\
  918             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT' \\
  919             family=ipv6
  920     """
  921     if not chain:
  922         return "Error: Chain needs to be specified"
  923     if not position:
  924         return "Error: Position needs to be specified or use append (-A)"
  925     if not rule:
  926         return "Error: Rule needs to be specified"
  927 
  928     if position < 0:
  929         rules = get_rules(family=family)
  930         size = len(rules[table][chain]["rules"])
  931         position = (size + position) + 1
  932         if position == 0:
  933             position = 1
  934 
  935     wait = "--wait" if _has_option("--wait", family) else ""
  936     returnCheck = check(table, chain, rule, family)
  937     if isinstance(returnCheck, bool) and returnCheck:
  938         return False
  939     cmd = "{} {} -t {} -I {} {} {}".format(
  940         _iptables_cmd(family), wait, table, chain, position, rule
  941     )
  942     out = __salt__["cmd.run"](cmd)
  943     return out
  944 
  945 
  946 def delete(table, chain=None, position=None, rule=None, family="ipv4"):
  947     """
  948     Delete a rule from the specified table/chain, specifying either the rule
  949         in its entirety, or the rule's position in the chain.
  950 
  951     This function accepts a rule in a standard iptables command format,
  952         starting with the chain. Trying to force users to adapt to a new
  953         method of creating rules would be irritating at best, and we
  954         already have a parser that can handle it.
  955 
  956     CLI Examples:
  957 
  958     .. code-block:: bash
  959 
  960         salt '*' iptables.delete filter INPUT position=3
  961         salt '*' iptables.delete filter INPUT \\
  962             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT'
  963 
  964         IPv6:
  965         salt '*' iptables.delete filter INPUT position=3 family=ipv6
  966         salt '*' iptables.delete filter INPUT \\
  967             rule='-m state --state RELATED,ESTABLISHED -j ACCEPT' \\
  968             family=ipv6
  969     """
  970 
  971     if position and rule:
  972         return "Error: Only specify a position or a rule, not both"
  973 
  974     if position:
  975         rule = position
  976 
  977     wait = "--wait" if _has_option("--wait", family) else ""
  978     cmd = "{} {} -t {} -D {} {}".format(_iptables_cmd(family), wait, table, chain, rule)
  979     out = __salt__["cmd.run"](cmd)
  980     return out
  981 
  982 
  983 def flush(table="filter", chain="", family="ipv4"):
  984     """
  985     Flush the chain in the specified table, flush all chains in the specified
  986     table if not specified chain.
  987 
  988     CLI Example:
  989 
  990     .. code-block:: bash
  991 
  992         salt '*' iptables.flush filter INPUT
  993 
  994         IPv6:
  995         salt '*' iptables.flush filter INPUT family=ipv6
  996     """
  997 
  998     wait = "--wait" if _has_option("--wait", family) else ""
  999     cmd = "{} {} -t {} -F {}".format(_iptables_cmd(family), wait, table, chain)
 1000     out = __salt__["cmd.run"](cmd)
 1001     return out
 1002 
 1003 
 1004 def _parse_conf(conf_file=None, in_mem=False, family="ipv4"):
 1005     """
 1006     If a file is not passed in, and the correct one for this OS is not
 1007     detected, return False
 1008     """
 1009     if _conf() and not conf_file and not in_mem:
 1010         conf_file = _conf(family)
 1011 
 1012     rules = ""
 1013     if conf_file:
 1014         with salt.utils.files.fopen(conf_file, "r") as ifile:
 1015             rules = ifile.read()
 1016     elif in_mem:
 1017         cmd = "{}-save".format(_iptables_cmd(family))
 1018         rules = __salt__["cmd.run"](cmd)
 1019     else:
 1020         raise SaltException("A file was not found to parse")
 1021 
 1022     ret = {}
 1023     table = ""
 1024     parser = _parser()
 1025     for line in rules.splitlines():
 1026         line = salt.utils.stringutils.to_unicode(line)
 1027         if line.startswith("*"):
 1028             table = line.replace("*", "")
 1029             ret[table] = {}
 1030         elif line.startswith(":"):
 1031             comps = line.split()
 1032             chain = comps[0].replace(":", "")
 1033             ret[table][chain] = {}
 1034             ret[table][chain]["policy"] = comps[1]
 1035             counters = comps[2].replace("[", "").replace("]", "")
 1036             (pcount, bcount) = counters.split(":")
 1037             ret[table][chain]["packet count"] = pcount
 1038             ret[table][chain]["byte count"] = bcount
 1039             ret[table][chain]["rules"] = []
 1040             ret[table][chain]["rules_comment"] = {}
 1041         elif line.startswith("-A"):
 1042             args = salt.utils.args.shlex_split(line)
 1043             index = 0
 1044             while index + 1 < len(args):
 1045                 swap = args[index] == "!" and args[index + 1].startswith("-")
 1046                 if swap:
 1047                     args[index], args[index + 1] = args[index + 1], args[index]
 1048                 if args[index].startswith("-"):
 1049                     index += 1
 1050                     if args[index].startswith("-") or (args[index] == "!" and not swap):
 1051                         args.insert(index, "")
 1052                     else:
 1053                         while (
 1054                             index + 1 < len(args)
 1055                             and args[index + 1] != "!"
 1056                             and not args[index + 1].startswith("-")
 1057                         ):
 1058                             args[index] += " {}".format(args.pop(index + 1))
 1059                 index += 1
 1060             if args[-1].startswith("-"):
 1061                 args.append("")
 1062             parsed_args = []
 1063             opts, _ = parser.parse_known_args(args)
 1064             parsed_args = vars(opts)
 1065             ret_args = {}
 1066             chain = parsed_args["append"]
 1067             for arg in parsed_args:
 1068                 if parsed_args[arg] and arg != "append":
 1069                     ret_args[arg] = parsed_args[arg]
 1070             if parsed_args["comment"] is not None:
 1071                 comment = parsed_args["comment"][0].strip('"')
 1072                 ret[table][chain[0]]["rules_comment"][comment] = ret_args
 1073             ret[table][chain[0]]["rules"].append(ret_args)
 1074     return ret
 1075 
 1076 
 1077 def _parser():
 1078     """
 1079     This function attempts to list all the options documented in the
 1080     iptables(8) and iptables-extensions(8) man pages.  They will not all be
 1081     used by all parts of the module; use them intelligently and appropriately.
 1082     """
 1083     add_arg = None
 1084     if sys.version.startswith("2.6"):
 1085         import optparse
 1086 
 1087         parser = optparse.OptionParser()
 1088         add_arg = parser.add_option
 1089     else:
 1090         import argparse  # pylint: disable=minimum-python-version
 1091 
 1092         parser = argparse.ArgumentParser()
 1093         add_arg = parser.add_argument
 1094 
 1095     # COMMANDS
 1096     add_arg("-A", "--append", dest="append", action="append")
 1097     add_arg("-D", "--delete", dest="delete", action="append")
 1098     add_arg("-I", "--insert", dest="insert", action="append")
 1099     add_arg("-R", "--replace", dest="replace", action="append")
 1100     add_arg("-L", "--list", dest="list", action="append")
 1101     add_arg("-F", "--flush", dest="flush", action="append")
 1102     add_arg("-Z", "--zero", dest="zero", action="append")
 1103     add_arg("-N", "--new-chain", dest="new-chain", action="append")
 1104     add_arg("-X", "--delete-chain", dest="delete-chain", action="append")
 1105     add_arg("-P", "--policy", dest="policy", action="append")
 1106     add_arg("-E", "--rename-chain", dest="rename-chain", action="append")
 1107 
 1108     # PARAMETERS
 1109     add_arg("-p", "--protocol", dest="protocol", action="append")
 1110     add_arg("-s", "--source", dest="source", action="append")
 1111     add_arg("-d", "--destination", dest="destination", action="append")
 1112     add_arg("-j", "--jump", dest="jump", action="append")
 1113     add_arg("-g", "--goto", dest="goto", action="append")
 1114     add_arg("-i", "--in-interface", dest="in-interface", action="append")
 1115     add_arg("-o", "--out-interface", dest="out-interface", action="append")
 1116     add_arg("-f", "--fragment", dest="fragment", action="append")
 1117     add_arg("-c", "--set-counters", dest="set-counters", action="append")
 1118 
 1119     # MATCH EXTENSIONS
 1120     add_arg("-m", "--match", dest="match", action="append")
 1121     ## addrtype
 1122     add_arg("--src-type", dest="src-type", action="append")
 1123     add_arg("--dst-type", dest="dst-type", action="append")
 1124     add_arg("--limit-iface-in", dest="limit-iface-in", action="append")
 1125     add_arg("--limit-iface-out", dest="limit-iface-out", action="append")
 1126     ## ah
 1127     add_arg("--ahspi", dest="ahspi", action="append")
 1128     add_arg("--ahlen", dest="ahlen", action="append")
 1129     add_arg("--ahres", dest="ahres", action="append")
 1130     ## bpf
 1131     add_arg("--bytecode", dest="bytecode", action="append")
 1132     ## cgroup
 1133     add_arg("--cgroup", dest="cgroup", action="append")
 1134     ## cluster
 1135     add_arg("--cluster-total-nodes", dest="cluster-total-nodes", action="append")
 1136     add_arg("--cluster-local-node", dest="cluster-local-node", action="append")
 1137     add_arg("--cluster-local-nodemask", dest="cluster-local-nodemask", action="append")
 1138     add_arg("--cluster-hash-seed", dest="cluster-hash-seed", action="append")
 1139     add_arg("--h-length", dest="h-length", action="append")
 1140     add_arg("--mangle-mac-s", dest="mangle-mac-s", action="append")
 1141     add_arg("--mangle-mac-d", dest="mangle-mac-d", action="append")
 1142     ## comment
 1143     add_arg("--comment", dest="comment", action="append")
 1144     ## connbytes
 1145     add_arg("--connbytes", dest="connbytes", action="append")
 1146     add_arg("--connbytes-dir", dest="connbytes-dir", action="append")
 1147     add_arg("--connbytes-mode", dest="connbytes-mode", action="append")
 1148     ## connlabel
 1149     add_arg("--label", dest="label", action="append")
 1150     ## connlimit
 1151     add_arg("--connlimit-upto", dest="connlimit-upto", action="append")
 1152     add_arg("--connlimit-above", dest="connlimit-above", action="append")
 1153     add_arg("--connlimit-mask", dest="connlimit-mask", action="append")
 1154     add_arg("--connlimit-saddr", dest="connlimit-saddr", action="append")
 1155     add_arg("--connlimit-daddr", dest="connlimit-daddr", action="append")
 1156     ## connmark
 1157     add_arg("--mark", dest="mark", action="append")
 1158     ## conntrack
 1159     add_arg("--ctstate", dest="ctstate", action="append")
 1160     add_arg("--ctproto", dest="ctproto", action="append")
 1161     add_arg("--ctorigsrc", dest="ctorigsrc", action="append")
 1162     add_arg("--ctorigdst", dest="ctorigdst", action="append")
 1163     add_arg("--ctreplsrc", dest="ctreplsrc", action="append")
 1164     add_arg("--ctrepldst", dest="ctrepldst", action="append")
 1165     add_arg("--ctorigsrcport", dest="ctorigsrcport", action="append")
 1166     add_arg("--ctorigdstport", dest="ctorigdstport", action="append")
 1167     add_arg("--ctreplsrcport", dest="ctreplsrcport", action="append")
 1168     add_arg("--ctrepldstport", dest="ctrepldstport", action="append")
 1169     add_arg("--ctstatus", dest="ctstatus", action="append")
 1170     add_arg("--ctexpire", dest="ctexpire", action="append")
 1171     add_arg("--ctdir", dest="ctdir", action="append")
 1172     ## cpu
 1173     add_arg("--cpu", dest="cpu", action="append")
 1174     ## dccp
 1175     add_arg("--sport", "--source-port", dest="source_port", action="append")
 1176     add_arg("--dport", "--destination-port", dest="destination_port", action="append")
 1177     add_arg("--dccp-types", dest="dccp-types", action="append")
 1178     add_arg("--dccp-option", dest="dccp-option", action="append")
 1179     ## devgroup
 1180     add_arg("--src-group", dest="src-group", action="append")
 1181     add_arg("--dst-group", dest="dst-group", action="append")
 1182     ## dscp
 1183     add_arg("--dscp", dest="dscp", action="append")
 1184     add_arg("--dscp-class", dest="dscp-class", action="append")
 1185     ## dst
 1186     add_arg("--dst-len", dest="dst-len", action="append")
 1187     add_arg("--dst-opts", dest="dst-opts", action="append")
 1188     ## ecn
 1189     add_arg("--ecn-tcp-cwr", dest="ecn-tcp-cwr", action="append")
 1190     add_arg("--ecn-tcp-ece", dest="ecn-tcp-ece", action="append")
 1191     add_arg("--ecn-ip-ect", dest="ecn-ip-ect", action="append")
 1192     ## esp
 1193     add_arg("--espspi", dest="espspi", action="append")
 1194     ## frag
 1195     add_arg("--fragid", dest="fragid", action="append")
 1196     add_arg("--fraglen", dest="fraglen", action="append")
 1197     add_arg("--fragres", dest="fragres", action="append")
 1198     add_arg("--fragfirst", dest="fragfirst", action="append")
 1199     add_arg("--fragmore", dest="fragmore", action="append")
 1200     add_arg("--fraglast", dest="fraglast", action="append")
 1201     ## hashlimit
 1202     add_arg("--hashlimit-upto", dest="hashlimit-upto", action="append")
 1203     add_arg("--hashlimit-above", dest="hashlimit-above", action="append")
 1204     add_arg("--hashlimit-burst", dest="hashlimit-burst", action="append")
 1205     add_arg("--hashlimit-mode", dest="hashlimit-mode", action="append")
 1206     add_arg("--hashlimit-srcmask", dest="hashlimit-srcmask", action="append")
 1207     add_arg("--hashlimit-dstmask", dest="hashlimit-dstmask", action="append")
 1208     add_arg("--hashlimit-name", dest="hashlimit-name", action="append")
 1209     add_arg("--hashlimit-htable-size", dest="hashlimit-htable-size", action="append")
 1210     add_arg("--hashlimit-htable-max", dest="hashlimit-htable-max", action="append")
 1211     add_arg(
 1212         "--hashlimit-htable-expire", dest="hashlimit-htable-expire", action="append"
 1213     )
 1214     add_arg(
 1215         "--hashlimit-htable-gcinterval",
 1216         dest="hashlimit-htable-gcinterval",
 1217         action="append",
 1218     )
 1219     ## hbh
 1220     add_arg("--hbh-len", dest="hbh-len", action="append")
 1221     add_arg("--hbh-opts", dest="hbh-opts", action="append")
 1222     ## helper
 1223     add_arg("--helper", dest="helper", action="append")
 1224     ## hl
 1225     add_arg("--hl-eq", dest="hl-eq", action="append")
 1226     add_arg("--hl-lt", dest="hl-lt", action="append")
 1227     add_arg("--hl-gt", dest="hl-gt", action="append")
 1228     ## icmp
 1229     add_arg("--icmp-type", dest="icmp-type", action="append")
 1230     ## icmp6
 1231     add_arg("--icmpv6-type", dest="icmpv6-type", action="append")
 1232     ## iprange
 1233     add_arg("--src-range", dest="src-range", action="append")
 1234     add_arg("--dst-range", dest="dst-range", action="append")
 1235     ## ipv6header
 1236     add_arg("--soft", dest="soft", action="append")
 1237     add_arg("--header", dest="header", action="append")
 1238     ## ipvs
 1239     add_arg("--ipvs", dest="ipvs", action="append")
 1240     add_arg("--vproto", dest="vproto", action="append")
 1241     add_arg("--vaddr", dest="vaddr", action="append")
 1242     add_arg("--vport", dest="vport", action="append")
 1243     add_arg("--vdir", dest="vdir", action="append")
 1244     add_arg("--vmethod", dest="vmethod", action="append")
 1245     add_arg("--vportctl", dest="vportctl", action="append")
 1246     ## length
 1247     add_arg("--length", dest="length", action="append")
 1248     ## limit
 1249     add_arg("--limit", dest="limit", action="append")
 1250     add_arg("--limit-burst", dest="limit-burst", action="append")
 1251     ## mac
 1252     add_arg("--mac-source", dest="mac-source", action="append")
 1253     ## mh
 1254     add_arg("--mh-type", dest="mh-type", action="append")
 1255     ## multiport
 1256     add_arg("--sports", "--source-ports", dest="source-ports", action="append")
 1257     add_arg(
 1258         "--dports", "--destination-ports", dest="destination-ports", action="append"
 1259     )
 1260     add_arg("--ports", dest="ports", action="append")
 1261     ## nfacct
 1262     add_arg("--nfacct-name", dest="nfacct-name", action="append")
 1263     ## osf
 1264     add_arg("--genre", dest="genre", action="append")
 1265     add_arg("--ttl", dest="ttl", action="append")
 1266     add_arg("--log", dest="log", action="append")
 1267     ## owner
 1268     add_arg("--uid-owner", dest="uid-owner", action="append")
 1269     add_arg("--gid-owner", dest="gid-owner", action="append")
 1270     add_arg("--socket-exists", dest="socket-exists", action="append")
 1271     ## physdev
 1272     add_arg("--physdev-in", dest="physdev-in", action="append")
 1273     add_arg("--physdev-out", dest="physdev-out", action="append")
 1274     add_arg("--physdev-is-in", dest="physdev-is-in", action="append")
 1275     add_arg("--physdev-is-out", dest="physdev-is-out", action="append")
 1276     add_arg("--physdev-is-bridged", dest="physdev-is-bridged", action="append")
 1277     ## pkttype
 1278     add_arg("--pkt-type", dest="pkt-type", action="append")
 1279     ## policy
 1280     add_arg("--dir", dest="dir", action="append")
 1281     add_arg("--pol", dest="pol", action="append")
 1282     add_arg("--strict", dest="strict", action="append")
 1283     add_arg("--reqid", dest="reqid", action="append")
 1284     add_arg("--spi", dest="spi", action="append")
 1285     add_arg("--proto", dest="proto", action="append")
 1286     add_arg("--mode", dest="mode", action="append")
 1287     add_arg("--tunnel-src", dest="tunnel-src", action="append")
 1288     add_arg("--tunnel-dst", dest="tunnel-dst", action="append")
 1289     add_arg("--next", dest="next", action="append")
 1290     ## quota
 1291     add_arg("--quota", dest="quota", action="append")
 1292     ## rateest
 1293     add_arg("--rateest", dest="rateest", action="append")
 1294     add_arg("--rateest1", dest="rateest1", action="append")
 1295     add_arg("--rateest2", dest="rateest2", action="append")
 1296     add_arg("--rateest-delta", dest="rateest-delta", action="append")
 1297     add_arg("--rateest-bps", dest="rateest-bps", action="append")
 1298     add_arg("--rateest-bps1", dest="rateest-bps1", action="append")
 1299     add_arg("--rateest-bps2", dest="rateest-bps2", action="append")
 1300     add_arg("--rateest-pps", dest="rateest-pps", action="append")
 1301     add_arg("--rateest-pps1", dest="rateest-pps1", action="append")
 1302     add_arg("--rateest-pps2", dest="rateest-pps2", action="append")
 1303     add_arg("--rateest-lt", dest="rateest-lt", action="append")
 1304     add_arg("--rateest-gt", dest="rateest-gt", action="append")
 1305     add_arg("--rateest-eq", dest="rateest-eq", action="append")
 1306     add_arg("--rateest-name", dest="rateest-name", action="append")
 1307     add_arg("--rateest-interval", dest="rateest-interval", action="append")
 1308     add_arg("--rateest-ewma", dest="rateest-ewma", action="append")
 1309     ## realm
 1310     add_arg("--realm", dest="realm", action="append")
 1311     ## recent
 1312     add_arg("--name", dest="name", action="append")
 1313     add_arg("--set", dest="set", action="append")
 1314     add_arg("--rsource", dest="rsource", action="append")
 1315     add_arg("--rdest", dest="rdest", action="append")
 1316     add_arg("--mask", dest="mask", action="append")
 1317     add_arg("--rcheck", dest="rcheck", action="append")
 1318     add_arg("--update", dest="update", action="append")
 1319     add_arg("--remove", dest="remove", action="append")
 1320     add_arg("--seconds", dest="seconds", action="append")
 1321     add_arg("--reap", dest="reap", action="append")
 1322     add_arg("--hitcount", dest="hitcount", action="append")
 1323     add_arg("--rttl", dest="rttl", action="append")
 1324     ## rpfilter
 1325     add_arg("--loose", dest="loose", action="append")
 1326     add_arg("--validmark", dest="validmark", action="append")
 1327     add_arg("--accept-local", dest="accept-local", action="append")
 1328     add_arg("--invert", dest="invert", action="append")
 1329     ## rt
 1330     add_arg("--rt-type", dest="rt-type", action="append")
 1331     add_arg("--rt-segsleft", dest="rt-segsleft", action="append")
 1332     add_arg("--rt-len", dest="rt-len", action="append")
 1333     add_arg("--rt-0-res", dest="rt-0-res", action="append")
 1334     add_arg("--rt-0-addrs", dest="rt-0-addrs", action="append")
 1335     add_arg("--rt-0-not-strict", dest="rt-0-not-strict", action="append")
 1336     ## sctp
 1337     add_arg("--chunk-types", dest="chunk-types", action="append")
 1338     ## set
 1339     add_arg("--match-set", dest="match-set", action="append")
 1340     add_arg("--return-nomatch", dest="return-nomatch", action="append")
 1341     add_arg("--update-counters", dest="update-counters", action="append")
 1342     add_arg("--update-subcounters", dest="update-subcounters", action="append")
 1343     add_arg("--packets-eq", dest="packets-eq", action="append")
 1344     add_arg("--packets-lt", dest="packets-lt", action="append")
 1345     add_arg("--packets-gt", dest="packets-gt", action="append")
 1346     add_arg("--bytes-eq", dest="bytes-eq", action="append")
 1347     add_arg("--bytes-lt", dest="bytes-lt", action="append")
 1348     add_arg("--bytes-gt", dest="bytes-gt", action="append")
 1349     ## socket
 1350     add_arg("--transparent", dest="transparent", action="append")
 1351     add_arg("--nowildcard", dest="nowildcard", action="append")
 1352     ## state
 1353     add_arg("--state", dest="state", action="append")
 1354     ## statistic
 1355     add_arg("--probability", dest="probability", action="append")
 1356     add_arg("--every", dest="every", action="append")
 1357     add_arg("--packet", dest="packet", action="append")
 1358     ## string
 1359     add_arg("--algo", dest="algo", action="append")
 1360     add_arg("--from", dest="from", action="append")
 1361     add_arg("--to", dest="to", action="append")
 1362     add_arg("--string", dest="string", action="append")
 1363     add_arg("--hex-string", dest="hex-string", action="append")
 1364     ## tcp
 1365     add_arg("--tcp-flags", dest="tcp-flags", action="append")
 1366     add_arg("--syn", dest="syn", action="append")
 1367     add_arg("--tcp-option", dest="tcp-option", action="append")
 1368     ## tcpmss
 1369     add_arg("--mss", dest="mss", action="append")
 1370     ## time
 1371     add_arg("--datestart", dest="datestart", action="append")
 1372     add_arg("--datestop", dest="datestop", action="append")
 1373     add_arg("--timestart", dest="timestart", action="append")
 1374     add_arg("--timestop", dest="timestop", action="append")
 1375     add_arg("--monthdays", dest="monthdays", action="append")
 1376     add_arg("--weekdays", dest="weekdays", action="append")
 1377     add_arg("--contiguous", dest="contiguous", action="append")
 1378     add_arg("--kerneltz", dest="kerneltz", action="append")
 1379     add_arg("--utc", dest="utc", action="append")
 1380     add_arg("--localtz", dest="localtz", action="append")
 1381     ## tos
 1382     add_arg("--tos", dest="tos", action="append")
 1383     ## ttl
 1384     add_arg("--ttl-eq", dest="ttl-eq", action="append")
 1385     add_arg("--ttl-gt", dest="ttl-gt", action="append")
 1386     add_arg("--ttl-lt", dest="ttl-lt", action="append")
 1387     ## u32
 1388     add_arg("--u32", dest="u32", action="append")
 1389 
 1390     # Xtables-addons matches
 1391     ## condition
 1392     add_arg("--condition", dest="condition", action="append")
 1393     ## dhcpmac
 1394     add_arg("--mac", dest="mac", action="append")
 1395     ## fuzzy
 1396     add_arg("--lower-limit", dest="lower-limit", action="append")
 1397     add_arg("--upper-limit", dest="upper-limit", action="append")
 1398     ## geoip
 1399     add_arg("--src-cc", "--source-country", dest="source-country", action="append")
 1400     add_arg(
 1401         "--dst-cc", "--destination-country", dest="destination-country", action="append"
 1402     )
 1403     ## gradm
 1404     add_arg("--enabled", dest="enabled", action="append")
 1405     add_arg("--disabled", dest="disabled", action="append")
 1406     ## iface
 1407     add_arg("--iface", dest="iface", action="append")
 1408     add_arg("--dev-in", dest="dev-in", action="append")
 1409     add_arg("--dev-out", dest="dev-out", action="append")
 1410     add_arg("--up", dest="up", action="append")
 1411     add_arg("--down", dest="down", action="append")
 1412     add_arg("--broadcast", dest="broadcast", action="append")
 1413     add_arg("--loopback", dest="loopback", action="append")
 1414     add_arg("--pointtopoint", dest="pointtopoint", action="append")
 1415     add_arg("--running", dest="running", action="append")
 1416     add_arg("--noarp", dest="noarp", action="append")
 1417     add_arg("--arp", dest="arp", action="append")
 1418     add_arg("--promisc", dest="promisc", action="append")
 1419     add_arg("--multicast", dest="multicast", action="append")
 1420     add_arg("--dynamic", dest="dynamic", action="append")
 1421     add_arg("--lower-up", dest="lower-up", action="append")
 1422     add_arg("--dormant", dest="dormant", action="append")
 1423     ## ipp2p
 1424     add_arg("--edk", dest="edk", action="append")
 1425     add_arg("--kazaa", dest="kazaa", action="append")
 1426     add_arg("--gnu", dest="gnu", action="append")
 1427     add_arg("--dc", dest="dc", action="append")
 1428     add_arg("--bit", dest="bit", action="append")
 1429     add_arg("--apple", dest="apple", action="append")
 1430     add_arg("--soul", dest="soul", action="append")
 1431     add_arg("--winmx", dest="winmx", action="append")
 1432     add_arg("--ares", dest="ares", action="append")
 1433     add_arg("--debug", dest="debug", action="append")
 1434     ## ipv4options
 1435     add_arg("--flags", dest="flags", action="append")
 1436     add_arg("--any", dest="any", action="append")
 1437     ## length2
 1438     add_arg("--layer3", dest="layer3", action="append")
 1439     add_arg("--layer4", dest="layer4", action="append")
 1440     add_arg("--layer5", dest="layer5", action="append")
 1441     ## lscan
 1442     add_arg("--stealth", dest="stealth", action="append")
 1443     add_arg("--synscan", dest="synscan", action="append")
 1444     add_arg("--cnscan", dest="cnscan", action="append")
 1445     add_arg("--grscan", dest="grscan", action="append")
 1446     ## psd
 1447     add_arg("--psd-weight-threshold", dest="psd-weight-threshold", action="append")
 1448     add_arg("--psd-delay-threshold", dest="psd-delay-threshold", action="append")
 1449     add_arg("--psd-lo-ports-weight", dest="psd-lo-ports-weight", action="append")
 1450     add_arg("--psd-hi-ports-weight", dest="psd-hi-ports-weight", action="append")
 1451     ## quota2
 1452     add_arg("--grow", dest="grow", action="append")
 1453     add_arg("--no-change", dest="no-change", action="append")
 1454     add_arg("--packets", dest="packets", action="append")
 1455     ## pknock
 1456     add_arg("--knockports", dest="knockports", action="append")
 1457     add_arg("--time", dest="time", action="append")
 1458     add_arg("--autoclose", dest="autoclose", action="append")
 1459     add_arg("--checkip", dest="checkip", action="append")
 1460 
 1461     # TARGET EXTENSIONS
 1462     ## AUDIT
 1463     add_arg("--type", dest="type", action="append")
 1464     ## CHECKSUM
 1465     add_arg("--checksum-fill", dest="checksum-fill", action="append")
 1466     ## CLASSIFY
 1467     add_arg("--set-class", dest="set-class", action="append")
 1468     ## CLUSTERIP
 1469     add_arg("--new", dest="new", action="append")
 1470     add_arg("--hashmode", dest="hashmode", action="append")
 1471     add_arg("--clustermac", dest="clustermac", action="append")
 1472     add_arg("--total-nodes", dest="total-nodes", action="append")
 1473     add_arg("--local-node", dest="local-node", action="append")
 1474     add_arg("--hash-init", dest="hash-init", action="append")
 1475     ## CONNMARK
 1476     add_arg("--set-xmark", dest="set-xmark", action="append")
 1477     add_arg("--save-mark", dest="save-mark", action="append")
 1478     add_arg("--restore-mark", dest="restore-mark", action="append")
 1479     add_arg("--and-mark", dest="and-mark", action="append")
 1480     add_arg("--or-mark", dest="or-mark", action="append")
 1481     add_arg("--xor-mark", dest="xor-mark", action="append")
 1482     add_arg("--set-mark", dest="set-mark", action="append")
 1483     add_arg("--nfmask", dest="nfmask", action="append")
 1484     add_arg("--ctmask", dest="ctmask", action="append")
 1485     ## CONNSECMARK
 1486     add_arg("--save", dest="save", action="append")
 1487     add_arg("--restore", dest="restore", action="append")
 1488     ## CT
 1489     add_arg("--notrack", dest="notrack", action="append")
 1490     add_arg("--ctevents", dest="ctevents", action="append")
 1491     add_arg("--expevents", dest="expevents", action="append")
 1492     add_arg("--zone", dest="zone", action="append")
 1493     add_arg("--timeout", dest="timeout", action="append")
 1494     ## DNAT
 1495     add_arg("--to-destination", dest="to-destination", action="append")
 1496     add_arg("--random", dest="random", action="append")
 1497     add_arg("--persistent", dest="persistent", action="append")
 1498     ## DNPT
 1499     add_arg("--src-pfx", dest="src-pfx", action="append")
 1500     add_arg("--dst-pfx", dest="dst-pfx", action="append")
 1501     ## DSCP
 1502     add_arg("--set-dscp", dest="set-dscp", action="append")
 1503     add_arg("--set-dscp-class", dest="set-dscp-class", action="append")
 1504     ## ECN
 1505     add_arg("--ecn-tcp-remove", dest="ecn-tcp-remove", action="append")
 1506     ## HL
 1507     add_arg("--hl-set", dest="hl-set", action="append")
 1508     add_arg("--hl-dec", dest="hl-dec", action="append")
 1509     add_arg("--hl-inc", dest="hl-inc", action="append")
 1510     ## HMARK
 1511     add_arg("--hmark-tuple", dest="hmark-tuple", action="append")
 1512     add_arg("--hmark-mod", dest="hmark-mod", action="append")
 1513     add_arg("--hmark-offset", dest="hmark-offset", action="append")
 1514     add_arg("--hmark-src-prefix", dest="hmark-src-prefix", action="append")
 1515     add_arg("--hmark-dst-prefix", dest="hmark-dst-prefix", action="append")
 1516     add_arg("--hmark-sport-mask", dest="hmark-sport-mask", action="append")
 1517     add_arg("--hmark-dport-mask", dest="hmark-dport-mask", action="append")
 1518     add_arg("--hmark-spi-mask", dest="hmark-spi-mask", action="append")
 1519     add_arg("--hmark-proto-mask", dest="hmark-proto-mask", action="append")
 1520     add_arg("--hmark-rnd", dest="hmark-rnd", action="append")
 1521     ## LED
 1522     add_arg("--led-trigger-id", dest="led-trigger-id", action="append")
 1523     add_arg("--led-delay", dest="led-delay", action="append")
 1524     add_arg("--led-always-blink", dest="led-always-blink", action="append")
 1525     ## LOG
 1526     add_arg("--log-level", dest="log-level", action="append")
 1527     add_arg("--log-prefix", dest="log-prefix", action="append")
 1528     add_arg("--log-tcp-sequence", dest="log-tcp-sequence", action="append")
 1529     add_arg("--log-tcp-options", dest="log-tcp-options", action="append")
 1530     add_arg("--log-ip-options", dest="log-ip-options", action="append")
 1531     add_arg("--log-uid", dest="log-uid", action="append")
 1532     ## MASQUERADE
 1533     add_arg("--to-ports", dest="to-ports", action="append")
 1534     ## NFLOG
 1535     add_arg("--nflog-group", dest="nflog-group", action="append")
 1536     add_arg("--nflog-prefix", dest="nflog-prefix", action="append")
 1537     add_arg("--nflog-range", dest="nflog-range", action="append")
 1538     add_arg("--nflog-threshold", dest="nflog-threshold", action="append")
 1539     ## NFQUEUE
 1540     add_arg("--queue-num", dest="queue-num", action="append")
 1541     add_arg("--queue-balance", dest="queue-balance", action="append")
 1542     add_arg("--queue-bypass", dest="queue-bypass", action="append")
 1543     add_arg("--queue-cpu-fanout", dest="queue-cpu-fanout", action="append")
 1544     ## RATEEST
 1545     add_arg("--rateest-ewmalog", dest="rateest-ewmalog", action="append")
 1546     ## REJECT
 1547     add_arg("--reject-with", dest="reject-with", action="append")
 1548     ## SAME
 1549     add_arg("--nodst", dest="nodst", action="append")
 1550     ## SECMARK
 1551     add_arg("--selctx", dest="selctx", action="append")
 1552     ## SET
 1553     add_arg("--add-set", dest="add-set", action="append")
 1554     add_arg("--del-set", dest="del-set", action="append")
 1555     add_arg("--exist", dest="exist", action="append")
 1556     ## SNAT
 1557     add_arg("--to-source", dest="to-source", action="append")
 1558     ## TCPMSS
 1559     add_arg("--set-mss", dest="set-mss", action="append")
 1560     add_arg("--clamp-mss-to-pmtu", dest="clamp-mss-to-pmtu", action="append")
 1561     ## TCPOPTSTRIP
 1562     add_arg("--strip-options", dest="strip-options", action="append")
 1563     ## TEE
 1564     add_arg("--gateway", dest="gateway", action="append")
 1565     ## TOS
 1566     add_arg("--set-tos", dest="set-tos", action="append")
 1567     add_arg("--and-tos", dest="and-tos", action="append")
 1568     add_arg("--or-tos", dest="or-tos", action="append")
 1569     add_arg("--xor-tos", dest="xor-tos", action="append")
 1570     ## TPROXY
 1571     add_arg("--on-port", dest="on-port", action="append")
 1572     add_arg("--on-ip", dest="on-ip", action="append")
 1573     add_arg("--tproxy-mark", dest="tproxy-mark", action="append")
 1574     ## TTL
 1575     add_arg("--ttl-set", dest="ttl-set", action="append")
 1576     add_arg("--ttl-dec", dest="ttl-dec", action="append")
 1577     add_arg("--ttl-inc", dest="ttl-inc", action="append")
 1578     ## ULOG
 1579     add_arg("--ulog-nlgroup", dest="ulog-nlgroup", action="append")
 1580     add_arg("--ulog-prefix", dest="ulog-prefix", action="append")
 1581     add_arg("--ulog-cprange", dest="ulog-cprange", action="append")
 1582     add_arg("--ulog-qthreshold", dest="ulog-qthreshold", action="append")
 1583 
 1584     # Xtables-addons targets
 1585     ## ACCOUNT
 1586     add_arg("--addr", dest="addr", action="append")
 1587     add_arg("--tname", dest="tname", action="append")
 1588     ## CHAOS
 1589     add_arg("--delude", dest="delude", action="append")
 1590     add_arg("--tarpit", dest="tarpit", action="append")
 1591     ## DHCPMAC
 1592     add_arg("--set-mac", dest="set-mac", action="append")
 1593     ## DNETMAP
 1594     add_arg("--prefix", dest="prefix", action="append")
 1595     add_arg("--reuse", dest="reuse", action="append")
 1596     add_arg("--static", dest="static", action="append")
 1597     ## IPMARK
 1598     add_arg("--and-mask", dest="and-mask", action="append")
 1599     add_arg("--or-mask", dest="or-mask", action="append")
 1600     add_arg("--shift", dest="shift", action="append")
 1601     ## TARPIT
 1602     add_arg("--honeypot", dest="honeypot", action="append")
 1603     add_arg("--reset", dest="reset", action="append")
 1604 
 1605     return parser