How can I access a Docker service bound to localhost through an SSH tunnel?

0
10
Asked By MellowPine47 On

I'm running Uptime Kuma in Docker with the host port bound only to localhost: 127.0.0.1:3005 -> 3001/tcp. I want the service to remain inaccessible from the public network and only reach it through an SSH tunnel. I tried using `ssh -L 3005:127.0.0.1:3005 user@server -p -vv`, but a default-drop iptables policy prevented the connection. Loopback traffic was allowed, but I wasn't sure whether the issue involved the OUTPUT, FORWARD, or Docker NAT chains. Since Docker translates the connection from the host port 3005 to the container port 3001, what firewall rule or tunnel configuration is appropriate?

3 Answers

Answered By QuietOrbit6 On

With a default-drop firewall, remember that Docker performs NAT before the packet reaches the container. The traffic may therefore appear on the Docker bridge interface as a connection to the container’s port 3001 rather than the published host port 3005. In this setup, allowing the relevant outbound traffic on `docker0`, such as `sudo iptables -A OUTPUT -o docker0 -p tcp --dport 3001 -j ACCEPT`, can permit the forwarded connection. Make sure established and related return traffic is allowed too, and place custom rules carefully alongside Docker’s own chains.

MellowPine47 -

The key was the NAT translation. Matching port 3005 in OUTPUT did not work after Docker rewrote the destination, but allowing TCP traffic headed through `docker0` to port 3001 fixed it.

Answered By CopperLark82 On

Because the port is published on the host as `127.0.0.1:3005`, the SSH tunnel should target the host-side port: `ssh -L 3005:127.0.0.1:3005 user@server -p `. You then open `http://127.0.0.1:3005` on your local machine. You normally should not target the container port 3001 from the SSH client, since that port exists inside Docker’s network namespace.

MellowPine47 -

That matches the intended setup: Docker listens only on the server’s loopback address, while SSH forwards my local port to that host-side listener.

Answered By SilverMaple31 On

Binding the published port to `127.0.0.1` is the right way to keep the service off the public interface. You can verify the behavior with `ss -lntp` and Docker’s port listing, then test the tunnel from the client. Firewall rules should account for the actual post-NAT interface and port, while connection tracking should handle the return packets.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.