|
1 | | -from simulator.packet import PacketIP |
| 1 | +from config import ProtoL3IP4IP6 |
| 2 | +from simulator.packet import PACKET_KINDS, PacketTCPUDP |
2 | 3 | from plugins.translate.abstract import Rule |
3 | 4 | from plugins.system.abstract_rule_match import RuleMatcher, RuleMatchResult |
4 | 5 | from plugins.translate.opnsense.rule import OPNsenseRule |
| 6 | +from utils.logger import log_warn, log_debug |
5 | 7 |
|
| 8 | +# todo: add explicit match-tests |
6 | 9 |
|
| 10 | + |
| 11 | +# pylint: disable=R0912 |
7 | 12 | class RuleMatcherOPNsense(RuleMatcher): |
8 | | - def matches(self, packet: PacketIP, rule: Rule) -> RuleMatchResult: |
| 13 | + def matches(self, packet: PACKET_KINDS, rule: Rule) -> RuleMatchResult: |
9 | 14 | """ |
10 | 15 | :param packet: Packet to match |
11 | 16 | :param rule: Rule to check |
12 | 17 | :return: RuleMatchResult |
13 | 18 | """ |
14 | 19 | opn_rule: OPNsenseRule = rule.raw |
15 | | - del opn_rule |
| 20 | + |
| 21 | + results = [] |
| 22 | + ### NETWORK INTERFACES ### |
| 23 | + if opn_rule.match_ni_in: |
| 24 | + results.append(packet.ni_in in opn_rule.nis) |
| 25 | + |
| 26 | + if opn_rule.match_ni_out: |
| 27 | + results.append(packet.ni_out in opn_rule.nis) |
| 28 | + |
| 29 | + ### PROTOCOLS ### |
| 30 | + if opn_rule.ipp is not None: |
| 31 | + if opn_rule.ipp == ProtoL3IP4IP6: |
| 32 | + results.append(True) |
| 33 | + |
| 34 | + else: |
| 35 | + results.append(opn_rule.ipp == packet.proto_l3) |
| 36 | + |
| 37 | + if opn_rule.proto is not None: |
| 38 | + if not hasattr(packet, 'proto_l4'): |
| 39 | + results.append(False) |
| 40 | + |
| 41 | + else: |
| 42 | + results.append(packet.proto_l4 in opn_rule.proto) |
| 43 | + |
| 44 | + ### SOURCE / DESTINATION ### |
| 45 | + if opn_rule.match_ip_saddr: |
| 46 | + if opn_rule.src_any: |
| 47 | + match = True |
| 48 | + |
| 49 | + else: |
| 50 | + match = any(packet.src in net for net in opn_rule.src) |
| 51 | + |
| 52 | + if opn_rule.src_invert: |
| 53 | + results.append(not match) |
| 54 | + |
| 55 | + else: |
| 56 | + results.append(match) |
| 57 | + |
| 58 | + if opn_rule.match_ip_daddr: |
| 59 | + if opn_rule.dst_any: |
| 60 | + match = True |
| 61 | + |
| 62 | + else: |
| 63 | + match = any(packet.dst in net for net in opn_rule.dst) |
| 64 | + |
| 65 | + if opn_rule.dst_invert: |
| 66 | + results.append(not match) |
| 67 | + |
| 68 | + else: |
| 69 | + results.append(match) |
| 70 | + |
| 71 | + ### PORTS ### |
| 72 | + if opn_rule.src_port is not None and len(opn_rule.src_port) > 0: |
| 73 | + if not isinstance(packet, PacketTCPUDP): |
| 74 | + results.append(False) |
| 75 | + |
| 76 | + else: |
| 77 | + results.append(packet.sport in opn_rule.src_port) |
| 78 | + |
| 79 | + if opn_rule.dst_port is not None and len(opn_rule.dst_port) > 0: |
| 80 | + if not isinstance(packet, PacketTCPUDP): |
| 81 | + results.append(False) |
| 82 | + |
| 83 | + else: |
| 84 | + results.append(packet.dport in opn_rule.dst_port) |
| 85 | + |
| 86 | + if len(results) == 0: |
| 87 | + log_warn('Firewall Plugin', ' > Matches: Found not matches we could process - skipping rule') |
| 88 | + |
| 89 | + else: |
| 90 | + log_debug('Firewall Plugin', f' > Match Results: {opn_rule.get_matches()} => {results}') |
| 91 | + |
| 92 | + return RuleMatchResult( |
| 93 | + matched=all(results), |
| 94 | + action=rule.action, |
| 95 | + target_chain_name=None, |
| 96 | + target_nat_ip=None, |
| 97 | + target_nat_port=None, |
| 98 | + ) |
| 99 | + |
| 100 | + # todo: SNAT / DNAT |
| 101 | + |
16 | 102 | return RuleMatchResult(False, None, None, None, None) |
0 commit comments