human (May 11, 2025, 02:22 PM)
How can I set up a podman network so it only has IPv6 and no IPv4?
assistant (May 11, 2025, 02:23 PM)
To set up a Podman network with only IPv6 and no IPv4, you'll need to create a custom network with specific IPv6 subnet configuration while disabling IPv4.
Here's how you can do it:
- First, create a new network with only IPv6 addressing:
podman network create --ipv6 --subnet fd00::/64 --gateway fd00::1 --disable-dns ipv6only
This command:
- Creates a new network named "ipv6only"
- Enables IPv6 with
--ipv6
flag - Sets an IPv6 subnet (using a ULA range fd00::/64)
- Sets a gateway address
- Disables DNS to prevent potential IPv4 DNS resolution
- Verify the network was created properly:
podman network inspect ipv6only
- When running containers, explicitly connect them to this network:
podman run --network ipv6only --name my-ipv6-container alpine sh
If you need to modify an existing network or troubleshoot any issues, you might need to:
- Remove the network with
podman network rm ipv6only
if you need to recreate it - Check for any host-level IPv4/IPv6 settings that might affect container networking
- Verify that your host system has IPv6 properly configured
Would you like more information about how to validate the IPv6-only setup or how to configure multiple containers on this network?
human (May 11, 2025, 08:43 PM)
IPv4 still works though if I try curl -4 ...
. I want to fully disable any outbound IPv4 traffic
assistant (May 11, 2025, 08:43 PM)
You're right - simply creating an IPv6-only network doesn't completely prevent containers from making IPv4 connections. To fully disable outbound IPv4 traffic, we need to use network isolation and firewall rules. Here's a more comprehensive approach:
- First, create your IPv6-only network:
podman network create --ipv6 --subnet fd00::/64 --gateway fd00::1 --disable-dns ipv6only
- Add firewall rules to block IPv4 traffic using iptables. Create a script to set up these rules:
#!/bin/bash
# Get the network interface for the podman network
NETWORK_IF=$(podman network inspect ipv6only -f '{{.NetworkInterface}}')
# Block all IPv4 traffic from containers on this network
iptables -I FORWARD -i ${NETWORK_IF} -p all -m addrtype --src-type IPV4 -j DROP
iptables -I FORWARD -o ${NETWORK_IF} -p all -m addrtype --dst-type IPV4 -j DROP
# Allow IPv6 traffic
ip6tables -I FORWARD -i ${NETWORK_IF} -j ACCEPT
ip6tables -I FORWARD -o ${NETWORK_IF} -j ACCEPT
echo "IPv4 blocking rules added for interface ${NETWORK_IF}"
- Make the script executable and run it with sudo:
chmod +x block_ipv4.sh
sudo ./block_ipv4.sh
- For stronger isolation, you can use a custom CNI configuration. Create a file called
ipv6only.conflist
:
{
"cniVersion": "0.4.0",
"name": "ipv6only",
"plugins": [
{
"type": "bridge",
"bridge": "cni-ipv6only",
"isGateway": true,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"ranges": [
[
{
"subnet": "fd00::/64",
"gateway": "fd00::1"
}
]
],
"routes": [
{ "dst": "::/0" }
]
}
},
{
"type": "firewall",
"backend": "iptables"
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}
- Add this to your CNI configuration directory (typically
/etc/cni/net.d/
):
sudo cp ipv6only.conflist /etc/cni/net.d/
- Run your container with this network:
podman run --network ipv6only --name ipv6-container alpine sh
- To verify IPv4 is completely blocked, you can test from inside the container:
podman exec -it ipv6-container sh
ping 8.8.8.8 # Should time out
curl -4 ipv4.example.com # Should fail
curl -6 ipv6.example.com # Should work
This approach uses multiple layers of isolation to ensure IPv4 traffic is completely blocked while IPv6 traffic can flow normally. The firewall rules specifically target IPv4 packets and drop them before they can leave your network.
human (May 11, 2025, 08:44 PM)
I'm running this in systemd; could RestrictAddressFamilies
help?
assistant (May 11, 2025, 08:45 PM)
Yes! Using RestrictAddressFamilies
in systemd is an excellent approach for restricting network address families. This will be more effective and cleaner than network-level rules since it restricts capabilities at the process level.
Here's how to implement this in your systemd service:
[Unit]
Description=IPv6-only container service
[Service]
ExecStart=podman run --network ipv6only --name ipv6-container alpine sleep infinity
# Only allow IPv6 (AF_INET6) and local socket families (AF_UNIX, AF_NETLINK)
RestrictAddressFamilies=AF_INET6 AF_UNIX AF_NETLINK
# Prevents the service from accessing IPv4 sockets
RestrictNamespaces=~AF_INET
# Other recommended security settings
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
This configuration:
-
Uses
RestrictAddressFamilies=AF_INET6 AF_UNIX AF_NETLINK
to only allow IPv6 sockets while permitting local UNIX sockets and netlink sockets (needed for network configuration) -
Explicitly restricts (
~
means deny) the IPv4 namespace withRestrictNamespaces=~AF_INET
-
Includes other security hardening options that are good practice for containerized services
To apply this:
-
Save the above configuration to a file, e.g.,
/etc/systemd/system/ipv6-container.service
-
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now ipv6-container.service
This systemd approach is superior to network rules because:
- It prevents the process from even creating IPv4 sockets
- It's enforced by the kernel
- There's no way for the container to bypass this restriction
- It's cleaner than maintaining firewall rules
To verify it's working:
systemctl status ipv6-container.service
podman exec -it ipv6-container sh
# Try ping 8.8.8.8 which should fail immediately rather than time out
# Try curl -4 which should fail with a socket creation error
Would you like more details on any specific part of this systemd configuration?