Implement Podman pod security with network policies and microsegmentation

Advanced 45 min Apr 23, 2026 584 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Secure Podman pods with custom network policies, traffic filtering, and microsegmentation using CNI plugins and netavark. Implement zero-trust networking with firewall rules and container isolation.

Prerequisites

  • Root or sudo access
  • Basic understanding of containers and networking
  • Familiarity with iptables and systemd

What this solves

Podman's default networking allows containers to communicate freely, creating potential security risks in multi-tenant environments. This tutorial implements network policies and microsegmentation to control traffic between pods, isolate workloads, and create secure network boundaries using CNI plugins and custom firewall rules.

Step-by-step configuration

Update system and install Podman with network tools

Install Podman and required networking components for advanced security configuration.

sudo apt update && sudo apt upgrade -y
sudo apt install -y podman cni-plugins iptables netavark aardvark-dns slirp4netns
sudo dnf update -y
sudo dnf install -y podman cni-plugins iptables netavark aardvark-dns slirp4netns

Configure Podman for rootless operation with network security

Enable user namespaces and configure subuid/subgid mappings for secure container isolation.

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami)
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
podman system migrate

Create custom secure network configurations

Define network policies with traffic filtering and microsegmentation capabilities.

{
  "name": "secure-frontend",
  "cniVersion": "1.0.0",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "secure-frontend0",
      "isDefaultGateway": true,
      "ipMasq": true,
      "hairpinMode": true,
      "ipam": {
        "type": "host-local",
        "subnet": "10.89.0.0/24",
        "routes": [
          {
            "dst": "0.0.0.0/0"
          }
        ]
      }
    },
    {
      "type": "firewall",
      "backend": "iptables"
    },
    {
      "type": "tuning"
    }
  ]
}

Create backend network with restricted access

Configure an isolated backend network that blocks external internet access.

{
  "name": "secure-backend",
  "cniVersion": "1.0.0",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "secure-backend0",
      "isDefaultGateway": false,
      "ipMasq": false,
      "hairpinMode": false,
      "ipam": {
        "type": "host-local",
        "subnet": "10.90.0.0/24"
      }
    },
    {
      "type": "firewall",
      "backend": "iptables",
      "iptablesAdminChainName": "BACKEND_ADMIN"
    }
  ]
}

Configure network policies with iptables rules

Implement granular traffic filtering between network segments using custom iptables chains.

#!/bin/bash

# Create custom iptables chains for network policies
iptables -t filter -N PODMAN_FRONTEND_POLICY 2>/dev/null
iptables -t filter -N PODMAN_BACKEND_POLICY 2>/dev/null
iptables -t filter -N PODMAN_MICROSEGMENT 2>/dev/null

# Flush existing rules
iptables -t filter -F PODMAN_FRONTEND_POLICY
iptables -t filter -F PODMAN_BACKEND_POLICY
iptables -t filter -F PODMAN_MICROSEGMENT

# Frontend network policies (10.89.0.0/24)
# Allow HTTP/HTTPS outbound
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -p tcp --dport 80 -j ACCEPT
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -p tcp --dport 443 -j ACCEPT

# Allow DNS
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -p udp --dport 53 -j ACCEPT
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -p tcp --dport 53 -j ACCEPT

# Allow communication to backend network
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -d 10.90.0.0/24 -p tcp --dport 5432 -j ACCEPT
iptables -t filter -A PODMAN_FRONTEND_POLICY -s 10.89.0.0/24 -d 10.90.0.0/24 -p tcp --dport 6379 -j ACCEPT

# Backend network policies (10.90.0.0/24)
# Block all outbound internet access
iptables -t filter -A PODMAN_BACKEND_POLICY -s 10.90.0.0/24 ! -d 10.0.0.0/8 -j DROP

# Allow established connections back from frontend
iptables -t filter -A PODMAN_BACKEND_POLICY -s 10.90.0.0/24 -d 10.89.0.0/24 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Microsegmentation rules
# Block inter-container communication within same network unless explicitly allowed
iptables -t filter -A PODMAN_MICROSEGMENT -s 10.89.0.0/24 -d 10.89.0.0/24 -j DROP
iptables -t filter -A PODMAN_MICROSEGMENT -s 10.90.0.0/24 -d 10.90.0.0/24 -j DROP

# Apply policies to FORWARD chain
iptables -t filter -I FORWARD -j PODMAN_FRONTEND_POLICY
iptables -t filter -I FORWARD -j PODMAN_BACKEND_POLICY
iptables -t filter -I FORWARD -j PODMAN_MICROSEGMENT

echo "Network policies applied successfully"

Make network policy script executable and persistent

Set proper permissions and create systemd service for automatic policy enforcement.

sudo chmod 755 /usr/local/bin/podman-network-policies.sh
sudo /usr/local/bin/podman-network-policies.sh
[Unit]
Description=Podman Network Security Policies
After=network.target
Before=podman.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/podman-network-policies.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Enable persistent network policies

Enable the systemd service to apply network policies automatically on boot.

sudo systemctl daemon-reload
sudo systemctl enable --now podman-network-policies.service
sudo systemctl status podman-network-policies.service

Create pod with network security policies

Deploy a secured pod using the custom network configuration with traffic filtering.

podman pod create --name secure-web-pod \
  --network secure-frontend \
  --security-opt label=level:s0:c100,c200 \
  --security-opt no-new-privileges \
  --publish 8080:80

Deploy containers with microsegmentation

Run application containers with strict network isolation and minimal privileges.

# Deploy web frontend with network restrictions
podman run -d --name web-frontend \
  --pod secure-web-pod \
  --security-opt label=level:s0:c100,c200 \
  --read-only \
  --tmpfs /tmp:noexec,nosuid,size=100m \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  nginx:alpine

# Create backend pod with isolated network
podman pod create --name secure-db-pod \
  --network secure-backend \
  --security-opt label=level:s0:c300,c400 \
  --security-opt no-new-privileges

# Deploy database with strict isolation
podman run -d --name postgres-db \
  --pod secure-db-pod \
  --security-opt label=level:s0:c300,c400 \
  --read-only \
  --tmpfs /tmp:noexec,nosuid,size=50m \
  --tmpfs /var/run/postgresql:noexec,nosuid,size=10m \
  --cap-drop ALL \
  -e POSTGRES_DB=appdb \
  -e POSTGRES_USER=appuser \
  -e POSTGRES_PASSWORD=secure_password123 \
  postgres:15-alpine

Configure network monitoring and logging

Set up traffic monitoring to detect policy violations and security incidents.

#!/bin/bash

# Enable iptables logging for policy violations
iptables -t filter -A PODMAN_MICROSEGMENT -j LOG --log-prefix "PODMAN_POLICY_VIOLATION: " --log-level 4
iptables -t filter -A PODMAN_BACKEND_POLICY -s 10.90.0.0/24 ! -d 10.0.0.0/8 -j LOG --log-prefix "BACKEND_INTERNET_BLOCK: " --log-level 4

# Monitor network connections
echo "Monitoring Podman network traffic. Check /var/log/syslog for policy violations."

# Display current connections
echo "Current network connections:"
ss -tuln | grep -E ":(80|443|5432|6379|8080)"

# Show iptables packet counters
echo "\nNetwork policy statistics:"
iptables -t filter -L PODMAN_FRONTEND_POLICY -v -n
iptables -t filter -L PODMAN_BACKEND_POLICY -v -n
sudo chmod 755 /usr/local/bin/monitor-podman-traffic.sh

Test network policies and microsegmentation

Verify that traffic filtering and isolation rules are working correctly.

# Test frontend to backend connectivity (should work on allowed ports)
podman exec web-frontend nc -zv 10.90.0.1 5432

# Test blocked inter-container communication within same network
podman run --rm --network secure-frontend alpine nc -zv 10.89.0.2 80

# Test backend internet access (should be blocked)
podman exec postgres-db nc -zv 8.8.8.8 53

# View policy violations in logs
sudo tail -f /var/log/syslog | grep "PODMAN_POLICY"

Verify your setup

Confirm that network policies and microsegmentation are properly configured and enforcing security boundaries.

# Check pod status and network assignments
podman pod ls
podman network ls

# Verify iptables rules are active
sudo iptables -t filter -L PODMAN_FRONTEND_POLICY -v -n
sudo iptables -t filter -L PODMAN_BACKEND_POLICY -v -n
sudo iptables -t filter -L PODMAN_MICROSEGMENT -v -n

# Test network connectivity
podman exec web-frontend wget -q --spider --timeout=5 http://example.com && echo "Frontend internet: OK" || echo "Frontend internet: BLOCKED"
podman exec postgres-db wget -q --spider --timeout=5 http://example.com && echo "Backend internet: ERROR - Should be blocked" || echo "Backend internet: BLOCKED - OK"

# Check container security labels
podman inspect web-frontend --format '{{.ProcessLabel}}'
podman inspect postgres-db --format '{{.ProcessLabel}}'

# Monitor traffic
sudo /usr/local/bin/monitor-podman-traffic.sh

Common issues

SymptomCauseFix
Containers can't reach internet iptables rules blocking all traffic Check sudo iptables -L -v -n and verify ACCEPT rules are before DROP rules
Network policies not applying CNI plugins not properly configured Restart podman service: systemctl --user restart podman
SELinux denials blocking containers Incorrect security labels Check sudo ausearch -m avc and use --security-opt label=disable for testing
DNS resolution failing Firewall blocking DNS traffic Ensure UDP/TCP port 53 is allowed in frontend policy
Inter-pod communication failing Overly restrictive microsegmentation Add specific allow rules before the blanket DROP rule in PODMAN_MICROSEGMENT

Next steps

Running this in production?

Want this handled for you? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. Our managed platform covers monitoring, backups and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

Rotterdam 12:17 · reachable in a message, no ticket form