{"id":13300106,"url":"https://github.com/eriksjolund/podman-RestrictAddressFamilies","last_synced_at":"2025-03-10T11:32:50.861Z","repository":{"id":45776655,"uuid":"514509576","full_name":"eriksjolund/podman-RestrictAddressFamilies","owner":"eriksjolund","description":"Restrict Podman internet access with the systemd directive RestrictAddressFamilies","archived":false,"fork":false,"pushed_at":"2022-07-30T15:32:24.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-12T08:39:04.351Z","etag":null,"topics":["container","documentation","echo-server","example","podman","security","socket-activation","systemd-service"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eriksjolund.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-16T07:27:47.000Z","updated_at":"2022-07-16T10:40:46.000Z","dependencies_parsed_at":"2022-07-22T06:02:05.768Z","dependency_job_id":null,"html_url":"https://github.com/eriksjolund/podman-RestrictAddressFamilies","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eriksjolund%2Fpodman-RestrictAddressFamilies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eriksjolund%2Fpodman-RestrictAddressFamilies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eriksjolund%2Fpodman-RestrictAddressFamilies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eriksjolund%2Fpodman-RestrictAddressFamilies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eriksjolund","download_url":"https://codeload.github.com/eriksjolund/podman-RestrictAddressFamilies/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242843431,"owners_count":20194372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","documentation","echo-server","example","podman","security","socket-activation","systemd-service"],"created_at":"2024-07-29T17:40:24.156Z","updated_at":"2025-03-10T11:32:50.855Z","avatar_url":"https://github.com/eriksjolund.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"Title: \"_Restricting Podman with the systemd directive RestrictAddressFamilies_\"\n\nSubtitle: \"_Learn how to restrict network access for Podman_\"\n\nThe previous blog post _Use socket activation with Podman to get improved security_ demonstrated that a socket-activated container can use the activated socket to serve the internet even when the network is disabled (i.e., when the option __--network=none__ is given to `podman run`). This blog post takes the approach one step further by also restricting the internet access for Podman and its helper programs (e.g., conmon and the OCI runtime).\n\nRequirements:\n* podman \u003e= 3.4.0\n* runc \u003e= 1.1.3 or crun \u003e= 1.5\n* container-selinux \u003e= 2.183.0 (if using SELinux)\n\nWhen using Podman in a systemd service, the __systemd__ directive\n[__RestrictAddressFamilies__](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=)\ncan be used to restrict Podman's access to sockets. The restriction only concerns the use of the system call __socket()__,\nwhich means that [socket-activated sockets](https://github.com/containers/podman/blob/main/docs/tutorials/socket_activation.md#socket-activation-of-containers)\nare unaffected by the directive.\n\nContainers that only need internet access via socket-activated sockets can still be run by Podman when\nsystemd is configured to restrict Podman's ability to use the system call `socket()` for the AF_INET and AF_INET6\nsocket families. Of course, Podman would then be blocked from pulling down any container images so the container\nimage needs to be present beforehand.\n\n## Example: restrict a socket-activated echo server\n\nLet's see how we could use __RestrictAddressFamilies__ for [socket-activate-echo](https://github.com/eriksjolund/socket-activate-echo/pkgs/container/socket-activate-echo),\na simple echo server container that supports socket activation.\n\nIf the `--pull=never` option is added to `podman run`, the echo server container will continue to work even with\nthe very restricted setting\n\n```\nRestrictAddressFamilies=AF_UNIX AF_NETLINK\n```\n\nAll use of the system call `socket()` is then disallowed except for AF_UNIX sockets and AF_NETLINK\nsockets.\n\nIn case there would be a security vulnerability in Podman, conmon or the OCI runtime, this configuration limits\nthe possibilities an intruder has to launch attacks on other PCs on the network.\n\n### Create the systemd unit files\n\nCreate the container\n\n```\n$ podman pull -q ghcr.io/eriksjolund/socket-activate-echo\n$ podman create --rm --name restricted-echo --network=none --pull=never ghcr.io/eriksjolund/socket-activate-echo\n```\n\nGenerate the systemd service unit\n\n```\n$ mkdir -p ~/.config/systemd/user\n$ podman generate systemd --name --new restricted-echo \u003e ~/.config/systemd/user/restricted-echo.service\n```\n\nAdd the two lines\n```\nRestrictAddressFamilies=AF_UNIX AF_NETLINK\nNoNewPrivileges=yes\n```\nunder the line `[Service]` with the program __sed__ (or just use an editor)\n\n```\n$ sed -i '/\\[Service\\]/a \\\nRestrictAddressFamilies=AF_UNIX AF_NETLINK\\\nNoNewPrivileges=yes' ~/.config/systemd/user/restricted-echo.service\n```\n\nCreate the file _~/.config/systemd/user/restricted-echo.socket_ with\nthe contents\n\n```\n[Unit]\nDescription=restricted echo server\n[Socket]\nListenStream=127.0.0.1:9933\n\n[Install]\nWantedBy=sockets.target\n```\n\nAdd the two lines\n```\nAfter=podman-usernamespace.service\nBindTo=podman-usernamespace.service\n```\nunder the line `[Unit]` with the program __sed__ (or just use an editor)\n\n```\n$ sed -i '/\\[Unit\\]/a \\\nAfter=podman-usernamespace.service\\\nBindTo=podman-usernamespace.service' ~/.config/systemd/user/restricted-echo.service\n```\n\nCreate the file _~/.config/systemd/user/podman-usernamespace.service_ with the contents\n\n```\n[Unit]\nDescription=podman-usernamespace.service\n\n[Service]\nType=oneshot\nRestart=on-failure\nTimeoutStopSec=70\nExecStart=/usr/bin/podman unshare /bin/true\nRemainAfterExit=yes\n```\n\n### Test the echo server\n\nStart the socket unit\n\n```\n$ systemctl --user start restricted-echo.socket\n```\n\nTest the echo server with the program __socat__\n\n```\n$ echo hello | socat - tcp4:127.0.0.1:9933\nhello\n$\n```\n\nThe echo server works as expected! It replies _\"hello\"_ after receiving the text _\"hello\"_.\n\nPodman is blocked from establishing new connections to the internet but everything\nworks fine because Podman is configured to not pull the container image.\n\nNow modify the service unit so that Podman always pulls the container image\n\n```\n$ grep -- --pull= ~/.config/systemd/user/restricted-echo.service\n\t--pull=never ghcr.io/eriksjolund/socket-activate-echo\n$ sed -i s/pull=never/pull=always/ ~/.config/systemd/user/restricted-echo.service\n$ grep -- --pull= ~/.config/systemd/user/restricted-echo.service\n\t--pull=always ghcr.io/eriksjolund/socket-activate-echo\n```\n\nAfter editing the unit file, systemd needs to reload its configuration\n\n```\n$ systemctl --user daemon-reload\n```\n\nStop the service\n\n```\n$ systemctl --user stop restricted-echo.service\n```\n\nTest the echo server with the program __socat__\n\n```\n$ echo hello | socat - tcp4:127.0.0.1:9933\n$\n```\n\nAs expected the service fails because Podman is blocked from establishing a connection to the container registry.\n\n__journalctl__ shows this error message\n\n```\n$ journalctl --user -xe -u restricted-echo.service | grep -A2 \"Trying to pull\" | tail -3\nJul 16 08:26:10 asus podman[28272]: Trying to pull ghcr.io/eriksjolund/socket-activate-echo:latest...\nJul 16 08:26:10 asus podman[28272]: Error: initializing source docker://ghcr.io/eriksjolund/socket-activate-echo:latest: pinging container registry ghcr.io: Get \"https://ghcr.io/v2/\": dial tcp 140.82.121.34:443: socket: address family not supported by protocol\nJul 16 08:26:10 asus systemd[10686]: test.service: Main process exited, code=exited, status=125/n/a\n$\n```\n\nsystemd has marked the service and the socket as being in the __failed__ unit state.\n\n```\n$ systemctl --user is-failed restricted-echo.service\nfailed\n$ systemctl --user is-failed restricted-echo.socket\nfailed\n```\n\nRevert the change and use __--pull=never__ instead\n\n```\n$ sed -i s/pull=always/pull=never/ ~/.config/systemd/user/restricted-echo.service\n$ systemctl --user daemon-reload\n$ systemctl --user reset-failed restricted-echo.service\n$ systemctl --user reset-failed restricted-echo.socket\n$ systemctl --user start restricted-echo.socket\n```\n\n## The need for a separate service for creating the Podman pause process\n\nRootless Podman uses a pause process for keeping the unprivileged\nnamespaces alive. When running a command such as `podman run`,\nPodman will first create the Podman pause process if it's missing. This is the case for\nrootless Podman. When running as root there is no need for a Podman pause process.\n\nLet's consider the situation when systemd starts the systemd user services for\nan unprivileged user directly after a reboot. If lingering has been enabled for the user\n(`loginctl enable-linger \u003cusername\u003e`) and the user is not logged in, the first\nstarted Podman systemd user service will notice that the Podman pause process is missing\nand will thus try to create it. This normally succeeds, but when RestrictAddressFamilies\nis used together with rootless Podman, creating the Podman pause process fails.\n\nThe reason is that using RestrictAddressFamilies in an unprivileged systemd user service\nimplies [`NoNewPrivileges=yes`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=),\nwhich prevents __/usr/bin/newuidmap__ and __/usr/bin/newgidmap__ from running with elevated privileges.\nRootless Podman needs to execute __newuidmap__ and __newgidmap__  when setting up the user namespace. Both executables normally\nrun with elevated privileges as they perform operations not available to an unprivileged user.\nThe extra capabilities are\n\n```\n$ getcap /usr/bin/newuidmap\n/usr/bin/newuidmap cap_setuid=ep\n$ getcap /usr/bin/newgidmap\n/usr/bin/newgidmap cap_setgid=ep\n$\n```\n\nServices using `RestrictAddressFamilies` or `NoNewPrivileges=yes` can\nbe made to work by configuring them to start after a systemd user service that is responsible for\ncreating the Podman pause process.\n\nFor instance, the unit _restricted-echo.service_ depends on _podman-usernamespace.service_:\n\n```           paus-process\n$ grep podman-usernamespace.service ~/.config/systemd/user/restricted-echo.service\nAfter=podman-usernamespace.service\nBindTo=podman-usernamespace.service\n```\n\nThe service _podman-usernamespace.service_ is a `Type=oneshot` service that executes `podman unshare /bin/true`. That\ncommand is normally used for other things, but a side effect of the command is that it creates the Podman pause\nprocess if it's missing.\n\nEnable lingering\n\n```\n$ loginctl enable-linger $USER\n```\n\nEnable the socket unit and reboot\n\n```\n$ systemctl --user -q enable restricted-echo.socket\n$ sudo reboot\n```\n\nAfter the reboot, test the echo server with the program __socat__\n\n```\n$ echo hello | socat - tcp4:127.0.0.1:9933\nhello\n$\n```\n\nThe echo server works as expected even after a reboot!\n\n### Wrap up\n\nThe systemd directive _RestrictAddressFamilies_ provides a way to restrict network access for Podman\nand its helper programs while a socket-activated container still can serve the internet.\n\nThis could, for instance, improve security for a machine that is running a socket-activated web server container.\nIn case Podman, conmon or the OCI runtime would be compromised due to\na security vulnerability, the intruder would gain less privileges and therefore have less\npossibilities to use the compromise as a starting point for attacks on other PCs.\n\nNote, using the systemd directive _RestrictAddressFamilies_ to restrict Podman is an advanced use of Podman.\nThe method is not mentioned in the [Podman documentation](https://docs.podman.io/en/latest/) and might not be officially supported.\n\nThe [socket activation tutorial](https://github.com/containers/podman/blob/main/docs/tutorials/socket_activation.md) provides\nmore information about socket activation support in Podman.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feriksjolund%2Fpodman-RestrictAddressFamilies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feriksjolund%2Fpodman-RestrictAddressFamilies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feriksjolund%2Fpodman-RestrictAddressFamilies/lists"}