Skip to content

Commit adefc5d

Browse files
committed
Add section "Set up container firewall"
Add example: Set up firewall that allows outgoing TCP/443 and UDP/53 Signed-off-by: Erik Sjölund <[email protected]>
1 parent 23b9fe0 commit adefc5d

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,120 @@ was fixed in crun 1.23).
24632463

24642464
</details>
24652465

2466+
## Set up container firewall
2467+
2468+
Configure the container firewall in a `createContainer` stage hook script.
2469+
This configuration is performed before the container is started.
2470+
The container process does not have privileges to read or write the firewall,
2471+
because the capability `NET_ADMIN` is not given to the container by default.
2472+
For details about capabilities,
2473+
see [__capabilities(7)__](https://man7.org/linux/man-pages/man7/capabilities.7.html).
2474+
2475+
> [!IMPORTANT]
2476+
> Do not specify `--cap-add net_admin` or `--privileged` when running a container that has
2477+
> a container firewall set up with a hook script, because the container process would
2478+
> then have the privilege to modify the firewall.
2479+
2480+
#### example: set up firewall that allows outgoing TCP/443 and UDP/53
2481+
2482+
Configure the container firewall to allow outgoing TCP/443 and UDP/53 but to drop
2483+
outgoing traffic for other TCP and UDP ports.
2484+
Show that curl in the container can download https://podman.io but not http://podman.io
2485+
2486+
Requirements:
2487+
2488+
The command `nft` needs to be installed on the host.
2489+
2490+
<details>
2491+
<summary>Click me</summary>
2492+
2493+
1. Check that the executable `/usr/bin/nft` from nftables is available on the host
2494+
```
2495+
ls /usr/bin/nft
2496+
```
2497+
The following output is expected
2498+
```
2499+
/usr/bin/nft
2500+
```
2501+
2. Create hooks dir
2502+
```
2503+
mkdir $HOME/hooks.d
2504+
```
2505+
The directory path was arbitrarily chosen.
2506+
3, Create policy file `$HOME/hooks.d/foobar.json` containing
2507+
```
2508+
{
2509+
"version": "1.0.0",
2510+
"hook": {
2511+
"path": "/home/test/configure-firewall.bash"
2512+
},
2513+
"when": {
2514+
"annotations": {
2515+
"^myannotation$": "yes"
2516+
}
2517+
},
2518+
"stages": ["createContainer"]
2519+
}
2520+
```
2521+
The filename `foobar.json` and the path
2522+
`/home/test/configure-firewall.bash` were arbitrarily chosen.
2523+
The strings `myannotation` and `yes` were arbitrarily chosen.
2524+
4. Create file `/home/test/configure-firewall.bash` containing
2525+
```
2526+
#!/bin/bash
2527+
echo "
2528+
table inet filter {
2529+
chain output {
2530+
type filter hook output priority filter; policy drop;
2531+
tcp dport 443 accept
2532+
udp dport 53 accept
2533+
}
2534+
}
2535+
" | /usr/bin/nft -f -
2536+
```
2537+
5. Change file permissions
2538+
```
2539+
chmod 755 /home/test/configure-firewall.bash
2540+
```
2541+
6. Run curl command to dowload http://podman.io
2542+
```
2543+
podman run \
2544+
--rm \
2545+
--hooks-dir ~/hooks.d \
2546+
--annotation myannotation=yes \
2547+
docker.io/library/fedora \
2548+
bash -c "curl -sS --connect-timeout 3 http://podman.io | head -1"
2549+
```
2550+
The command fails and the following error is printed
2551+
```
2552+
curl: (28) Connection timed out after 3000 millisecond
2553+
```
2554+
7. Run curl command to dowload https://podman.io
2555+
```
2556+
podman run \
2557+
--rm \
2558+
--hooks-dir ~/hooks.d \
2559+
--annotation myannotation=yes \
2560+
docker.io/library/fedora \
2561+
bash -c "curl -sS --connect-timeout 3 https://podman.io | head -1"
2562+
```
2563+
The command succeeds and the following output is printed
2564+
```
2565+
<!doctype html>
2566+
```
2567+
2568+
When configuring a container unit (quadlet), specify the hooks directory with [`GlobalArgs=`](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#globalargs) under the `[Container]` section.
2569+
For example
2570+
```
2571+
GlobalArgs=--hooks-dir=%h/hooks.d
2572+
```
2573+
The string `%h` is a [systemd specifier](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Specifiers) that is replaced with the home directory.
2574+
2575+
</details>
2576+
2577+
See also blog post [_Firewall a podman container_](https://jerabaul29.github.io/jekyll/update/2025/10/17/Firewall-a-podman-container.html)
2578+
by Jean Rabault (published October 2025). See also Podman GitHub [discussion](https://github.com/containers/podman/discussions/27099).
2579+
24662580
# Capture network traffic
24672581

24682582
The pasta option __--pcap__ enables capturing of network traffic.

0 commit comments

Comments
 (0)