Esempio n. 1
0
    def rules(self, ipv, rules):
        _rules = []

        for rule in rules:
            # replace %%REJECT%%
            try:
                i = rule.index("%%REJECT%%")
            except ValueError:
                pass
            else:
                if ipv in ["ipv4", "ipv6"]:
                    rule[i:i + 1] = [
                        "REJECT", "--reject-with",
                        ipXtables.DEFAULT_REJECT_TYPE[ipv]
                    ]
                else:
                    raise FirewallError(errors.EBTABLES_NO_REJECT,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)

            # replace %%ICMP%%
            try:
                i = rule.index("%%ICMP%%")
            except ValueError:
                pass
            else:
                if ipv in ["ipv4", "ipv6"]:
                    rule[i] = ipXtables.ICMP[ipv]
                else:
                    raise FirewallError(errors.INVALID_IPV,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)

            # replace %%LOGTYPE%%
            try:
                i = rule.index("%%LOGTYPE%%")
            except ValueError:
                pass
            else:
                if self._log_denied == "off":
                    continue
                if ipv not in ["ipv4", "ipv6"]:
                    raise FirewallError(errors.INVALID_IPV,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)
                if self._log_denied in ["unicast", "broadcast", "multicast"]:
                    rule[i:i + 1] = [
                        "-m", "pkttype", "--pkt-type", self._log_denied
                    ]
                else:
                    rule.pop(i)

            _rules.append(rule)

        backend = None
        if ipv == "ipv4":
            if self.ip4tables_enabled:
                # do not call if disabled
                backend = self.ip4tables_backend
        elif ipv == "ipv6":
            if self.ip6tables_enabled:
                # do not call if disabled
                backend = self.ip6tables_backend
        elif ipv == "eb":
            if self.ebtables_enabled:
                # do not call if disabled
                backend = self.ebtables_backend
        else:
            raise FirewallError(errors.INVALID_IPV,
                                "'%s' not in {'ipv4'|'ipv6'|'eb'}" % ipv)

        if not backend:
            return ""

        if self._individual_calls or \
           not backend.restore_command_exists or \
           (ipv == "eb" and not self.ebtables_backend.restore_noflush_option):
            for i, rule in enumerate(_rules):
                # remove leading and trailing '"' for use with execve
                j = 0
                while j < len(rule):
                    x = rule[j]
                    if len(x) > 2 and x[0] == '"' and x[-1] == '"':
                        rule[j] = x[1:-1]
                    j += 1

                try:
                    backend.set_rule(rule)
                except Exception as msg:
                    log.error(
                        "Failed to apply rules. A firewall reload might solve the issue if the firewall has been modified using ip*tables or ebtables."
                    )
                    log.error(msg)
                    for rule in reversed(_rules[:i]):
                        try:
                            backend.set_rule(reverse_rule(rule))
                        except Exception:
                            # ignore errors here
                            pass
                    return False
            return True
        else:
            return backend.set_rules(_rules)
Esempio n. 2
0
    def rules(self, ipv, rules):
        _rules = [ ]

        for rule in rules:
            # replace %%REJECT%%
            try:
                i = rule.index("%%REJECT%%")
            except ValueError:
                pass
            else:
                if ipv in [ "ipv4", "ipv6" ]:
                    rule[i:i+1] = [ "REJECT", "--reject-with",
                                    ipXtables.DEFAULT_REJECT_TYPE[ipv] ]
                else:
                    raise FirewallError(errors.EBTABLES_NO_REJECT,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)

            # replace %%ICMP%%
            try:
                i = rule.index("%%ICMP%%")
            except ValueError:
                pass
            else:
                if ipv in [ "ipv4", "ipv6" ]:
                    rule[i] = ipXtables.ICMP[ipv]
                else:
                    raise FirewallError(errors.INVALID_IPV,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)

            # replace %%LOGTYPE%%
            try:
                i = rule.index("%%LOGTYPE%%")
            except ValueError:
                pass
            else:
                if self._log_denied == "off":
                    continue
                if ipv not in [ "ipv4", "ipv6" ]:
                    raise FirewallError(errors.INVALID_IPV,
                                        "'%s' not in {'ipv4'|'ipv6'}" % ipv)
                if self._log_denied in [ "unicast", "broadcast",
                                         "multicast" ]:
                    rule[i:i+1] = [ "-m", "pkttype", "--pkt-type",
                                    self._log_denied ]
                else:
                    rule.pop(i)

            _rules.append(rule)

        backend = None
        if ipv == "ipv4":
            if self.ip4tables_enabled:
                # do not call if disabled
                backend = self.ip4tables_backend
        elif ipv == "ipv6":
            if self.ip6tables_enabled:
                # do not call if disabled
                backend = self.ip6tables_backend
        elif ipv == "eb":
            if self.ebtables_enabled:
                # do not call if disabled
                backend = self.ebtables_backend
        else:
            raise FirewallError(errors.INVALID_IPV,
                                "'%s' not in {'ipv4'|'ipv6'|'eb'}" % ipv)

        if not backend:
            return ""

        if self._individual_calls or \
           not backend.restore_command_exists or \
           (ipv == "eb" and not self.ebtables_backend.restore_noflush_option):
            for i,rule in enumerate(_rules):
                # remove leading and trailing '"' for use with execve
                j = 0
                while j < len(rule):
                    x = rule[j]
                    if len(x) > 2 and x[0] == '"' and x[-1] == '"':
                        rule[j] = x[1:-1]
                    j += 1

                try:
                    backend.set_rule(rule)
                except Exception as msg:
                    log.error("Failed to apply rules. A firewall reload might solve the issue if the firewall has been modified using ip*tables or ebtables.")
                    log.error(msg)
                    for rule in reversed(_rules[:i]):
                        try:
                            backend.set_rule(reverse_rule(rule))
                        except Exception:
                            # ignore errors here
                            pass
                    return False
            return True
        else:
            return backend.set_rules(_rules)