Docker SSH forwarding - bind: Address not available - docker

I have a Docker container, which I would like to be able to interact with a database trough a SSH tunnel.
My Docker image is built on an alpine image and in the Dockerfile I have installed openssh-client and exposed port 27017
When I spin up my Docker image and try to forward the ports with:
ssh -i /.ssh/ssh_key user#remote_ip -L 27017:localhost:27017 -Nf
I get an error:
bind: Address not available
It is not a problem to ssh into the remote server, but I am not able to forward the ports.
Thanks

I manage to create a ssh tunnel from a docker-compose using this entrypoint:
ssh -4 -i /.ssh/ssh_key -NL *:27017:0.0.0.0:27017 user#remote_ip
and then i was able to use the ssh tunnel from an another container by using the network created with the docker-compose
docker run --network=tunnel_default image nmap -p 27027 service_name
tunnel_default is the name of the network
image is a docker image where nmap is installed (it allows you to check open ports)
service_name is the name i gave to the service inside the docker-compose

You can get a "bind address not available" if you don't specify which interface you want to use. By default it will use all of them, including IPV6. In my case, it was binding on IPV4 but the "address not available" was actually for IPV6 e.g. bind [::1]:2001: Address not available. If you use the -4 option, this will use IPV4 only and if you were getting an IPV6 type error, then this will resolve that for you, which it was for me on Arch Linux.
-4 Forces ssh to use IPv4 addresses only.
-D [bind_address:]port
Specifies a local “dynamic” application-level port forwarding. This works by allocating a
socket to listen to port on the local side, optionally bound to the specified
bind_address. Whenever a connection is made to this port, the connection is forwarded
over the secure channel, and the application protocol is then used to determine where to
connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are sup‐
ported, and ssh will act as a SOCKS server. Only root can forward privileged ports.
Dynamic port forwardings can also be specified in the configuration file.
IPv6 addresses can be specified by enclosing the address in square brackets. Only the
superuser can forward privileged ports. By default, the local port is bound in accordance
with the GatewayPorts setting. However, an explicit bind_address may be used to bind the
connection to a specific address. The bind_address of “localhost” indicates that the lis‐
tening port be bound for local use only, while an empty address or ‘*’ indicates that the
port should be available from all interfaces.

Related

Dockerized Telnet over SSH Reverse Tunnel

I know that the title might be confusing so let me explain.
The is my current situation:
Server A - 127.0.0.1
Server B - 1.2.3.4.5
Server B opens a reverse tunnel to Server A. This gives me a random port on Server A to communicate with the Server B. Let's assume the port is 1337.
As I mentioned to access Server B I am sending packets to 127.0.0.1:1337.
Our client needs a Telnet connection. Since Telnet is insecure but a requirement, we decided to use telnet OVER the ssh reverse tunnel.
Moreover, we created an alpine container with busybox inside of it to eliminate any access to the host. And here is our problem.
The tunnel is created on the host, yet the telnet client is inside a docker container. Those are two separate systems.
I can share my host network with the docker with -network=host but it eliminates the encapsulation idea of the docker container.
Also binding the docker to host like that -p 127.0.0.1:1337:1337 screams that the port is already in use and it can't bind to that (duh ssh is using it)
Mapping ports from host to the container are also not working since the telnet client isn't forwarding the traffic to a specific port so we can't just "sniff" it out.
Does anyone have an idea how to overcome this?
I thought about sharing my host network and trying to configure iptables rules to limit the docker functionality over the network but my iptables skills aren't really great.
The port forward does not work, because that is basically the wrong direction. -p 127.0.0.1:1337:1337 means "take everything thats coming in on that host-port, and forward it into the container". But you want to connect from the container to that port on the host.
Thats basically three steps:
The following steps require atleast Docker v20.04
On the host: Bind your tunnel to the docker0 interface on the host (might require that you figure out the ip of that interface first). In other words, referring to your example, ensure that the local side of the tunnel does not end at 127.0.0.1:1337 but <ip of host interface docker0>:1337
On the host: Add --add-host host.docker.internal:host-gateway to your docker run command
Inside your container: telnet to host.docker.internal (magic DNS name) on the port you bound in step 2 (i.e. 1337)

docker: Connection refused on bound port from other device in the same NAT

I'm trying to set up an HTTP server in a Docker container on port 8888 on a Raspbian host. I use -p 8888:8888 to bind the port to all interfaces. This allows me to connect to it with localhost:8888 without issue. However, when I connect to the bound port on the host from another device in the same NAT using its IP address (192.168.1.xxx), my connection is refused.
I'm using the bridge networking mode for this. I tried the "host" mode and that didn't work at all.
You need to link the containers with the (deprecated) —-link command documented here. Otherwise they run in isolated networks. You can also use the more modern and supported way and create a network that each shares; both are described in the linked page.

Docker container can't connect to ip host

I have deployed a netflix hystrix dashboard with turbine on a docker container, I can access to http://ip:8081/hystrix but when I try to monitor the stream of turbine it freeze and doesn't return any information, I test using curl inside the container and execute curl http://localhost:8081/turbine.stream and curl http://containername:8081/turbine.stream, with those two command works perfectly but when I use the host ip as curl http://hostip:8081/turbine.stream the curl throws Failed to connect to hostip port 8081: No route to host, I can't found a solution, can someone help me with this issue?,
Thanks in advance.
In order to access the container through Host IP you need to ensure the following:
Port mapping is allowing through the Host/Public IP itself not only localhost.
You can check this by executing docker ps on the docker host and look for the PORTS column the default should be as the following 0.0.0.0:8081->8081/tcp which means it can accept connection from any interface either public, private or localhost.
The firewall is not blocking the connection on port 8081.
By default the firewall of the host should be managed by Docker daemon itself so the port 8081 will be allowed in the firewall but you might have a different case either Docker is not managing the firewall of the host or there is an extra layer that prevents the connection

Can't set udp source port in docker

I am using Docker 18.06.1-ce-win73 on windows 10 and trying to perform the following udp operation:
Docker port 10001 --------------> host port 10620
It is mandatory for the application running on the host to receive packets from the port 10001.
Inside the docker container, using python I bind on the IP ('0.0.0.0', 10001) and use the socket to send my packets to the host IP on port 16020.
I have also started the container with the argument -p 10001:10001/udp.
Unfortunately, when receiving the packet on the Host application, the origin port is not 10001 but a random one.
Is it possible to force docker to use a specific source port when using UDP from inside the container ?
You can control the container source port, but when you communicate outside of docker, even to your host, the request will go through a NAT layer that will change the source to be the host with a random port. You may be able to modify the iptables rules to work around this NAT effect.
However, if you really need control of the source port like this, you may be better off switching to host networking (--net=host or network_mode: host depending on how you run your containers), or change to a networking driver like macvlan that exposes the container directly without going through the NAT rules.

Docker network settings and iptables NAT

I have a server running inside a docker container, listening on UDP port, let's say 1234. This port is exposed in Dockerfile.
Also, I have an external server helping with NAT traversal, basically, just sending addresses of the registered server and a client to each other, and allowing to connect to a server by the name it sent during registration.
Now, if I run my container with -P option, my port is getting published as some random port, e.g. 32774. But on the helper server I see my server connected to it from port 1234, and so it can't send a correct address to a client. And a client can't connect at all.
If I run my container explicitly publishing my server on the same port with -p 1234:1234/udp, a client can connect to my server directly. But now on the helper server I see my server connected to it from port 1236, and again it can't send the correct port to a client.
How can this be resolved? My aim is to require as little addition configuration as possible from people who will use my docker image.
EDIT: So, I need either to know my external port number from inside the container to send it to the discovery server, which, as I understand, not possible at the moment, right? Or I need to make outgoing connections from the container and my port to use the same external port as configured for incoming connections - is that possible?
The ports are managed by docker and the docker network adaptor. When using solely -P then the port is exposed docker internally and accessible through docker linking. When using "1234:1234" then the port is mapped on a host port and directly available for a client and also available for linking.
Start the helper server with a link option "--link server container/name". The helper server will connect to host "server" on port 1234. The correct ip address will be managed by docker.
Enable docker to change your iptables configuration, which is docker default. Afterwards the client should be able to connect to both instances. Note that the helper server should provide the host ip and not the docker container ip address. The docker container ip address does only work inside the host where the docker network adapter is running.

Resources