How to make a tunnel from PuTTY

A simple recipe, by Leon Brooks.

Copyright © 2003 Leon Brooks of CyberKnights Pty Ltd. See the GNU Free Documentation Licence for copying conditions. Semi-apologies for the fonts in the concept diagram, some of them don’t get out often. This is version 0.1 of 22 June 2003.

The Ingredients

Optionally, PuTTY is now available on other platforms. These instructions also work just fine for a Linux-to-Linux PuTTY tunnel.

The Method

1. Start PuTTY. You will see a window somewhat like this one:

2. Run through the settings tweaking stuff for a nice PuTTY experience; start by clicking on the Appearance subcategory and making the cursor a blinking block (to make it easy to find), then choose a font which includes all of the extended VT-100 characters.

2a. I generally use 12-point Terminal:

3. Next (unless your Internet link is too fast, say, 100 megabit, to bother with this), enable compression. Select SSH protocol level 2 as the default in the SSH subcategory for better security:

4. Set up a username unless you want the user to choose one themselves. If your internet access goes out through a masquerade or NAT of some sort and you want to defeat connection timeouts on it, set the keepalives to a reasonable number of seconds (say, 480). PuTTY will send null packets at that interval, each of which resets any timeouts.

5. If the connection is to be totally automated, generate a key (with PuTTYgen, on Windows, or ssh-keygen on Linux/Unix) and tell PuTTY where the private half is:

The public half needs to be sent to the remote gateway and installed there, typically by adding it to the file ~/.ssh/authorized_keys or ~/.ssh/authorized_keys2.

6. This is the core and key to it all, the tunelling setup. In this example, we’re tunneling the telnet port on the local machine, through the gateway to the telnet port on the remote server “telnetservername”. This name is resolved from the remote gateway machine, so it can be a hostname not visible to the user machine.

If the user machine is also behind a firewall and you want other machines to use the same tunnel, switch on “Local ports accept connections”.

Do not enable this if your MS-Windows box is exposed to the Internet (a bad idea in itself) because you will be giving the whole world unencrypted telnet access to the server – at which point those who know about it will be putting together sweepstakes on how many minutes it takes an intruder to discover this.

The source port is the port on the user machine (see first diagram if confused) to which you will address connections that you intend to have tunnelled. The destination defines a host and a port to which the remote gateway’s sshd will connect incoming traffic from the user machine. When you click on Add, the results are displayed like this:

If you’d established a remote tunnel (instead of a local one), the list would say Rport   localhostname:port and cause the gateway’s sshd (if permitted) to be listening on the source port for connections; these would be forwarded out to the destination from the user machine (exactly the reverse of the tunnel we just set up).

7. Flip back to the Session subcategory, identify the gateway host’s Internet interface address (you will need a dynamic DNS service to do this if the gateway’s Internet connection does not have a fixed IP address), mention that it’s SSH, name your session (in this case “Tunnel to my telnet server” and save it:

8. Whenever you need the tunnel to appear, you can start PuTTY and double-click that session.

9. To automate this one step further, define an icon (“short cut”) with a program string like this – putty -load "Tunnel to my telnet server" – set to run minimised. If you’re using an encryption-key login (described in step 5 above), all you do to establish the tunnel is double-click on your new icon.

Specific Applications

Telnet applications are obvious. The final SCO server that I supported (never again: SCO Unix is horrid, I can’t imagine why SCO’d suspect anybody of copying from it) had a core application that required a telnet connection. PuTTY made doing this securely as a road warrior trivial.

Terminal Services have a particular problem if the user machine is running MS-Windows XP. XP “knows” that connecting to localhost will produce an infinite loop, and in a fit of over-protectiveness refuses to allow you to connect the TS client to any port on

XP also has a useful bug: any traffic which makes it to the loopback device is treated as locally addressed regardless of the destination IP value (ie, it will even answer queries outside the range to if they’re routed to it), so all you need do is point the TS client at an address that will normally be routed to the loopback interface, such as

Brief Rant on XP and networking

Now... while I’m eternally grateful for a way to work around the safeties, does it make sense to answer all traffic to loopback but only deny TS the ability to connect to just one (out of about 16 million) of the addresses normally routed there?

It gets worse. A friend’s XP-laden laptop one day decided (presumably for the friend’s own good) that the loopback interface needed an automatically assigned address. Due to a surprising dearth of DHCP servers listening on the loopback interface, it eventually settled on 169.254.blah.blah and many applications expecting to see and use had nervous breakdowns.

No worries, we thought, let’s set it back to Set it to a fixed address, happy as Larry (whoever he is), but No, sorry, that’s a reserved address. Thwack. This is the loopback interface, silly machine! So we used the above tactic and set it to, where it resides to this day [weeeeell... until about October 2003, anyway. XP gutted itself and the owner wiped and reinstalled his boot disk, “fixing” the problem en passant].

Remote X, remote email

A Remote tunnel can be used for forwarding an X session to a local X server, permitting you to run Linux/Unix applications on the remote server but display them on your MS-Windows workstation. To do this, tell your local X server to listen for traffic from the user machine (workstation), and set the server’s DISPLAY environment variable to point to port 6000 on the gateway. If the gateway already has an X display running, use DISPLAY=gateway:1 and port 6001 at the remote end, but still forward that to port 6000 on the local end. PuTTY has a convenience option for X forwarding.

Email can be POPped from a server (possibly including the gateway) normally only accessible from within the gateway’s LAN by forwarding a connection to port 110 on the mail server.

What won’t work through a PuTTY tunnel

In some of the above cases, this is generally not regarded as a bad thing.

What to do if a PuTTY tunnel isn’t good enough

Try a PPP-over-SSH tunnel, which takes all protocols (VPN) and is not much more difficult to set up.

Consider using IPSec, which is faster-responding (it’s based on UDP not TCP) but can be a little trickier to set up, and does require super-user access on the gateway server.

Because of the way IPSec works, you will need to define four tunnels (LAN-LAN, gateway-gateway, gateway-LAN and LAN-gateway) if you want completely secure traffic from end to end including the gateways themselves. On Linux you can use iproute2 to make one LAN-LAN tunnel work for all of the above cases by ordering all traffic intended for the other end of the VPN to originate from the LAN interface.

OpenVPN is a fairly powerful networking tool. That makes it a tad more complicated to set up than PPP-over, but it will work in a variety of ports, protocols and methods, making it a better long-term solution.

Another reasonable compromise solution is the Zebedee tool.


The following people (s/ splat /@/ for real email) have provided helpful comments on this text. I have not taken all of those comments on board, so if there are still gross errors, omissions or misrepresentations, don’t blame them. (-:

Thanks also to Kimberly Shelt <kim splat> for nagging me into applying those fixes and tidying this up a bit.