There is some development I need to do on some remote box. Fortunately, I have shell access, but I need to go through a gateway that has AllowTcpForwarding set to false.

I took a peak at the docs and it says:

AllowTcpForwarding Specifies whether TCP forwarding is permitted. The default is ''yes''. Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders.

How would I go about installing (or building) my own forwarder? My goal here is to setup a remote interpreter using Pycharm via SSH and binding it to some local port, that data fed through ssh, that through the gateway, and then to the development box where the code is actually run. I imagine I could somehow utilize nc or some other unix utility that'll help get the job done.

I know I can ssh to my remote box by doing:

ssh -t user1@gateway ssh user2@devbox

But obviously this option isn't available in pycharm. I'll have to be able to open some local port such that

ssh -p 12345 localhost
(or variant)

will connect me to user2@devbox. This will allow me to configure the remote interpreter to use port 12345 on localhost to connect to the remote box.

  • The gateway has AllowTcpForwarding set to false but does the remote box? if it does not why not forward to it? Oh I understand now... Since you can access the router you can probably port forward on the router. Why not do that?
    – jdwolf
    Nov 24, 2017 at 2:41

5 Answers 5


As long as one can execute socat locally and on gateway (or even just bash and cat on gateway, see last example!) and is allowed to not use a pty to be 8bits clean, it's possible to establish a tunnel through ssh. Here are 4 examples, improving upon the previous:

Basic example working once

(having it fork would require one ssh connection per tunnel, not good). Having to escape the : for socat to accept the exec command:


$ socat tcp-listen:12345,reuseaddr exec:'ssh user1@gateway exec socat - tcp\:devbox\:22',nofork


$ ssh -p 12345 user2@localhost


user1@gateway's password:


user2@localhost's password: 

Reversing first and second addresses makes the socket immediately available

socat has to stay in charge, so no nofork:


    $ socat exec:'ssh user1@gateway exec socat - tcp\:devbox\:22' tcp-listen:12345,reuseaddr
    user1@gateway's password:


    $ ssh -p 12345 user2@localhost
    user2@localhost's password:

Using a ControlMaster ssh

allows to fork while using only a single ssh connection to the gateway, thus giving a behaviour similar to the usual port forwarding:


    $ ssh -N -o ControlMaster=yes -o ControlPath=~/mysshcontrolsocket user1@gateway
    user1@gateway's password:


    $ socat tcp-listen:12345,reuseaddr,fork exec:'ssh -o ControlPath=~/mysshcontrolsocket user1@gateway exec socat - tcp\:devbox\:22'


    $ ssh -p 12345 user2@localhost
    user2@localhost's password:

Having only bash and cat available on gateway

By using bash's built-in tcp redirection, and two half-duplex cat commands (for a full-duplex result) one doesn't even need a remote socat or netcat. Handling of multiple layers of nested and escaped quotes was a bit awkward and can perhaps be done better, or simplified by the use of a remote bash script. Care has to be taken to have the forked cat for output only:

term1 (no change):

$ ssh -N -o ControlMaster=yes -o ControlPath=~/mysshcontrolsocket user1@gateway
user1@gateway's password:


$ socat tcp-listen:12345,reuseaddr,fork 'exec:ssh -T -o ControlPath=~/mysshcontrolsocket user1@gateway '\''exec bash -c \'\''"exec 2>/dev/null 8<>/dev/tcp/devbox/22; cat <&8 & cat >&8"\'\'\'


$ ssh -p 12345 user2@localhost
user2@localhost's password:

Replace ProxyJump with Bash

The idea above is good! Here is my generic ssh_config version when ProxyJump is not working because AllowTcpForwarding set to no and my default shell is BASH:

ProxyCommand=ssh -T user1@gateway "exec 3<>/dev/tcp/%h/%p 2<&- ; cat <&3 & cat >&3 ; kill $!"
  • -T Disable pseudo-terminal allocation
  • exec No new process (bash) will be created
  • 3<> is simply redirection to an available file descriptor
  • /dev/tcp/... will ask bash to open the corresponding TCP socket.
  • %h and %p will be evaluated by your OpenSSH client as devbox and 22
  • 2<&- will close the STDERR (you could also redirect it to /dev/null)
  • cat <&3 & will read the selected file descriptor 3 in the background
  • cat >&3 will write our file descriptor in the foreground
  • kill $! will kill the "reading" cat <&3 command running in the background when you close/broke the connection. Otherwise it would keep running.

It could replace ProxyJump for me in situations when it was disabled on the jump server but I really didn't wanted to forward my private key there or enter any passwords without an extra level of encryption. Using others SSH_AUTH_SOCK as root or record terminal sessions completely with keystrokes are both real things.

But please, always make sure you don't violate any policies that apply to you!


Oh no, we almost forgot netcat!

If there is netcat (any version) on your jump host, you can use it instead of ProxyJump in your config generally like:

ProxyCommand=ssh -T user1@gateway "exec nc %h %p"

Or from the command line:

ssh user2@devbox -oPorxyCommand="ssh -T user1@gateway 'exec nc devbox 22'"

SSH tunneling can do done both ways. SSH into the router. SSH from the router into the devbox. Then run SSH from the devbox to make an outbound connection to your computer running an SSH server with port forwarding enabled while setting up a remote port forward back to the devbox. At that point you can close the other ssh connection.


I would just set up anouther sshd to run on a different port.
Edit the settings so tcpforwarding is allowed.

cp /etc/ssh/sshd{,-second}_config 

Edit sshd-second_config

Port 22220
cp /usr/lib/systemd/system/sshd.service  /etc/systemd/system/sshd-second.service

Alter /etc/systemd/system/sshd-second.service in the following way:

Description=OpenSSH server second instance daemon
ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd-second_config $OPTIONS

The ExecStart line may differ, depending on the release.

systemctl daemon-reload
systemctl enable sshd-second.service --now

More information can be found here:

Now you should be able to forward whatever you want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.