Sometimes you need to connect to the host from a Podman container running on it. How would you do that?

In the past I was able to get this working by connecting to the gateway IP of the container. For example, I have a web server running on the host listening on port 8080.

➜ nc -vz localhost 8080
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:8080.
Ncat: 0 bytes sent, 0 bytes received in 0.02 seconds.

Next, create a new container to run curl for testing.

➜ podman run -it --rm alpine sh
/ #
/ # ip route
default via 192.168.1.1 dev br0  metric 425
192.168.1.0/24 dev br0 scope link  metric 425

Let’s try to curl the default gateway:

/ # curl -v http://192.168.1.1:8080
sh: curl: not found

Fine! I will install curl and try again:

/ # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/10) Installing ca-certificates (20240705-r0)
(2/10) Installing brotli-libs (1.1.0-r2)
(3/10) Installing c-ares (1.33.1-r0)
(4/10) Installing libunistring (1.2-r0)
(5/10) Installing libidn2 (2.3.7-r0)
(6/10) Installing nghttp2-libs (1.62.1-r0)
(7/10) Installing libpsl (0.21.5-r1)
(8/10) Installing zstd-libs (1.5.6-r0)
(9/10) Installing libcurl (8.11.0-r2)
(10/10) Installing curl (8.11.0-r2)
Executing busybox-1.36.1-r29.trigger
Executing ca-certificates-20240705-r0.trigger
OK: 13 MiB in 24 packages

/ # curl -v http://192.168.1.1:8080
*   Trying 192.168.1.1:8080...
* connect to 192.168.1.1 port 8080 from 192.168.1.114 port 39314 failed: Operation timed out
* Failed to connect to 192.168.1.1 port 8080 after 134524 ms: Could not connect to server
* closing connection #0
curl: (28) Failed to connect to 192.168.1.1 port 8080 after 134524 ms: Could not connect to server

So why this no longer worked? According to [1],[2] and [3], starting from Podman 5.0, the default rootless networking tool has been switched from slirp4netns to pasta. To connect to host services, we can use host.containers.internal.

/ # grep host.containers.internal /etc/hosts
169.254.1.2     host.containers.internal host.docker.internal

/ # curl -v https://host.containers.internal:8080
* Host host.containers.internal:8080 was resolved.
* IPv6: (none)
* IPv4: 169.254.1.2
*   Trying 169.254.1.2:8080...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS alert, internal error (592):
* TLS connect error: error:0A000438:SSL routines::tlsv1 alert internal error
* closing connection #0
curl: (35) TLS connect error: error:0A000438:SSL routines::tlsv1 alert internal error

/ # nc -vz host.containers.internal 8080
host.containers.internal (169.254.1.2:8080) open

The above output showed that the container could access the web server running on port 8080 on the host.

References: