mode
mode
¶
Hook mode: OCI hooks + per-container netns.
Uses OCI hooks to apply per-container nftables rules inside each container's network namespace. No root required — only podman and nft.
Orchestrates collaborators per lifecycle phase:
- RulesetBuilder (
nft.rules) — generates and verifies nft rulesets - DnsResolver (
dns.resolver) — pre-start domain resolution - ProfileLoader (
profiles) — allowlist profile composition - AuditLogger (
audit) — event logging - CommandRunner (
run) — subprocess execution (nft, nsenter) - dnsmasq (
dns.dnsmasq) — runtime DNS with nftset auto-population - hook_install (
hooks.install) — OCI hook file generation - state (
state) — per-container state bundle I/O
logger = logging.getLogger(__name__)
module-attribute
¶
HookMode(*, config, runner, audit, dns, profiles, ruleset)
¶
Hook-mode shield backend (Strategy, implements ShieldModeBackend).
Coordinates the full lifecycle of OCI-hook-based container firewalling.
Delegates to RulesetBuilder for nft generation, DnsResolver for
name resolution, ProfileLoader for allowlists, dnsmasq for
runtime DNS, and state for per-container persistence.
Create a hook mode backend with all collaborators.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
ShieldConfig
|
Shield configuration (provides state_dir). |
required |
runner
|
CommandRunner
|
Command runner for subprocess calls. |
required |
audit
|
AuditLogger
|
Audit logger for event logging. |
required |
dns
|
DnsResolver
|
DNS resolver for domain resolution and caching. |
required |
profiles
|
ProfileLoader
|
Profile loader for allowlist profiles. |
required |
ruleset
|
RulesetBuilder
|
Ruleset builder for nft generation and verification. |
required |
Source code in src/terok_shield/hooks/mode.py
pre_start(container, profiles)
¶
Prepare for container start in hook mode.
Installs hooks, composes profiles, resolves DNS, writes allowlist, detects DNS tier, sets annotations, and returns the podman CLI arguments needed for shield protection.
Raises:
| Type | Description |
|---|---|
ShieldNeedsSetup
|
When global hooks are not installed
(see |
Source code in src/terok_shield/hooks/mode.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
allow_domain(domain)
¶
Add a domain to the dnsmasq config and signal reload.
Delegates to dnsmasq.add_domain(), which persists the domain to
live.domains (not profile.domains) and removes any matching
entry from denied.domains. When dnsmasq is running, a SIGHUP is
sent so the change takes effect immediately without a container restart.
These entries are runtime additions: they survive dnsmasq reloads but
are separate from the pre-start profile.domains list.
The IP-level allow (nft set update) is handled separately by
allow_ip() — this method is the domain-tracking counterpart
that ensures future IP rotations are also captured.
No-op when the container is not using the dnsmasq DNS tier (the
static IP-level allow already happened via allow_ip()).
Source code in src/terok_shield/hooks/mode.py
deny_domain(domain)
¶
Remove a domain from the dnsmasq config and signal reload.
Counterpart of allow_domain(). Removes the domain so dnsmasq
stops auto-populating nft sets for it on future DNS queries.
No-op when the container is not using the dnsmasq DNS tier.
Source code in src/terok_shield/hooks/mode.py
allow_ip(container, ip)
¶
Live-allow an IP for a running container via nsenter.
Source code in src/terok_shield/hooks/mode.py
deny_ip(container, ip)
¶
Live-deny an IP for a running container via nsenter.
Removes from the nft allow set (best-effort) and from live.allowed. Adds to the nft deny set. Always persists to deny.list so operator deny decisions stick across restarts.
Source code in src/terok_shield/hooks/mode.py
shield_down(container, *, allow_all=False)
¶
Switch a running container to shield-down (accept-all + deny.list).
Source code in src/terok_shield/hooks/mode.py
shield_quarantine(container)
¶
Total network blackout — drop all traffic, log dropped traffic.
Reads no settings — no DNS, no allowlists, no loopback ports,
no gateway probe, no profile lookup. build_quarantine /
verify_quarantine are static; the only inputs are the
container name and the live ruleset state (table-or-no-table).
Any config-conditional branch added here is a bug.
Source code in src/terok_shield/hooks/mode.py
shield_up(container)
¶
Restore normal deny-all mode for a running container.
Source code in src/terok_shield/hooks/mode.py
shield_state(container)
¶
Query the live nft ruleset to determine the container's shield state.
Source code in src/terok_shield/hooks/mode.py
list_rules(container)
¶
List current nft rules for a running container.
Source code in src/terok_shield/hooks/mode.py
preview(*, down=False, allow_all=False)
¶
Generate the ruleset that would be applied to a container.