Skip to content

Commit b98240c

Browse files
committed
handle terminal-actions from child-chains and chain default-policies, moved translate-config
1 parent 7663ea4 commit b98240c

File tree

15 files changed

+426
-211
lines changed

15 files changed

+426
-211
lines changed

README.md

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,23 @@ ftf-cli --firewall-system 'linux_netfilter' \
2828
--file-routes 'testdata/plugin_translate_linux_routes.json' \
2929
--file-route-rules 'testdata/plugin_translate_linux_route-rules.json' \
3030
--file-ruleset 'testdata/plugin_translate_netfilter_ruleset.json' \
31-
--src-ip 10.0.0.1 \
32-
--dst-ip 172.17.10.6
31+
--src-ip 172.17.11.5 \
32+
--dst-ip 2.2.2.2
3333

34-
> 🛈 ROUTER: Packet inbound-interface: wan
35-
> 🛈 ROUTER: Packet inbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
34+
> 🛈 ROUTER: Packet inbound-interface: docker0
35+
> 🛈 ROUTER: Packet inbound-route: 172.17.0.0/16, scope link
3636
> 🛈 FIREWALL: Processing Chain: Table nat ip4 | Chain PREROUTING ip4 nat
3737
> 🛈 FIREWALL: > Chain PREROUTING | Rule 0 | Match => jump
3838
> 🛈 FIREWALL: > Chain PREROUTING | Sub-Chain: DOCKER
39-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0
40-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1
41-
> 🛈 ROUTER: Packet outbound-interface: docker0
42-
> 🛈 ROUTER: Packet outbound-route: 172.17.0.0/16, scope link
39+
> 🛈 FIREWALL: > Chain DOCKER | Rule 0 | Match => return
40+
> 🛈 ROUTER: Packet outbound-interface: wan
41+
> 🛈 ROUTER: Packet outbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
4342
> 🛈 FIREWALL: Processing Chain: Table filter ip4 | Chain FORWARD ip4 filter
4443
> 🛈 FIREWALL: > Chain FORWARD | Rule 0 | Match => jump
4544
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-USER
4645
> 🛈 FIREWALL: > Chain DOCKER-USER | Rule 0 | Match => return
47-
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => jump
48-
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-FORWARD
49-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 0 | Match => jump
50-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-CT
51-
> 🛈 FIREWALL: > Chain DOCKER-CT | Rule 0 | Match => accept
52-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 1 | Match => jump
53-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-ISOLATION-STAGE-1
54-
> 🛈 FIREWALL: > Chain DOCKER-ISOLATION-STAGE-1 | Rule 0
55-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 2 | Match => jump
56-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-BRIDGE
57-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Rule 0 | Match => jump
58-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Sub-Chain: DOCKER
59-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0
60-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1 | Match => drop
61-
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
62-
46+
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => drop
47+
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #101 "TEST DROP" | Matches: [proto_l3 == ip4 & ip_daddr == ['2.2.2.2/32']]}
6348
```
6449

6550
----

docs/source/usage/3_run.rst

Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ Pass Example
9090
> 🛈 FIREWALL: > Chain FORWARD | Rule 0 | Match => jump
9191
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-USER
9292
> 🛈 FIREWALL: > Chain DOCKER-USER | Rule 0 | Match => return
93-
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => jump
93+
> 🛈 FIREWALL: > Chain FORWARD | Rule 1
94+
> 🛈 FIREWALL: > Chain FORWARD | Rule 2
95+
> 🛈 FIREWALL: > Chain FORWARD | Rule 3
96+
> 🛈 FIREWALL: > Chain FORWARD | Rule 4 | Match => jump
9497
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-FORWARD
9598
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 0 | Match => jump
9699
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-CT
@@ -116,36 +119,22 @@ Block Example
116119

117120
.. code-block:: bash
118121
119-
ftf-cli ... --src-ip 10.0.0.1 --dst-ip 172.17.10.6
122+
ftf-cli ... --src-ip 172.17.11.5 --dst-ip 2.2.2.2
120123
121-
> 🛈 ROUTER: Packet inbound-interface: wan
122-
> 🛈 ROUTER: Packet inbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
124+
> 🛈 ROUTER: Packet inbound-interface: docker0
125+
> 🛈 ROUTER: Packet inbound-route: 172.17.0.0/16, scope link
123126
> 🛈 FIREWALL: Processing Chain: Table nat ip4 | Chain PREROUTING ip4 nat
124127
> 🛈 FIREWALL: > Chain PREROUTING | Rule 0 | Match => jump
125128
> 🛈 FIREWALL: > Chain PREROUTING | Sub-Chain: DOCKER
126-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0
127-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1
128-
> 🛈 ROUTER: Packet outbound-interface: docker0
129-
> 🛈 ROUTER: Packet outbound-route: 172.17.0.0/16, scope link
129+
> 🛈 FIREWALL: > Chain DOCKER | Rule 0 | Match => return
130+
> 🛈 ROUTER: Packet outbound-interface: wan
131+
> 🛈 ROUTER: Packet outbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
130132
> 🛈 FIREWALL: Processing Chain: Table filter ip4 | Chain FORWARD ip4 filter
131133
> 🛈 FIREWALL: > Chain FORWARD | Rule 0 | Match => jump
132134
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-USER
133135
> 🛈 FIREWALL: > Chain DOCKER-USER | Rule 0 | Match => return
134-
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => jump
135-
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-FORWARD
136-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 0 | Match => jump
137-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-CT
138-
> 🛈 FIREWALL: > Chain DOCKER-CT | Rule 0 | Match => accept
139-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 1 | Match => jump
140-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-ISOLATION-STAGE-1
141-
> 🛈 FIREWALL: > Chain DOCKER-ISOLATION-STAGE-1 | Rule 0
142-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 2 | Match => jump
143-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-BRIDGE
144-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Rule 0 | Match => jump
145-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Sub-Chain: DOCKER
146-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0
147-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1 | Match => drop
148-
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
136+
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => drop
137+
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #101 "TEST DROP" | Matches: [proto_l3 == ip4 & ip_daddr == ['2.2.2.2/32']]}
149138
150139
----
151140

@@ -156,45 +145,31 @@ You can get more detailed output by increasing the verbosity:
156145

157146
.. code-block:: bash
158147
159-
ftf-cli ... --src-ip 10.0.0.1 --dst-ip 172.17.10.6 --verbosity 2
148+
ftf-cli ... --src-ip 172.17.11.5 --dst-ip 2.2.2.2 --verbosity 2
160149
161-
> 🛈 ROUTER: Packet inbound-interface: wan
162-
> 🛈 ROUTER: Packet inbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
150+
> 🛈 ROUTER: Packet inbound-interface: docker0
151+
> 🛈 ROUTER: Packet inbound-route: 172.17.0.0/16, scope link
163152
> 🛈 FIREWALL: Processing Chain: Table nat ip4 | Chain PREROUTING ip4 nat
164153
> 🛈 FIREWALL: > Chain PREROUTING | Rule 0 | Match => jump | {'action': 'jump', 'seq': 0, 'raw': Rule: #3 | Matches: []}
165154
> 🛈 FIREWALL: > Chain PREROUTING | Sub-Chain: DOCKER
166-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0 | {'action': 'return', 'seq': 0, 'raw': Rule: #10 | Matches: [ni_in == ['docker0']]}
167-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1 | {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
155+
> 🛈 FIREWALL: > Chain DOCKER | Rule 0 | Match => return | {'action': 'return', 'seq': 0, 'raw': Rule: #10 | Matches: [ni_in == ['docker0']]}
168156
> 🛈 FIREWALL: Flow-type: forward
169-
> 🛈 ROUTER: Packet outbound-interface: docker0
170-
> 🛈 ROUTER: Packet outbound-route: 172.17.0.0/16, scope link
157+
> 🛈 ROUTER: Packet outbound-interface: wan
158+
> 🛈 ROUTER: Packet outbound-route: 0.0.0.0/0, gw 10.255.255.254, metric 600, scope remote
171159
> 🛈 FIREWALL: Processing Chain: Table filter ip4 | Chain FORWARD ip4 filter
172160
> 🛈 FIREWALL: > Chain FORWARD | Rule 0 | Match => jump | {'action': 'jump', 'seq': 0, 'raw': Rule: #20 | Matches: []}
173161
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-USER
174162
> 🛈 FIREWALL: > Chain DOCKER-USER | Rule 0 | Match => return | {'action': 'return', 'seq': 0, 'raw': Rule: #19 | Matches: []}
175-
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => jump | {'action': 'jump', 'seq': 1, 'raw': Rule: #8 | Matches: []}
176-
> 🛈 FIREWALL: > Chain FORWARD | Sub-Chain: DOCKER-FORWARD
177-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 0 | Match => jump | {'action': 'jump', 'seq': 0, 'raw': Rule: #11 | Matches: []}
178-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-CT
179-
> 🛈 FIREWALL: > Chain DOCKER-CT | Rule 0 | Match => accept | {'action': 'accept', 'seq': 0, 'raw': Rule: #23 | Matches: [ni_out == ['docker0']]}
180-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 1 | Match => jump | {'action': 'jump', 'seq': 1, 'raw': Rule: #10 | Matches: []}
181-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-ISOLATION-STAGE-1
182-
> 🛈 FIREWALL: > Chain DOCKER-ISOLATION-STAGE-1 | Rule 0 | {'action': 'jump', 'seq': 0, 'raw': Rule: #25 | Matches: [ni_in == ['docker0'], ni_out != ['docker0']]}
183-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Rule 2 | Match => jump | {'action': 'jump', 'seq': 2, 'raw': Rule: #9 | Matches: []}
184-
> 🛈 FIREWALL: > Chain DOCKER-FORWARD | Sub-Chain: DOCKER-BRIDGE
185-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Rule 0 | Match => jump | {'action': 'jump', 'seq': 0, 'raw': Rule: #24 | Matches: [ni_out == ['docker0']]}
186-
> 🛈 FIREWALL: > Chain DOCKER-BRIDGE | Sub-Chain: DOCKER
187-
> 🛈 FIREWALL: > Chain DOCKER | Rule 0 | {'action': 'return', 'seq': 0, 'raw': Rule: #10 | Matches: [ni_in == ['docker0']]}
188-
> 🛈 FIREWALL: > Chain DOCKER | Rule 1 | Match => drop | {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
189-
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
163+
> 🛈 FIREWALL: > Chain FORWARD | Rule 1 | Match => drop | {'action': 'drop', 'seq': 1, 'raw': Rule: #101 "TEST IP4-DADDR DROP" | Matches: [proto_l3 == ip4 & ip_daddr == ['2.2.2.2/32']]}
164+
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #101 "TEST IP4-DADDR DROP" | Matches: [proto_l3 == ip4 & ip_daddr == ['2.2.2.2/32']]}
190165
191166
Or run use the silent-mode:
192167

193168
.. code-block:: bash
194169
195-
ftf-cli ... --src-ip 10.0.0.1 --dst-ip 172.17.10.6 --verbosity silent
170+
ftf-cli ... --src-ip 172.17.11.5 --dst-ip 2.2.2.2 --verbosity silent
196171
197-
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #22 | Matches: [ni_in != ['docker0'], ni_out == ['docker0']]}
172+
> ✖ FIREWALL: Packet blocked by rule: {'action': 'drop', 'seq': 1, 'raw': Rule: #101 "TEST IP4-DADDR DROP" | Matches: [proto_l3 == ip4 & ip_daddr == ['2.2.2.2/32']]}
198173
199174
----
200175

src/firewall_test/config.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,77 @@ class Match(ABC):
8989

9090
class MatchPort(Match):
9191
N = 'port'
92+
93+
94+
class RuleAction(ABC):
95+
N = 'Abstract Rule-Action'
96+
97+
98+
class RuleActionKindTerminal(RuleAction):
99+
N = 'Abstract Rule-Action Terminal'
100+
101+
102+
class RuleActionKindTerminalKill(RuleActionKindTerminal):
103+
N = 'Abstract Rule-Action Terminal'
104+
105+
106+
class RuleActionAccept(RuleActionKindTerminal):
107+
N = 'accept'
108+
109+
110+
class RuleActionDrop(RuleActionKindTerminalKill):
111+
N = 'drop'
112+
113+
114+
class RuleActionReject(RuleActionKindTerminalKill):
115+
N = 'reject'
116+
117+
118+
class RuleActionKindToChain(RuleAction):
119+
N = 'Abstract Rule-Action To-Chain'
120+
121+
122+
class RuleActionJump(RuleActionKindToChain):
123+
N = 'jump'
124+
125+
126+
class RuleActionGoTo(RuleActionKindToChain):
127+
N = 'goto'
128+
129+
130+
class RuleActionReturn(RuleActionKindTerminal):
131+
N = 'return'
132+
133+
134+
class RuleActionContinue(RuleAction):
135+
N = 'continue'
136+
137+
138+
class RuleActionKindNAT(RuleAction):
139+
N = 'Abstract Rule-Action NAT'
140+
141+
142+
class RuleActionDNAT(RuleActionKindNAT):
143+
N = 'dnat'
144+
145+
146+
class RuleActionSNAT(RuleActionKindNAT):
147+
N = 'snat'
148+
149+
150+
RULE_ACTIONS = [
151+
RuleActionAccept, RuleActionDrop, RuleActionReject,
152+
RuleActionJump, RuleActionGoTo, RuleActionContinue, RuleActionReturn,
153+
RuleActionDNAT, RuleActionSNAT,
154+
]
155+
RULE_ACTION_MAPPING = {
156+
RuleActionAccept.N: RuleActionAccept,
157+
RuleActionDrop.N: RuleActionDrop,
158+
RuleActionReject.N: RuleActionReject,
159+
RuleActionJump.N: RuleActionJump,
160+
RuleActionGoTo.N: RuleActionGoTo,
161+
RuleActionContinue.N: RuleActionContinue,
162+
RuleActionReturn.N: RuleActionReturn,
163+
RuleActionDNAT.N: RuleActionDNAT,
164+
RuleActionSNAT.N: RuleActionSNAT,
165+
}

src/firewall_test/plugins/system/abstract_rule_match.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from abc import abstractmethod
22
from ipaddress import IPv4Address, IPv6Address
33

4+
from config import RuleAction
45
from plugins.system.abstract import BaseRuleMatcher
5-
from plugins.translate.config import RuleAction
66
from plugins.translate.abstract import Table, Rule
77
from simulator.packet import PacketIP
88

src/firewall_test/plugins/system/firewall_netfilter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
from config import RuleActionKindTerminal, RuleActionKindToChain, RuleActionKindNAT
12
from plugins.system.abstract_rule_match import RuleMatcher, RuleMatchResult
2-
from plugins.translate.config import RuleActionKindTerminal, RuleActionKindToChain, RuleActionKindNAT
33
from plugins.translate.abstract import Rule
44
from plugins.translate.netfilter.parse import NftRule
55
from simulator.packet import PacketIP, PacketTCPUDP, PacketICMP

src/firewall_test/plugins/translate/abstract.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
from ipaddress import ip_network, ip_address, IPv4Network, IPv6Network, IPv4Address, IPv6Address
33
from re import compile as regex_compile
44

5-
from config import ProtoL3, ProtoL3IP4, ProtoL3IP6, PROTOS_L3, ProtoL3IP4IP6
6-
from plugins.translate.config import RuleAction, RuleActionAccept, RuleActionReject, RuleActionDrop, \
7-
RuleActionJump, RuleActionGoTo, RuleActionContinue, RULE_ACTIONS, RuleActionReturn
5+
from config import ProtoL3, ProtoL3IP4, ProtoL3IP6, PROTOS_L3, ProtoL3IP4IP6, \
6+
RuleAction, RuleActionAccept, RuleActionReject, RuleActionDrop, \
7+
RuleActionJump, RuleActionGoTo, RuleActionContinue, RULE_ACTIONS, RuleActionReturn, RULE_ACTION_MAPPING
88

99
REGEX_MAC_ADDRESS = regex_compile(r'^[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}:[\da-f]{2}$')
1010

@@ -295,15 +295,14 @@ class Chain(TranslateOutput):
295295
FAMILY_IP6 = ProtoL3IP6.N
296296
FAMILIES = [FAMILY_IP, FAMILY_IP4, FAMILY_IP6]
297297

298-
POLICY_ACCEPT = 'accept'
299-
POLICY_DROP = 'drop'
300-
POLICY_REJECT = 'reject'
301-
POLICIES = [POLICY_ACCEPT, POLICY_DROP, POLICY_REJECT]
298+
POLICY_ACCEPT = RuleActionAccept
299+
POLICY_DROP = RuleActionDrop
300+
POLICY_REJECT = RuleActionReject
302301

303302
# pylint: disable=W0622
304303
def __init__(
305-
self, name: str, hook: str, policy: str, rules: list[Rule], priority: int = 0,
306-
type: str = 'filter', family: type[ProtoL3] = ProtoL3IP4IP6,
304+
self, name: str, hook: str, policy: (None, RuleActionAccept, RuleActionDrop, RuleActionReject),
305+
rules: list[Rule], priority: int = 0, type: str = 'filter', family: type[ProtoL3] = ProtoL3IP4IP6,
307306
):
308307
self.name = name
309308
self.type = type
@@ -313,6 +312,9 @@ def __init__(
313312
self.policy = policy
314313
self.rules = rules
315314

315+
if self.policy is None:
316+
self.policy = RuleActionAccept
317+
316318
# runtime infos
317319
self.run_table = None
318320

@@ -321,7 +323,7 @@ def dump(self) -> dict:
321323
"name": self.name,
322324
"type": self.type,
323325
"hook": self.hook,
324-
"policy": self.policy,
326+
"policy": self.policy.N,
325327
"priority": self.priority,
326328
"family": self.family.N,
327329
"rules": [r.dump() for r in self.rules],
@@ -336,7 +338,7 @@ def validate(self):
336338
r = self.dump()
337339
assert isinstance(r['name'], str)
338340
assert len(r['name']) > 0
339-
assert r['policy'] in self.POLICIES
341+
assert r['policy'] in RULE_ACTION_MAPPING
340342
assert isinstance(r['priority'], int)
341343
assert r['type'] in self.TYPES
342344
if len(r['rules']) > 0:

src/firewall_test/plugins/translate/config.py

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

0 commit comments

Comments
 (0)