How does SSH dynamic forward (-D) function under the hood?
I understand that SSH dynamic forward opens a SOCSK4 proxy on the local host, and that each connection to the SOCK4 proxy is forwarded over the SSH tunnel to the remote destination.
Does SSH intercept the connections to the SOCKS4 proxy? I mean, it cannot be a "normal" SOCKS4 proxy, because then it would directly proxy the connections to the remote hosts.
Furthermore, how does SSH handle responses from the remote hosts, i.e., how does it transfer them back over the SSH tunnel to the recipients on the local host?
When the -D flag is given, the SSH client will start a built-in SOCKS4/5 proxy. (note: "SOCKS", not "SOCK").
-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 supported, and ssh will act as a SOCKS server.
When another application wishes to connect to a proxied service, they will establish a connection via this SOCKS server. The SOCKS protocol is a little bit of negotiation that occurs at the beginning of a connection, something like this: (inspired by the wiki page)
ssh -D 1234 user#remote is execute, the SSH client starts a SOCKS proxy server listening on port 1234.
A local application wishes to communicate with a service via the SOCKS proxy, so connects to port 1234.
The SOCKS client asks for a connection to a particular IP address and port - e.g: 66.102.7.99, port 4321.
The SOCKS server, in this case the SSH client, will negotiate to establish this onward connection with it's server (remote, from above). This may fail.
The SOCKS serve will respond to the client with success / failure information.
If successful, all data passed through this socket will now be forwarded appropriately:
From the local application, to the SSH server (remote), and then onto 66.102.7.99.
From 66.102.7.99 to the SSH server (remote), and then onto the local SSH client, and ultimately the local application.
Does SSH intercept the connections to the SOCK4 proxy?
No, the SSH Client is the SOCKS proxy.
I mean, it cannot be a "normal" SOCK4 proxy, because then it would directly proxy the connections to the remote hosts.
I suppose it's not really - the SSH Client and Server act together to achieve the function of a "normal" SOCKS proxy. The high-level result is that the proxy listens on one host, but forwards data from another host, with a magical link in between.
Furthermore, how does SSH handle responses from the remote hosts, i.e., how does it transfer them back over the SSH tunnel to the recipients on the local host?
TCP is a connection-oriented method of communication. That is to say that once a connection is established, data can flow in both directions, and is reliably identified as "related to that connection". With this information it is trivial to associate the data with arbitrary rules such as "forward to the SSH server, who will forward to 66.102.7.99".
Related
I'm wondering actually about the difference between usage of stunnel and ssh port-forwarding (-L and -R flags functionality). I know that both things are difference solutions - SSH tolerates its own keys, stunnel relies on SSL and certificates as a wrapper around TCP/UDP traffic, and so on.
But in the end - let's say you want to connect to some internal service that is inside local (a private network) and still you can do it in two ways:
deploy hardened instance (exposed to public ) that will work for you as a jump host (use SSH port forwarding)
deploy hardened instance (exposed to public) that will host stunnel server and wait for a connection from any stunnel client
I will be grateful for your thoughts about that!
stunnel and ssh are for very different situations.
ssh is a standard tool to connect to a machine and you can use local/remote forwards on top of your tunnels.
stunnel is used in case of firewalls with deep packet inspection, blocking ssh traffic. It can also be used to hide the real used protocol, can be necessary in some countries.
If you are behind a strong firewall, you are simply not able to use ssh, but stunnel still works, because it looks like ordinary https traffic.
But on top of using stunnel, you are normally use other protocols, like ssh.
The stunnel is only used to tunnel the firewall and ssh is used for the real connections then.
There are tools like sshuttle that allow proxying of all traffic through an outbound SSH connection. In our case, we can only SSH into the server, and would like to then proxy all outbound traffic over the inbound SSH connection. Is this possible?
It's possible using ssh port forwarding.In this scenario let's say you can ssh login into b, the command
ssh -L2001:HostD:143 user#HostB will use the ssh tunnel to forward all the outbound traffic from your port 2001 to the port 143 of the HostD , And as you can see ,you can replace HostD by by localhost ,that would made it instead forward the traffic to the port 143 of HostB
Image credit goes to https://www.youtube.com/watch?v=JKrO5WABdoY&t=251s
I'm developing some webhook required direct access public domain to internal machine, thinking use SSH tunnel to forward data, or got alternative solution?
Hosting server & development machine are in same network
192.168.1.2/24 (Hosting server)
2nd machine is virtual mapping using forticlient firewall without static or dynamic IP in visible in hosting server, so is 1 way initial communication right now.
In this case possible to setup SSH tunnel forward all traffic from 192.168.1.2:80 to handle in development machine port 8080?
How to ssh syntax look like?
Thanks.
This could be done by setting up an SSH tunnel to the remote machine:
ssh -L localhost:80:localhost:8080 development-system
Every request to port 80 on the hosting-server is now forwarded to port 8080 on the development-system.
Please note, that the port 80 on the hosting-server could only be used, when you start the SSH command as root. Also note that the port 80 is only accessible from the hosting-server. To access the port 80 on the hosting-server from everywhere use the following:
ssh -L 80:localhost:8080 development-system
Be sure that you want that.
A good introduction to the topic could be found at
https://www.ssh.com/ssh/tunneling/example
https://unix.stackexchange.com/questions/115897/whats-ssh-port-forwarding-and-whats-the-difference-between-ssh-local-and-remot
When I connect to SSH I use port 22 as destination, but when the reply comes back, does it come in on port 22 as well? Or is the client source port randomly assigned as in other TCP communication?
If set up a firewall allowing outbound traffic to port 22 - Do I also need to allow incoming traffic on port 22?
The client SSH port is randomly assigned, as in most client/server systems over TCP/IP.
Were the client port fixed, you would not be able to open multiple SSH connections from the same client IP address, as the connections would be indistinguishable on an IP protocol level. The client port number is the only piece that makes the connection unique (client IP, server IP and server port being the same).
You do not need to allow the incoming traffic though. There is only one outgoing connection in SSH (the responses from the server come over an existing connection).
I am currently trying to work out how to SSH to servers behind firewalls that deny all incoming connections. The servers can SSH out, so I am wondering if there is a way to get the server behind the firewall to create an SSH tunnel to my workstation, then allow my workstation to send commands back to the server through it?
I have looked into tunneling / reverse tunneling, but these appear to be port forwarding solutions, which will not work as the firewall denies all connections on all ports.
Ideally, I would like to do this in Ruby (using the Net::SSH gem), such that instead of opening a new connection like:
Net::SSH.start('host', 'user', :password => "password")
I could somehow bind to an existing tunnel.
Thanks!
This is fairly simple if you have control over the server. I'll give the command-line version, and you can work that into any framework you like:
server$ ssh -R 9091:localhost:22 client.example.egg
client$ ssh -p 9091 localhost
The server establishes a connection to the client first which starts listening on the "R"emote end (i.e. the client) on port 9091 (something I just made up), and forwards those connections to localhost:22, i.e. to the ssh server on itself.
The client then just needs to connect to its own local port 9091, which is transparently forwarded to the server's ssh server.
This will usually wreak havoc to your public key checking (and adherent security!), because the client's ssh client doesn't know that localhost:9091 is the same as server:22. If your client is Putty, then you have an option to provide the "real" server name somewhere so that the credentials can be looked up properly.
Unless you can create (and maintain) a tunnel out from the host you're trying to connect to first (which would allow you then to connect through that tunnel), no you can't. That's the point of a firewall: prevent unauthorised access to a network.
However the firewall shouldn't block a tunnel, although it depends exactly how the tunnel's managed. A port-forwarding tunnel set up using ssh's tunneling features would subvert the firewall. However it may also get you in trouble with the administrator of the remote network.
So ultimately, you'd need to speak to the network administrator to get the firewall rules relaxed in order to do it without needing to tunnel, or at least get authorisation to have a tunnel.