Skip to content

Commit 6c090e1

Browse files
committed
extending tests for firewall chain handling
1 parent d018d2d commit 6c090e1

File tree

4 files changed

+90
-113
lines changed

4 files changed

+90
-113
lines changed
Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,98 @@
11
import pytest
22

33
from testdata_test import TESTDATA_FILE_NF_RULESET
4-
from config import ProtoL3IP4, ProtoL3IP4IP6, ProtoL3IP6, FlowInput, FlowOutput, FlowForward
4+
from config import ProtoL3IP4, ProtoL3IP6 # RuleActionAccept, RuleActionDrop, RuleActionReject, RuleActionSNAT
5+
from simulator.firewall import Firewall
56

67
with open(TESTDATA_FILE_NF_RULESET, 'r', encoding='utf-8') as f:
78
TESTDATA_RULESET = f.read()
89

910

11+
def _init_test() -> Firewall:
12+
from plugins.system.system_linux_netfilter import SystemLinuxNetfilter
13+
from plugins.translate.netfilter.ruleset import NetfilterRuleset
14+
from simulator.firewall import Firewall
1015

11-
def test_firewall_chains_basic():
16+
ruleset = NetfilterRuleset(TESTDATA_RULESET).get()
17+
return Firewall(
18+
system=SystemLinuxNetfilter,
19+
ruleset=ruleset,
20+
)
21+
22+
23+
@pytest.mark.parametrize(
24+
'src,dst,table_name,ipp,is_none',
25+
[
26+
('192.168.0.10', '1.1.1.1', 'main', ProtoL3IP4, False),
27+
('192.168.0.10', '1.1.1.1', 'main', ProtoL3IP6, True),
28+
('192.168.0.10', '1.1.1.1', 'early', ProtoL3IP4, False),
29+
('::1', '2003::2', 'main', ProtoL3IP6, False),
30+
('::1', '2003::2', 'main', ProtoL3IP4, True),
31+
]
32+
)
33+
def test_firewall_chain_by_name_and_family(src, dst, table_name, ipp, is_none):
1234
from simulator.packet import PacketIP
1335
from simulator.firewall import Firewall
14-
from plugins.translate.abstract import Table
36+
from plugins.translate.abstract import Table, Ruleset
1537
from plugins.system.system_linux_netfilter import SystemLinuxNetfilter
16-
from plugins.translate.netfilter.ruleset import NetfilterRuleset
38+
from plugins.translate.netfilter.ruleset import NetfilterChainOutput as Chain
39+
40+
table_early = Table(
41+
name='early',
42+
priority=-1,
43+
chains=[
44+
Chain(name='input', hook='input', policy=Chain.POLICY_ACCEPT, family=ProtoL3IP4, rules=[]),
45+
Chain(name='input', hook='input', policy=Chain.POLICY_ACCEPT, family=ProtoL3IP6, rules=[]),
46+
],
47+
)
48+
table_main = Table(
49+
name='main',
50+
chains=[
51+
Chain(name='input', hook='input', policy=Chain.POLICY_DROP, family=ProtoL3IP4, rules=[]),
52+
Chain(name='input', hook='input', policy=Chain.POLICY_DROP, family=ProtoL3IP6, rules=[]),
53+
Chain(name='input', hook='input', policy=Chain.POLICY_DROP, rules=[]),
54+
],
55+
)
1756

18-
ruleset = NetfilterRuleset(TESTDATA_RULESET).get()
1957
fw = Firewall(
2058
system=SystemLinuxNetfilter,
21-
ruleset=ruleset,
59+
ruleset=Ruleset(tables=[table_early, table_main]),
2260
)
23-
# packet = PacketIP(src=src, dst=dst)
24-
# table = Table(name='test', chains=[], family=ipp)
25-
# assert fw._run_tables._is_matching_table(packet=packet, table=table) == matching
61+
packet = PacketIP(src=src, dst=dst)
62+
table = None
63+
for t in fw.ruleset.tables:
64+
if t.name == table_name:
65+
table = t
66+
67+
for c in t.chains:
68+
c.run_table = t
69+
70+
c = fw._run_tables._run_chains._get_chain_by_name_and_family(
71+
packet=packet,
72+
name='input',
73+
family=ipp,
74+
table=table,
75+
)
76+
if is_none:
77+
assert c is None
78+
79+
else:
80+
assert c is not None
81+
assert c.name == 'input'
82+
assert c.hook == 'input'
83+
assert c.family == ipp
84+
assert c.run_table.name == table_name
85+
86+
87+
# todo: test multiple testdata-rulesets for edge-case handling (RunFirewallChain.process)
88+
# sub-chain (jump) terminal action should end hook
89+
# sub-chain (goto) should end parent chain
90+
# dnat
91+
# snat
92+
# masquerade
93+
# action return
94+
# action continue (?)
95+
# lazy action
96+
# lazy action mixed with 'quick' action
97+
# chain default-policy
98+

src/firewall_test/simulator/06_firewall_test.py

Lines changed: 0 additions & 100 deletions
This file was deleted.

src/firewall_test/simulator/firewall.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ def __init__(self, fw, run_tables):
1616
self._fw = fw
1717
self._run_tables = run_tables
1818

19-
def _get_chain_by_name_and_family(self, packet: PACKET_KINDS, name: str, family: str) -> (Chain, None):
20-
for table in self._run_tables.get_tables(packet):
21-
for chain in self._run_tables.get_chains(packet=packet, table=table):
19+
def _get_chain_by_name_and_family(self, packet: PACKET_KINDS, table: Table, name: str, family: str) -> (Chain, None):
20+
for t in self._run_tables.get_tables(packet):
21+
if t.name != table.name or t.family != table.family or t.priority != table.priority:
22+
continue
23+
24+
for chain in self._run_tables.get_chains(packet=packet, table=t):
2225
if chain.name == name and chain.family == family:
2326
return chain
2427

@@ -101,6 +104,7 @@ def process(self, chain: Chain, packet: PACKET_KINDS) -> (bool, (Rule, None)):
101104
packet=packet,
102105
name=result.target_chain_name,
103106
family=chain.family,
107+
table=chain.run_table,
104108
)
105109
if target_chain is None:
106110
log_warn(
@@ -146,7 +150,7 @@ def process(self, chain: Chain, packet: PACKET_KINDS) -> (bool, (Rule, None)):
146150
log_debug('Firewall', f'> Chain {chain.name} | Applying lazy-action: {action_str}')
147151
return not issubclass(lazy_action, RuleActionKindTerminalKill), lazy_rule
148152

149-
if chain.policy in [RuleActionDrop, RuleActionReject]:
153+
if chain.type == chain.TYPE_FILTER and chain.policy in [RuleActionDrop, RuleActionReject]:
150154
return False, None
151155

152156
return True, None

0 commit comments

Comments
 (0)