def test_clear_rules(self): ruleset = pf.PFRuleset() ruleset.append(pf.PFRule(action=pf.PF_PASS, flags="S", flagset="SA", keep_state=pf.PF_STATE_NORMAL)) self.pf.load_ruleset(ruleset) self.pf.clear_rules() self.assertFalse(self.pf.get_ruleset().rules)
def _create_state(self): ruleset = pf.PFRuleset() ruleset.append(pf.PFRule(action=pf.PF_PASS, flags="S", flagset="SA", proto=IPPROTO_UDP, keep_state=pf.PF_STATE_NORMAL)) self.pf.load_ruleset(ruleset) self.pf.clear_states() with open(os.devnull, "w") as n: subprocess.call(["/usr/sbin/nslookup", "google.com"], stdout=n, stderr=n)
def test_load_ruleset(self): iface = pf.PFAddr(type=pf.PF_ADDR_DYNIFTL, ifname=self.testif) tables = [pf.PFTable("web_srv", "10.0.1.20", "10.0.1.21", "10.0.1.22")] rules = [ # match out on $ifname inet from !($ifname) to any nat-to ($ifname) pf.PFRule(action=pf.PF_MATCH, direction=pf.PF_OUT, ifname=self.testif, af=AF_INET, src=pf.PFRuleAddr(iface, neg=True), nat=pf.PFPool(pf.PF_POOL_NAT, iface)), # pass out quick pf.PFRule(action=pf.PF_PASS, direction=pf.PF_OUT, quick=True, flags="S", flagset="SA", keep_state=pf.PF_STATE_NORMAL), # anchor "test_anchor" pf.PFRuleset("test_anchor"), # pass in on $ifname inet proto tcp from any to $ifname port ssh pf.PFRule(action=pf.PF_PASS, direction=pf.PF_IN, ifname=self.testif, af=AF_INET, proto=IPPROTO_TCP, dst=pf.PFRuleAddr(iface, pf.PFPort("ssh", IPPROTO_TCP)), flags="S", flagset="SA", keep_state=pf.PF_STATE_NORMAL), # pass in on $ifname inet proto tcp to $ifname port www \ # rdr-to <web_srv> round-robin sticky-address pf.PFRule(action=pf.PF_PASS, direction=pf.PF_IN, ifname=self.testif, af=AF_INET, proto=IPPROTO_TCP, dst=pf.PFRuleAddr(iface, pf.PFPort("www", IPPROTO_TCP)), flags="S", flagset="SA", keep_state=pf.PF_STATE_NORMAL, rdr=pf.PFPool(pf.PF_POOL_RDR, pf.PFAddr("<web_srv>"), opts=(pf.PF_POOL_ROUNDROBIN| pf.PF_POOL_STICKYADDR))), # pass out on $ifname inet proto tcp to port 80 \ # divert-packet port 700 pf.PFRule(action=pf.PF_PASS, direction=pf.PF_OUT, ifname=self.testif, af=AF_INET, proto=IPPROTO_TCP, dst=pf.PFRuleAddr(port=pf.PFPort("www", IPPROTO_TCP)), divert=pf.PFDivert(pf.PF_DIVERT_PACKET, port=700)), # pass in inet proto icmp all icmp-type echoreq max-pkt-rate 100/10 pf.PFRule(action=pf.PF_PASS, direction=pf.PF_IN, af=AF_INET, proto=IPPROTO_ICMP, type=pf.ICMP_ECHO+1, keep_state=pf.PF_STATE_NORMAL, pktrate=pf.PFThreshold(100, 10))] rules[2].append( pf.PFTable("spammers", flags=pf.PFR_TFLAG_PERSIST), # pass in on $ifname inet proto tcp from ! <spammers> \ # to $ifname port 25 rdr-to 10.0.1.23 pf.PFRule(action=pf.PF_PASS, direction=pf.PF_IN, ifname=self.testif, af=AF_INET, proto=IPPROTO_TCP, src=pf.PFRuleAddr(pf.PFAddr("<spammers>"), neg=True), dst=pf.PFRuleAddr(iface, pf.PFPort(25, IPPROTO_TCP)), flags="S", flagset="SA", keep_state=pf.PF_STATE_NORMAL, rdr=pf.PFPool(pf.PF_POOL_RDR, pf.PFAddr("10.0.1.23")))) self.pf.clear_rules() rs = pf.PFRuleset() rs.append(*tables) rs.append(*rules) self.pf.load_ruleset(rs) self.assertEqual(len(self.pf.get_ruleset().rules), len(rules))
def rules(message=None): """Gather pf rules and show rules page""" if request.method == 'POST': # Remove rules if request.form.get('delete_rules') == "true": # Create list of rules to remove remove_list = list() for item, value in request.form.iteritems(): if item[:5] == 'rule_': remove_list.append(int(value)) # Remove each rule with the higher IDs first ruleset = packetfilter.get_ruleset() for value in sorted(remove_list, reverse=True): ruleset.remove(value) # Load edited ruleset packetfilter.load_ruleset(ruleset) message = PFWEB_ALERT_SUCCESS_DEL # Save pf.conf save_pfconf(packetfilter) # Set new order of rules elif request.form.get('save_order'): # Load JSON list form_order = json.loads(request.form['save_order']) # Load ruleset and rules. Create new ruleset to load old_ruleset = packetfilter.get_ruleset() old_rules = old_ruleset.rules new_ruleset = pf.PFRuleset() # Add the tables to the new ruleset new_ruleset.append(*old_ruleset.tables) # Run through new order and append each rule into their new spot for old_index in form_order: new_ruleset.append(old_rules[old_index]) # Load the ruleset back in packetfilter.load_ruleset(new_ruleset) # Save pf.conf save_pfconf(packetfilter) message = PFWEB_ALERT_SUCCESS_ORDER return redirect(url_for('rules', message=message), code=302) if message == PFWEB_ALERT_SUCCESS_DEL: message = {'alert': 'success', 'msg': 'Successfully deleted rule(s)'} elif message == PFWEB_ALERT_SUCCESS_ORDER: message = {'alert': 'success', 'msg': 'Successfully reordered rules'} elif message == PFWEB_ALERT_SUCCESS_EDIT: message = {'alert': 'success', 'msg': 'Successfully edited rule'} elif message == PFWEB_ALERT_SUCCESS_ADD: message = {'alert': 'success', 'msg': 'Successfully added rule'} rules = get_rules(packetfilter) # Create a dictionary of tables table_list = get_tables(packetfilter) tables = {t['name']: t['addrs'] for t in table_list} return render_template('rules.html', logged_in=flask_login.current_user.get_id(), fw_tab='active', rules=rules, tables=tables, port_ops=PFWEB_PORT_OPS, message=message)
def xml_to_pfrule(data): print "starting translation" print data xml_datas = [] xml_rules = xmltodict.parse( data, dict_constructor=dict )["mspl-set"]["it-resource"]["configuration"]["rule"] if isinstance(xml_rules, list): for xml_rule in xml_rules: xml_datas.append(xml_rule) else: xml_datas.append(xml_rules) rate_limit = None rules = pf.PFRuleset() for xml_data in xml_datas: print xml_data rule = pf.PFRule() if settings.quick_rules == "True": rule.quick = True Addrs = None Addrd = None Ports = None Portd = None xml_src = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "source-address") if xml_src is not None: Addrs = pf.PFAddr(xml_src) xml_dst = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "destination-address") if xml_dst is not None: Addrd = pf.PFAddr(xml_dst) xml_proto = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "protocol") if xml_proto is not None: if xml_proto.lower() == "tcp": rule.proto = socket.IPPROTO_TCP elif xml_proto.lower() == "udp": rule.proto = socket.IPPROTO_UDP xml_direction = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "direction") if xml_direction is not None: if xml_direction.lower() == "inbound": rule.direction = pf.PF_IN elif xml_direction.lower() == "outbound": rule.direction = pf.PF_OUT xml_interface = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "interface") if xml_interface is not None: rule.ifname = xml_interface.replace("eth", "vtnet") xml_sport = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "source-port") xml_dport = getValIfKeyExists( xml_data["condition"]["packet-filter-condition"], "destination-port") # Retrieve default target from MSPL default_target = getValIfKeyExists(xml_data, "action").upper() if default_target is not None: if default_target == "ACCEPT": rule.action = pf.PF_PASS rule.keep_state = pf.PF_STATE_NORMAL elif default_target == "DROP": rule.action = pf.PF_DROP elif default_target == "REJECT": rule.action = pf.PF_DROP rule.rule_flag = pf.PFRULE_RETURN elif default_target == "SCRUB": rule.action = pf.PF_SCRUB # In case of packets/sec rate limit: if getValIfKeyExists( xml_data["condition"], "traffic-flow-condition") is not None: # It is a number of allowed packets or bits per unit of time # (seconds, minutes, hours or days). # -m limit --limit <rate-limit> --limit-burst <limit-burst> \ # -j ACCEPT # rate_limit = getValIfKeyExists( # xml_data["condition"]["traffic-flow-condition"], # "rate-limit") # The maximum number of connections per host. max_connections = getValIfKeyExists( xml_data["condition"]["traffic-flow-condition"], "max-connections") # If the action is DROP or REJECT the rule will fire an error # if max_src_conn is setted if max_connections is not None and default_target == "ACCEPT": # rule.max_src_nodes = max_connections rule.max_src_conn = max_connections rule.rule_flag = pf.PFRULE_SRCTRACK # Connections rate limit connections_rate = getValIfKeyExists( xml_data["condition"]["traffic-flow-condition"], "connections-rate") # If the action is DROP or REJECT the rule will fire an error # if max_src_conn_rate is setted if connections_rate is not None and default_target == "ACCEPT": splitted = connections_rate.split('/') # rule.max_src_nodes = max_connections limit = splitted[0] seconds = splitted[1] rule.max_src_conn_rate = (limit, seconds) rule.rule_flag = pf.PFRULE_SRCTRACK # In case of specified ports, ports can be applied only # if protocol is specified: if xml_sport is not None: if xml_proto is not None: if xml_proto.lower() == "tcp": Ports = pf.PFPort(xml_sport, socket.IPPROTO_TCP) elif xml_proto.lower() == "udp": Ports = pf.PFPort(xml_sport, socket.IPPROTO_UDP) else: Ports = pf.PFPort(xml_sport) if xml_dport is not None: if xml_proto is not None: if xml_proto.lower() == "tcp": Portd = pf.PFPort(xml_dport, socket.IPPROTO_TCP) elif xml_proto.lower() == "udp": Portd = pf.PFPort(xml_dport, socket.IPPROTO_UDP) else: print xml_dport Portd = pf.PFPort(xml_dport) # TODO: Manage Priority priority = getValIfKeyExists(xml_data, "priority") if Addrs is not None and Ports is not None: rule.src = pf.PFRuleAddr(Addrs, Ports) elif Addrs is not None: rule.src = pf.PFRuleAddr(Addrs) elif Ports is not None: rule.src = pf.PFRuleAddr(pf.PFAddr(), Ports) if Addrd is not None and Portd is not None: rule.dst = pf.PFRuleAddr(Addrd, Portd) elif Addrd is not None: rule.dst = pf.PFRuleAddr(Addrd) elif Portd is not None: rule.dst = pf.PFRuleAddr(pf.PFAddr(), Portd) # Append rule rules.append(rule) return rules