Tunelling RDP over SSH through NAT on both sides

Written by Matej Drolc

A short recipe on how to establish a rdp session from machine A to machine B even though both machines sit behind a NAT (and/or firewall)…


This is another note-to-myself post because digging the same recipe out of scripts in my filesystem is a very tedious task.

The problem: we have two machines, both behind NAT/firewall and we would like to RDP from one to the other over the internet even though we do not have the option of opening/forwarding any ports on the public interface and through the firewall. We use ssh tunnels through a third machine. This works for any TCP connection really, it is not limited to RDP.

Alt text


  • A ssh server running a ssh server (in my case a cheap OpenWrt router)
  • plink.exe on both host and client rdp machines


Let’s say the ssh server’s address is ssh.example.com.

  1. On rdp host machine run:

    plink.exe -N -C -v -R 6000:localhost:3389 sshuser@ssh.example.com -pw password
  2. On rdp client machine run:

    plink.exe -N -C -v -L 5555:localhost:6000 sshuser@ssh.example.com -pw password
  3. When both tunnels are established, on rdp client machine open remote desktop client and connect to:


Addendum: Setting up a ssh-only user without shell on OpenWrt

When connecting with a no shell user, -N switch is compulsory.

# (14.07-rc3, r42056)
echo 'sshuser:x:1000:1000:User for ssh tunnels:/var:/bin/false' >>/etc/passwd
echo 'sshuser:x:15020:0:99999:7:::' >>/etc/shadow
echo 'sshuser:x:1000:' >>/etc/group
passwd sshuser
# Turns out dropbear will reject (message is authpriv.warn dropbear[2378]: User 'sshuser' has invalid shell, rejected) authentication without /bin/false in /etc/shells even though it makes no sense.
echo '/bin/false' >> /etc/shells


ssh tunnel, ssh reverse tunnel, remote desktop, rdp defeating NAT, defeating firewall, tcp over ssh rdp over ssh