I will go through 2 important topics in ssh which is Port Forwarding and connecting to a server via a Jump Server in the middle.
Port forwarding (port mapping)
It simply means redirects a communication request from one address (IPadd) and port number combination to another IPadd and port number.
The main usage of Port Forwarding is to let 2 systems to communicate (through any kind of services) which are usually located in 2 different networks:
- Private network (protected/masquered network)
- Public network.
It is a general terms and can be used in ssh, Linux, Network and many other applications. No matter where it is used, port forwarding can be categorized in 3 groups which I will go through them in the context of ssh:
a. Local Port forwarding
It is the most common type of port forwarding which let a client to connect to the destination service (port) over ssh (port 22 by default). So we need to configure our ssh connection in a way that let ssh server in the destination to redirect our data to the specified service(port) there for us. In another word, our expection from ssh server is that he/she redirect the traffics that comes from our clinet (local port) to the destination port (service).
So the main target is following:
Make remote resources accessible on your local system as your were in remote location.
Our only advantage is the fact that we use ssh for this purpose since our assumption is that communication over ssh is already possible (firewalls let the ssh traffics to pass through)!
The first and main question that should be asked is following:
The service that we want to access is located at the same server as SSH Server or is located in another server which is accessable from SSH server.
The command is :
ssh -L SourcePort:Something:DestinationPort Username@SSH-server-add
If the service that we want to access is located at the same system as SSH Server, then we must replace Something with localhost (or 127.0.0.1)
ssh -L SourcePort:localhost:DestinationPort Username@SSH-server-add
If the service that we want to access is located at a system other than SSH Server itself, then we must replace Something with the IPadd (name) of that system which is hosting or service:
ssh -L SourcePort:IPadd-Hosting-Service:DestinationPort Username@SSH-server-add
From our clinet side when we want to access the service, will always use following combination:
- our client is system A
- The destination System with SSH server is B
- Another system hosting a service which is accessable from B is C
A -> ip: 192.168.67.X
B -> ip: 40.71.34.X (hosting ssh server)
C -> ip: 40.72.34.Y
ssh connection to server B is possible as can be seen here:
##telnet 40.71.34.X 22
Connected to 40.71.34.X.
Escape character is ‘^]’.
I want to access to the special service called Splunk in System B through Web which is available on port 8000 but somehow blocked and can not be accesed directly, As can be seen here:
##telnet 40.71.34.X 8000
So I want to take advantage of Local Port forwarding for this purpose by using following command which “-L” basically tell ssh that we are doing local port forwarding:
#ssh -L 8888:localhost:8000 email@example.com.X
Port numbers less than 1024 or greater than 49150 are reserved for the system, any other port we can choose for the local system which i have chosen port 8888 here!
so now if I open a browser and do: https://localhost:8888 -> keep it in mind it depends on the target service how we can access it. For example if the service instead of web server (port 8000) was a remote desktop port (port 3389) then in the local system we open the remote desktop app (exp windows) and put: localhost:3389
So to understand even better, we forwarded localhost:8888 to the 40.71.34.X:8000 which is used when we want to have access to a service in the remote system (target system which is ssh server).
So basically the command will tell the ssh-server (system B) that please redirect the traffics to the service which is located on your own system (by using localhost)!
Now imagine the scenario that the service (same as before splunk web server) that we want to access is not located at the same system as ssh-server (system B), but it is located in another system (system C) which is accessable from system B. So now we change our command in a way that tell SSH-Server please redirect the traffics to the System C for Us:
#ssh -L 8888:IPadd-of-SystemC:8000 firstname.lastname@example.org.X
I just emphasis one more time that no matter where the service is located (in B or C), from client side we use always following to access:
b. Remote Port forwarding
The only difference is that we want to let somebody from the target server (server who is ssh server (system B)) to connect a service in our local system (A). So it is just another way around. Let’s stick to the same example with this difference that Splunk (web server) is installed in our local system (system A) and we want to let guys from outside (system B which is ssh-server) to connect to it. We do exactly the same command except changing the flag from -L to -R:
#ssh -R 8888:localhost:8000 email@example.com.X
sow now if somebody sitting at System B and open his browser and put: https://localhost:8888 then he has access to our local splunk server (web server) through ssh even though IP address 192.168.67.X is not routable (private IP add).
so in summary in Local Port forwarding somebody want to access a service at target system (system who is hosting ssh server (B)) which is A -> B and in Remote port forwarding somebody from target system (system who is hosting ssh server (B))
want to have a access to a serivice in System A. Keep it in mind that in both casses we run the mentioned commands from System A since System B is hosting the ssh server.
So in both cases direct access to whatever Services (like Web, Remote Desktop…) from either Server A or from Server B is not possible (for whatever reason) and the only possibility is having SSH from a Client (A) To a Target Server (B which is hosting ssh server). In both cases offcourse SSH command with whatever flags (-L or -R) should be run from Clinet (ssh client)! The Only things that differenciate between Local port forwarding (-L) and Remote Port forwarding (-R) is depend on service which we want to access is located in which one, if located in Target server (ssh server) then simply Local port forwarding otherwise Remote port forwading!
c. Dynamic Port forwarding
It is not much useful.
Connecting with ssh to a server via a Jump server in the middle
So from my computer I need to connect first to mxtcag0110 and from there to lxtcag0120 which I do not have direct access due to Firewall Blockage. There are several ways of doing that which I will go through all of them here:
- My Sytsme is A
- mxtcag0110 is B (Jump Server)
- lxtcag0120 is C
This is the most secure method because encryption is end-to-end. In addition to whatever other encryption goes on, the end points of the chain encrypt and decrypt each other’s traffic. So the traffic passing through the intermediate hosts is always encrypted. But this method cannot be used if the intermediate hosts deny port forwarding.
From command-line it can be used using ssh with -J flag which basically instruct the ssh to connect first to the jump server and then establish a TCP forwarding (forwarding port 22 to the target server) to the Target server from there.
ssh -J mxtcag0110.rouhani.org lxtcag0120.rouhani.org
It is very important to keep in mind that if we want to have passwordless ssh by using keys, we need to copy the Public key of our system (A) to both Jumper server (B) and Target server (C) authorized_keys.
And if the username and port on any system is different we can specify them:
ssh -J username@B:port username@C:port
We can also put the above command in .ssh/config file to make the life easier by only using: -> “ssh lxtcag0120”
IdentityFile ~/.ssh/id_rsa -> refer to Private key
2. Taking advantage of ProxyCommand.
The idea here is to use the stdio forwarding. Previously we needed to install netcat in the Jump server that provides the capability of stdio forwarding for us, but in the new version of openssh we have this capability simply by adding -W flag. Therefore I explain here with the newer version of the Openssh which should be the case by you as well.
ssh -o ProxyCommand=”ssh -W %h:%p mxtcag0110″ lxtcag0120 -> keep it in mind that %h:%p stand for Host:Port. If the private is somewhere other than .ssh/ with different name as standard (id_rsa) we can specify it by using: ssh -i ~/.ssh/nameOfthePrivateKey
We can also can config file here like following:
ProxyCommand ssh -q -W %h:%p mxtcag0110
Important: In both above methods, it is necessary that the public key of the A (our system) being inserted in the Target system (C) authorized_key otherwise it dose not work. So basically here we use only the key that is located in our system (which connection being initiated). Now let’s look at different scenario in 3 method by using ssh agent.
3. Using ssh agent
what is the main usage of the ssh agent: ssh-agent is a background program that handles passwords for SSH private keys (some people protect their private key with password). The ssh-add command prompts the user for a private key password and adds it to the list maintained by ssh-agent. Once you add a password to ssh-agent, you will not be prompted for it when using SSH or scp to connect to hosts with your public key.
To activate the ssh agent:
eval `ssh-agent` -> Make sure you use the backquote (`), located under the tilde (~), rather than the single quote (‘).
and to add the private key password (its the key that our private key with that encrypted, to hide our key)
ssh-add -> it will refer to the .ssh/id_rsa by default otherwise we need to specify the private key location
I put both of them in my home directory .bashrc.
and also to kill the ssh agent when I am logout I put following in .bash_logout:
Now let’s come back to our main topic which is connection from system A to the system C over our jump server whic is system B:
Here if in system B we have different keys (public/private pair) we can pu the public key of the B in authorized_key file of the C!
ssh -A -t mxtcag0110.rouhani.org ssh -A -t lxtcag0120.rouhani.org -> -A flag will activate the ssh agent