def parse_forward_port(self, value, compat=False): port = None protocol = None toport = None toaddr = None i = 0 while ("=" in value[i:]): opt = value[i:].split("=", 1)[0] i += len(opt) + 1 if "=" in value[i:]: val = value[i:].split(":", 1)[0] else: val = value[i:] i += len(val) + 1 if opt == "port": port = val elif opt == "proto": protocol = val elif opt == "toport": toport = val elif opt == "toaddr": toaddr = val elif opt == "if" and compat: # ignore if option in compat mode pass else: raise FirewallError(errors.INVALID_FORWARD, "invalid forward port arg '%s'" % (opt)) if not port: raise FirewallError(errors.INVALID_FORWARD, "missing port") if not protocol: raise FirewallError(errors.INVALID_FORWARD, "missing protocol") if not (toport or toaddr): raise FirewallError(errors.INVALID_FORWARD, "missing destination") if not check_port(port): raise FirewallError(errors.INVALID_PORT, port) if protocol not in ["tcp", "udp", "sctp", "dccp"]: raise FirewallError(errors.INVALID_PROTOCOL, "'%s' not in {'tcp'|'udp'|'sctp'|'dccp'}" % \ protocol) if toport and not check_port(toport): raise FirewallError(errors.INVALID_PORT, toport) if toaddr and not check_single_address("ipv4", toaddr): if compat or not check_single_address("ipv6", toaddr): raise FirewallError(errors.INVALID_ADDR, toaddr) return (port, protocol, toport, toaddr)
def parse_forward_port(self, value, compat=False): port = None protocol = None toport = None toaddr = None i = 0 while ("=" in value[i:]): opt = value[i:].split("=", 1)[0] i += len(opt) + 1 if "=" in value[i:]: val = value[i:].split(":", 1)[0] else: val = value[i:] i += len(val) + 1 if opt == "port": port = val elif opt == "proto": protocol = val elif opt == "toport": toport = val elif opt == "toaddr": toaddr = val elif opt == "if" and compat: # ignore if option in compat mode pass else: raise FirewallError(errors.INVALID_FORWARD, "invalid forward port arg '%s'" % (opt)) if not port: raise FirewallError(errors.INVALID_FORWARD, "missing port") if not protocol: raise FirewallError(errors.INVALID_FORWARD, "missing protocol") if not (toport or toaddr): raise FirewallError(errors.INVALID_FORWARD, "missing destination") if not check_port(port): raise FirewallError(errors.INVALID_PORT, port) if protocol not in [ "tcp", "udp", "sctp", "dccp" ]: raise FirewallError(errors.INVALID_PROTOCOL, "'%s' not in {'tcp'|'udp'|'sctp'|'dccp'}" % \ protocol) if toport and not check_port(toport): raise FirewallError(errors.INVALID_PORT, toport) if toaddr and not check_single_address("ipv4", toaddr): if compat or not check_single_address("ipv6", toaddr): raise FirewallError(errors.INVALID_ADDR, toaddr) return (port, protocol, toport, toaddr)
def build_zone_forward_port_rules(self, enable, zone, filter_chain, port, protocol, toport, toaddr, mark_id): add_del = { True: "-A", False: "-D" }[enable] mark_str = "0x%x" % mark_id mark = [ "-m", "mark", "--mark", mark_str ] to = "" if toaddr: if check_single_address("ipv6", toaddr): to += "[%s]" % toaddr else: to += toaddr if toport and toport != "": to += ":%s" % portStr(toport, "-") target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS["PREROUTING"], zone=zone) rules = [] rules.append([ add_del, "%s_allow" % (target), "-t", "mangle", "-p", protocol, "--dport", portStr(port), "-j", "MARK", "--set-mark", mark_str ]) # local and remote rules.append([ add_del, "%s_allow" % (target), "-t", "nat", "-p", protocol ] + mark + [ "-j", "DNAT", "--to-destination", to ]) target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS[filter_chain], zone=zone) rules.append([ add_del, "%s_allow" % (target), "-t", "filter", "-m", "conntrack", "--ctstate", "NEW" ] + mark + [ "-j", "ACCEPT" ]) return rules
def build_zone_forward_port_rules(self, enable, zone, filter_chain, port, protocol, toport, toaddr, mark_id, rich_rule=None): add_del = {True: "-A", False: "-D"}[enable] mark_str = "0x%x" % mark_id mark = ["-m", "mark", "--mark", mark_str] to = "" if toaddr: if check_single_address("ipv6", toaddr): to += "[%s]" % toaddr else: to += toaddr if toport and toport != "": to += ":%s" % portStr(toport, "-") target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS["PREROUTING"], zone=zone) rule_fragment = ["-p", protocol, "--dport", portStr(port)] if rich_rule: rule_fragment += self._rich_rule_destination_fragment( rich_rule.destination) rule_fragment += self._rich_rule_source_fragment(rich_rule.source) rules = [] if rich_rule: rules.append( self._rich_rule_log(rich_rule, enable, "mangle", target, rule_fragment)) rules.append([add_del, "%s_allow" % (target), "-t", "mangle"] + rule_fragment + ["-j", "MARK", "--set-mark", mark_str]) # local and remote rules.append( [add_del, "%s_allow" % (target), "-t", "nat", "-p", protocol] + mark + ["-j", "DNAT", "--to-destination", to]) target = DEFAULT_ZONE_TARGET.format(chain=SHORTCUTS[filter_chain], zone=zone) rules.append([ add_del, "%s_allow" % (target), "-t", "filter", "-m", "conntrack", "--ctstate", "NEW" ] + mark + ["-j", "ACCEPT"]) return rules
def parse_forward_port(self, value): port = None protocol = None toport = None toaddr = None args = value.split(":") for arg in args: try: (opt, val) = arg.split("=") if opt == "port": port = val elif opt == "proto": protocol = val elif opt == "toport": toport = val elif opt == "toaddr": toaddr = val except ValueError: raise FirewallError(errors.INVALID_FORWARD, "invalid forward port arg '%s'" % (arg)) if not port: raise FirewallError(errors.INVALID_FORWARD, "missing port") if not protocol: raise FirewallError(errors.INVALID_FORWARD, "missing protocol") if not (toport or toaddr): raise FirewallError(errors.INVALID_FORWARD, "missing destination") if not check_port(port): raise FirewallError(errors.INVALID_PORT, port) if protocol not in [ "tcp", "udp", "sctp", "dccp" ]: raise FirewallError(errors.INVALID_PROTOCOL, "'%s' not in {'tcp'|'udp'|'sctp'|'dccp'}" % \ protocol) if toport and not check_port(toport): raise FirewallError(errors.INVALID_PORT, toport) if toaddr and not check_single_address("ipv4", toaddr): raise FirewallError(errors.INVALID_ADDR, toaddr) return (port, protocol, toport, toaddr)
def parse_forward_port(self, value): port = None protocol = None toport = None toaddr = None args = value.split(":") for arg in args: try: (opt, val) = arg.split("=") if opt == "port": port = val elif opt == "proto": protocol = val elif opt == "toport": toport = val elif opt == "toaddr": toaddr = val except ValueError: raise FirewallError(errors.INVALID_FORWARD, "invalid forward port arg '%s'" % (arg)) if not port: raise FirewallError(errors.INVALID_FORWARD, "missing port") if not protocol: raise FirewallError(errors.INVALID_FORWARD, "missing protocol") if not (toport or toaddr): raise FirewallError(errors.INVALID_FORWARD, "missing destination") if not check_port(port): raise FirewallError(errors.INVALID_PORT, port) if protocol not in [ "tcp", "udp" ]: raise FirewallError(errors.INVALID_PROTOCOL, "'%s' not in {'tcp'|'udp'}" % protocol) if toport and not check_port(toport): raise FirewallError(errors.INVALID_PORT, toport) if toaddr and not check_single_address("ipv4", toaddr): raise FirewallError(errors.INVALID_ADDR, toaddr) return (port, protocol, toport, toaddr)
def check(self): if self.family is not None and self.family not in ["ipv4", "ipv6"]: raise FirewallError(INVALID_FAMILY, self.family) if self.family is None: if self.source is not None or self.destination is not None: raise FirewallError(MISSING_FAMILY) if type(self.element) == Rich_ForwardPort: raise FirewallError(MISSING_FAMILY) if self.element is None: if self.action is None: raise FirewallError(INVALID_RULE, "no element, no action") if self.source is None: raise FirewallError(INVALID_RULE, "no element, no source") if self.destination is not None: raise FirewallError(INVALID_RULE, "destination action") if type(self.element) not in [ Rich_IcmpBlock, Rich_ForwardPort, Rich_Masquerade ]: if self.log is None and self.audit is None and \ self.action is None: raise FirewallError(INVALID_RULE, "no action, no log, no audit") # source if self.source is not None: if self.family is None: raise FirewallError(INVALID_FAMILY) if self.source.addr is None or \ not functions.check_address(self.family, self.source.addr): raise FirewallError(INVALID_ADDR, str(self.source.addr)) # destination if self.destination is not None: if self.family is None: raise FirewallError(INVALID_FAMILY) if self.destination.addr is None or \ not functions.check_address(self.family, self.destination.addr): raise FirewallError(INVALID_ADDR, str(self.destination.addr)) # service if type(self.element) == Rich_Service: # service availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(INVALID_SERVICE, str(self.element.name)) # port elif type(self.element) == Rich_Port: if not functions.check_port(self.element.port): raise FirewallError(INVALID_PORT, self.element.port) if not self.element.protocol in ["tcp", "udp"]: raise FirewallError(INVALID_PROTOCOL, self.element.protocol) # protocol elif type(self.element) == Rich_Protocol: if not functions.checkProtocol(self.element.value): raise FirewallError(INVALID_PROTOCOL, self.element.value) # masquerade elif type(self.element) == Rich_Masquerade: if self.destination is not None: raise FirewallError(INVALID_RULE, "masquerade and destination") if self.action is not None: raise FirewallError(INVALID_RULE, "masquerade and action") # icmp-block elif type(self.element) == Rich_IcmpBlock: # icmp type availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(INVALID_ICMPTYPE, str(self.element.name)) if self.action: raise FirewallError(INVALID_RULE, "icmp-block and action") # forward-port elif type(self.element) == Rich_ForwardPort: if not functions.check_port(self.element.port): raise FirewallError(INVALID_PORT, self.element.port) if not self.element.protocol in ["tcp", "udp"]: raise FirewallError(INVALID_PROTOCOL, self.element.protocol) if self.element.to_port == "" and self.element.to_address == "": raise FirewallError(INVALID_PORT, self.element.to_port) if self.element.to_port != "" and \ not functions.check_port(self.element.to_port): raise FirewallError(INVALID_PORT, self.element.to_port) if self.element.to_address != "" and \ not functions.check_single_address(self.family, self.element.to_address): raise FirewallError(INVALID_ADDR, self.element.to_address) if self.family is None: raise FirewallError(INVALID_FAMILY) if self.action is not None: raise FirewallError(INVALID_RULE, "forward-port and action") # other element and not empty? elif self.element is not None: raise FirewallError(INVALID_RULE, "Unknown element %s" % type(self.element)) # log if self.log is not None: if self.log.level and \ self.log.level not in [ "emerg", "alert", "crit", "error", "warning", "notice", "info", "debug" ]: raise FirewallError(INVALID_LOG_LEVEL, self.log.level) if self.log.limit is not None: self.log.limit.check() # audit if self.audit is not None: if type(self.action) not in [Rich_Accept, Rich_Reject, Rich_Drop]: raise FirewallError(INVALID_AUDIT_TYPE, type(self.action)) if self.audit.limit is not None: self.audit.limit.check() # action if self.action is not None: if type(self.action) == Rich_Reject: self.action.check(self.family) if self.action.limit is not None: self.action.limit.check()
def check(self): if self.family is not None and self.family not in ["ipv4", "ipv6"]: raise FirewallError(errors.INVALID_FAMILY, self.family) if self.family is None: if (self.source is not None and self.source.addr is not None) or \ self.destination is not None: raise FirewallError(errors.MISSING_FAMILY) if type(self.element) == Rich_ForwardPort: raise FirewallError(errors.MISSING_FAMILY) if self.priority < self.priority_min or self.priority > self.priority_max: raise FirewallError(errors.INVALID_PRIORITY, "'priority' attribute must be between %d and %d." \ % (self.priority_min, self.priority_max)) if self.element is None and \ (self.log is None or (self.log is not None and self.priority == 0)): if self.action is None: raise FirewallError(errors.INVALID_RULE, "no element, no action") if self.source is None and self.destination is None and self.priority == 0: raise FirewallError(errors.INVALID_RULE, "no element, no source, no destination") if type(self.element) not in [ Rich_IcmpBlock, Rich_ForwardPort, Rich_Masquerade, Rich_Tcp_Mss_Clamp ]: if self.log is None and self.audit is None and \ self.action is None: raise FirewallError(errors.INVALID_RULE, "no action, no log, no audit") # source if self.source is not None: if self.source.addr is not None: if self.family is None: raise FirewallError(errors.INVALID_FAMILY) if self.source.mac is not None: raise FirewallError(errors.INVALID_RULE, "address and mac") if self.source.ipset is not None: raise FirewallError(errors.INVALID_RULE, "address and ipset") if not functions.check_address(self.family, self.source.addr): raise FirewallError(errors.INVALID_ADDR, str(self.source.addr)) elif self.source.mac is not None: if self.source.ipset is not None: raise FirewallError(errors.INVALID_RULE, "mac and ipset") if not functions.check_mac(self.source.mac): raise FirewallError(errors.INVALID_MAC, str(self.source.mac)) elif self.source.ipset is not None: if not check_ipset_name(self.source.ipset): raise FirewallError(errors.INVALID_IPSET, str(self.source.ipset)) else: raise FirewallError(errors.INVALID_RULE, "invalid source") # destination if self.destination is not None: if self.destination.addr is not None: if self.family is None: raise FirewallError(errors.INVALID_FAMILY) if self.destination.ipset is not None: raise FirewallError(errors.INVALID_DESTINATION, "address and ipset") if not functions.check_address(self.family, self.destination.addr): raise FirewallError(errors.INVALID_ADDR, str(self.destination.addr)) elif self.destination.ipset is not None: if not check_ipset_name(self.destination.ipset): raise FirewallError(errors.INVALID_IPSET, str(self.destination.ipset)) else: raise FirewallError(errors.INVALID_RULE, "invalid destination") # service if type(self.element) == Rich_Service: # service availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(errors.INVALID_SERVICE, str(self.element.name)) # port elif type(self.element) == Rich_Port: if not functions.check_port(self.element.port): raise FirewallError(errors.INVALID_PORT, self.element.port) if self.element.protocol not in ["tcp", "udp", "sctp", "dccp"]: raise FirewallError(errors.INVALID_PROTOCOL, self.element.protocol) # protocol elif type(self.element) == Rich_Protocol: if not functions.checkProtocol(self.element.value): raise FirewallError(errors.INVALID_PROTOCOL, self.element.value) # masquerade elif type(self.element) == Rich_Masquerade: if self.action is not None: raise FirewallError(errors.INVALID_RULE, "masquerade and action") if self.source is not None and self.source.mac is not None: raise FirewallError(errors.INVALID_RULE, "masquerade and mac source") # icmp-block elif type(self.element) == Rich_IcmpBlock: # icmp type availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(errors.INVALID_ICMPTYPE, str(self.element.name)) if self.action: raise FirewallError(errors.INVALID_RULE, "icmp-block and action") # icmp-type elif type(self.element) == Rich_IcmpType: # icmp type availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(errors.INVALID_ICMPTYPE, str(self.element.name)) # forward-port elif type(self.element) == Rich_ForwardPort: if not functions.check_port(self.element.port): raise FirewallError(errors.INVALID_PORT, self.element.port) if self.element.protocol not in ["tcp", "udp", "sctp", "dccp"]: raise FirewallError(errors.INVALID_PROTOCOL, self.element.protocol) if self.element.to_port == "" and self.element.to_address == "": raise FirewallError(errors.INVALID_PORT, self.element.to_port) if self.element.to_port != "" and \ not functions.check_port(self.element.to_port): raise FirewallError(errors.INVALID_PORT, self.element.to_port) if self.element.to_address != "" and \ not functions.check_single_address(self.family, self.element.to_address): raise FirewallError(errors.INVALID_ADDR, self.element.to_address) if self.family is None: raise FirewallError(errors.INVALID_FAMILY) if self.action is not None: raise FirewallError(errors.INVALID_RULE, "forward-port and action") # source-port elif type(self.element) == Rich_SourcePort: if not functions.check_port(self.element.port): raise FirewallError(errors.INVALID_PORT, self.element.port) if self.element.protocol not in ["tcp", "udp", "sctp", "dccp"]: raise FirewallError(errors.INVALID_PROTOCOL, self.element.protocol) # tcp-mss-clamp elif type(self.element) == Rich_Tcp_Mss_Clamp: if self.action is not None: raise FirewallError( errors.INVALID_RULE, "tcp-mss-clamp and %s are mutually exclusive" % self.action) if self.element.value: if not functions.checkTcpMssClamp(self.element.value): raise FirewallError(errors.INVALID_RULE, self.element.value) # other element and not empty? elif self.element is not None: raise FirewallError(errors.INVALID_RULE, "Unknown element %s" % type(self.element)) # log if self.log is not None: self.log.check() # audit if self.audit is not None: if type(self.action) not in [Rich_Accept, Rich_Reject, Rich_Drop]: raise FirewallError(errors.INVALID_AUDIT_TYPE, type(self.action)) if self.audit.limit is not None: self.audit.limit.check() # action if self.action is not None: if type(self.action) == Rich_Reject: self.action.check(self.family) elif type(self.action) == Rich_Mark: self.action.check() if self.action.limit is not None: self.action.limit.check()
def check(self): if self.family is not None and self.family not in [ "ipv4", "ipv6" ]: raise FirewallError(INVALID_FAMILY, self.family) if self.family is None: if (self.source is not None and self.source.addr is not None) or \ self.destination is not None: raise FirewallError(MISSING_FAMILY) if type(self.element) == Rich_ForwardPort: raise FirewallError(MISSING_FAMILY) if self.element is None: if self.action is None: raise FirewallError(INVALID_RULE, "no element, no action") if self.source is None: raise FirewallError(INVALID_RULE, "no element, no source") if self.destination is not None: raise FirewallError(INVALID_RULE, "destination action") if type(self.element) not in [ Rich_IcmpBlock, Rich_ForwardPort, Rich_Masquerade ]: if self.log is None and self.audit is None and \ self.action is None: raise FirewallError(INVALID_RULE, "no action, no log, no audit") # source if self.source is not None: if self.source.addr is not None: if self.family is None: raise FirewallError(INVALID_FAMILY) if self.source.mac is not None: raise FirewallError(INVALID_RULE, "address and mac") if not functions.check_address(self.family, self.source.addr): raise FirewallError(INVALID_ADDR, str(self.source.addr)) elif self.source.mac is not None: if not functions.check_mac(self.source.mac): raise FirewallError(INVALID_MAC, str(self.source.mac)) elif self.source.ipset is not None: if not functions.check_ipset(self.source.ipset): raise FirewallError(INVALID_IPSET, str(self.source.ipset)) else: raise FirewallError(INVALID_RULE, "invalid source") # destination if self.destination is not None: if self.family is None: raise FirewallError(INVALID_FAMILY) if self.destination.addr is None or \ not functions.check_address(self.family, self.destination.addr): raise FirewallError(INVALID_ADDR, str(self.destination.addr)) # service if type(self.element) == Rich_Service: # service availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(INVALID_SERVICE, str(self.element.name)) # port elif type(self.element) == Rich_Port: if not functions.check_port(self.element.port): raise FirewallError(INVALID_PORT, self.element.port) if self.element.protocol not in [ "tcp", "udp" ]: raise FirewallError(INVALID_PROTOCOL, self.element.protocol) # protocol elif type(self.element) == Rich_Protocol: if not functions.checkProtocol(self.element.value): raise FirewallError(INVALID_PROTOCOL, self.element.value) # masquerade elif type(self.element) == Rich_Masquerade: if self.action is not None: raise FirewallError(INVALID_RULE, "masquerade and action") if self.source is not None and self.source.mac is not None: raise FirewallError(INVALID_RULE, "masquerade and mac source") # icmp-block elif type(self.element) == Rich_IcmpBlock: # icmp type availability needs to be checked in Firewall, here is no # knowledge about this, therefore only simple check if self.element.name is None or len(self.element.name) < 1: raise FirewallError(INVALID_ICMPTYPE, str(self.element.name)) if self.action: raise FirewallError(INVALID_RULE, "icmp-block and action") # forward-port elif type(self.element) == Rich_ForwardPort: if not functions.check_port(self.element.port): raise FirewallError(INVALID_PORT, self.element.port) if self.element.protocol not in [ "tcp", "udp" ]: raise FirewallError(INVALID_PROTOCOL, self.element.protocol) if self.element.to_port == "" and self.element.to_address == "": raise FirewallError(INVALID_PORT, self.element.to_port) if self.element.to_port != "" and \ not functions.check_port(self.element.to_port): raise FirewallError(INVALID_PORT, self.element.to_port) if self.element.to_address != "" and \ not functions.check_single_address(self.family, self.element.to_address): raise FirewallError(INVALID_ADDR, self.element.to_address) if self.family is None: raise FirewallError(INVALID_FAMILY) if self.action is not None: raise FirewallError(INVALID_RULE, "forward-port and action") # other element and not empty? elif self.element is not None: raise FirewallError(INVALID_RULE, "Unknown element %s" % type(self.element)) # log if self.log is not None: if self.log.level and \ self.log.level not in [ "emerg", "alert", "crit", "error", "warning", "notice", "info", "debug" ]: raise FirewallError(INVALID_LOG_LEVEL, self.log.level) if self.log.limit is not None: self.log.limit.check() # audit if self.audit is not None: if type(self.action) not in [ Rich_Accept, Rich_Reject, Rich_Drop ]: raise FirewallError(INVALID_AUDIT_TYPE, type(self.action)) if self.audit.limit is not None: self.audit.limit.check() # action if self.action is not None: if type(self.action) == Rich_Reject: self.action.check(self.family) if self.action.limit is not None: self.action.limit.check()