Tunneling may be quite similar in concept to port forwarding. The difference is this: With port forwarding, one device receives the traffic and then that same device forwards the traffic to the destination port. Tunneling is simply an elaboration of this concept where the result is a slightly more complicated scenario: one piece of software (running on one device) receives the traffic and then it sends it to a tunnel, expecting that another piece of software (running on the same device or, probably more commonly, on a different device) will then process the traffic, quite likely by forwarding the traffic to a destination port. Key reasons to perform this are features provided by the tunnel implementation, such as authentication requirements to use the tunnel (such as authentication requirements needed to create the tunnel in order for the tunnel to then be usable), encryption, and impacting routing (such as allowing traffic through a firewall which allows the tunnelled traffic but which might not allow other types of traffic such as less secured E-Mail traffic).

The idea of a tunnel is that traffic entering one end of the tunnel has a clear exit point: the other end of the tunnel. Traffic in the tunnel doesn't need to worry much about the complexities of the world outside of the tunnel. Using the analogy of a car: a tunnel may go through a mountain. Then, there is no need to deal with the complexities that a mountain may often pose, such as the need to drive in a less striaght line. Similarly, most network traffic may be stopped by a firewall, but traffic in a tunnel may pass on through.

When the tunnel is providing confidentiality, the analogy becomes even more useful. Traffic that goes through a tunnel's entrance should leave the tunnel by using the expected, desired exit (which is the other end of the tunnel), without simply veering off in an unexpected different direction and then exiting somewhere unanticipated. The protection (the “walls”) of the tunnel help to enforce this design of traffic flow. Just as cars don't typically just turn perpendicular while in a striaght tunnel, network traffic shouldn't be leaving via unanticipated exits. This helps with concerns about data that needs to be confidential.

[#sshptfwd]: Creating a port forwarding rule using SSH
Software requirements

SSH tunneling may often be supported by SSH programs. (For example, both the OpenSSH suite and by the popular PuTTY (version for Microsoft Windows) GUI client do implement this. A more thorough list may be found in the section about SSH programs (and perhaps more specifically the list of remote access: SSH terminal clients.)

SSH TCP port forwarding must be implemented by both the SSH client software and the SSH server software. Note that, to get tunneling working, support for the tunneling needs to be enabled. This is mentioned because SSH server software can easily be configured to have this support disabled, then the SSH client is not going to successfully make a tunnel. (For example, if OpenSSH is using keys for authorization, and the “Authorized Keys File” prohibits that type of forwarding when that key is being used for authentication, the SSH server software may have such support disabled for that connection. This decision may be made before the SSH connection is fully established.)

There are also some specialized applications that may be used.

Solutions for Microsoft Windows

Check out PuTTY (version for Microsoft Windows).

Solution(s) for Mac OS X
Apple.com's page about SSHTunnel, a freeware application which lists “Mac OS X 10.5 or later” on the “System Requirements” section of that page, although there is a “Universal” binary icon which indicates compatbility with a Pre-OSX version of Mac OS.

This section helps to explain how SSH tunneling works. It's quite a bit of material to cover, but is recommended for those who don't really know how tunneling works. It may also cover some required steps, and why those steps are needed. The material should help one to make the decisions made to help create a tunnel that will accomplish the desired goal.

It is possible that those who have prior experience creating tunnels may be able to get by without going through all of this introductory material, as such an experienced person may know how the traffic needs to be handled. Guides, to implementing these steps in various software, follow this design section.

The role of each piece of SSH software

This detailed description is meant to help explain the process well enough that one can then determine which piece of SSH software will be performing each of these steps in the process.

TCP port forwarding options for setting up forwarding are “set up”/configured by the client software. What the SSH client software does is review the TCP port forwarding configuration. If a “local” forwarded TCP port is specified, then the SSH client begins to listen on the specified TCP port (on one or more addresses, as configured). If a “remote” forwarded TCP port is specified, then the SSH client will request that the SSH server listens on a specified TCP port. (Naturally, the SSH server may refuse to cooperate with the forwarding request, based on factors such as the configuration that the SSH server is set up to use, and/or if the requested port is unavailable because it is already in use.) In either case, the SSH software's TCP port that is listening for such traffic is referred to as a “forwarded” TCP port.

Any traffic received on the specified forwarded TCP port will then get encrypted (as part of the standard SSH process) and sent from one piece of SSH software (e.g. the SSH client) over the encrypted SSH connection. The other SSH software (e.g. the SSH server) that receives the encrypted forwarded traffic (traffic which was just sent over the SSH connection) then decrypts the encrypted forwarded traffic. Then, this decrypted traffic is processed by the SSH software that received the traffic on the SSH connection. The common method of processing the traffic, at this point of the whole operation, is to forward that decrypted traffic again: the SSH software that received the traffic from the SSH tunnel will send the traffic to an IP (IPv6 or IPv4) address and TCP port number that was specified by the port forwarding configuration settings. (The SSH client processed these settings, and informed the SSH server of those settings as needed, at the start of the process before the forwarded TCP port was created.)


This is meant for forwarding TCP ports. UDP may be accomplishable by using a combination of UDP and TCP and some fancy piping in combination with some other software, as shown by UDP tunneling through SSH (with netcat and mkfifo).

This is often a simple way to add encryption to traffic, even if the traffic is created (sent) and used (received) by software which does not support the method of encryption being used. Also, the authentication used by the SSH software is used, in addition to whatever authentication is supported by the software that is having traffic be tunneled. This is good if the software does not support a strong method of encryption on its own. For example, protocols such as VNC or POP3 which are often implemented with no authentication or authentication which is often plaintext and/or weak (e.g.. due to a short number of significant bits, and perhaps even a restricted character set) may have encryption effectively added by sending all traffic, including the initial authentication, through an SSH tunnel which encrypts all of the traffic.

Since end users can easily add authentication and encryption, developers of many other types of software have found there is very little need whatsoever, quite possibly even no need at all, for the developer to independantly spend time adding features for authentication and/or encryption because tunneling allows end users to handle this simply. (This not only saves software developers time in the short term, but in the long term they don't need to update support for newer methods of encryption: The end user who creates the tunnel can do that.)

[#tunlreqm]: Requirements
Software requirements

(This almost seems redundant with the “software requirements” of the port forwarding section, although it is a bit different.)

SSH technology needs to be implemented:

SSH server (configuration) requirements
Basically, what this means is that an SSH server needs to be actively running, and the SSH server needs to have an authentication method (so users, or key files (or both users and key files) need to be set up).
SSH client requirements

SSH client software supporting tunneling needs to be obtained. For most popular modern operating systems, all of this is taken care of when installing the operating system. The key exception is Microsoft Windows. Microsoft Windows does not come bundled with the necessary software. Many users of Microsoft Windows operating systems like to use an SSH client called PuTTY, although other solutions such as OpenSSH software may also be used.

[#sshpfwch]: Decisions/Choices needed to have the required knowledge
Overview/summary of required knowledge

Know the location of the port that will be forwarding the traffic, the address and port combination which does the initial forwarding, and then the destination address and port used by the SSH software which is on the other end of the SSH tunnel from the TCP port that does the initial traffic forwarding. That might not be abundantly clear before setting up an initial tunnel, so an example, as follows, shows a demonstration of each of these decisions.

[#vncshfwd]: Example scenarios (with VNC)

Various examples may be used: As another example, PuTTY documentation on port forwarding discusses a POP3 connection.

However, the examples referred to by this guide involves one machine having a VNC client and an SSH client. (Having both the VNC client and the SSH client on the same machine may simplify initial testing.) There is a (different) machine which is running an SSH server. There is a machine which is running a VNC server. In these examples, the SSH client can communicate SSH traffic to the SSH server. In both examples, the VNC server is listening for traffic on a certain address range which the SSH server can directly communicate with, so the SSH server can communicate with both the SSH client and the VNC server. However, the VNC client cannot communicate directly to the VNC server. The two separate examples, about to be described separately, simply involve different reasons why the VNC software cannot communicate directly even though the SSH software can.

In the first example, the VNC server is on the same machine as the SSH server, and the VNC server is only listening for traffic on the machine's IPv4 loopback address of “”. Standard IPv4 routing rules allows the SSH server to communicate with the VNC server, but other machines are prevented from communicating directly with the VNC server.

A visual diagram of the first scenario may show two processes on each of two computers

VNC Client < - > SSH Client
< - >
SSH Server < - > VNC Server

In another example, the VNC server may be listening for traffic only on certain address ranges, likely within the ranges of privately-assinged IP addresses. A standard firewall configuration typically controls how traffic from the privately-assigned IP address ranges can travel, and the firewall's rules may be preventing the VNC client from communicating directly with the VNC server. However, an exception to the firewall may allow the SSH server to be reachable by an SSH client.

A visual diagram of the second example scenario shows three computers, plus a firewall (which could be a fourth computer)

VNC Client < - > SSH Client
< - >
Firewall blocking all but SSH
< - >
SSH Server
< - >
VNC Server

[#lcadptfd]: The location of the forwarding address and port

First consider what SSH software is going to be handling the traffic initially (before the traffic is encrypted and then sent over the active SSH connection). Using either of the VNC examples just described, the VNC traffic is going to be TCP traffic initiated by the VNC client. This VNC client will be communicating with a TCP port that is being listened to by the SSH client, and then that SSH software will send the traffic over an encrypted tunnel. In this example, the SSH software that is handling the traffic before it goes through the tunnel is the SSH client (and not the SSH server, which will handle the traffic after it goes through the tunnel). The SSH client handles the traffic before the SSH server.

If the SSH client is the SSH software that is listening to the forwarded TCP port, then that forwarded TCP port is a “local” TCP port from the SSH client software's perspective. PuTTY documentation on SSH port forwarding, which is documentation for an SSH client, refers to this as a “local-to-remote” port. If the SSH server is the SSH software that is listening to the forwarded TCP port, then that forwarded TCP port is a “remote” TCP port from the SSH client software's perspective. (Although this could be thought of as a local TCP port for the SSH server software, it is the SSH client software's perspective that is generally paid attention to when SSH port forwarding is being configured). PuTTY documentation on SSH port forwarding, which is documentation for an SSH client, refers to this as a “remote-to-local” port.

In this example involving a typical setup involving VNC, from the vantage of the SSH client, this is a port which is local to the SSH client.

[#fwdadrpt]: Deciding on the forwarding address and port

Determine the IP address and TCP port number which should be listened to by the SSH softare which will be listening to the forwarded port. (Actually, the address is often omitted from the command line, in which case the default may be affected by another configuration option, such as “GatewayPorts” in the configuration file (ssh_config) for OpenSSH usually found in “/etc/ssh/.”.) However, the TCP port number (or UDP port number?) should be specified.

PuTTY documentation about port forwarding references some options, “Local ports accept connections from other hosts” (available with SSH1 and SSH2) and “Remote ports do the same” (which is not available with SSH1) which are likely related, at least in concept, to determining what address is being listened on.

[#dstrefwd]: Decide on the destination address and port used by the SSH software on the opposite end of the tunnel

After the initial traffic goes through the tunnel, the other SSH software will receive the tunnelled traffic and will need to know how to process the traffic. In all likelihood, the sensible action for the SSH software receiving the tunneled traffic is going to be to forward the traffic to an address (and for TCP (and UDP?) traffic, to forward the traffic to a specific desired TCP port number (or UDP port number as appropriate?). When determining this address, realize that the address may be specified relative to this SSH software which is receiving the tunnelled traffic. This means that any address on a loopback interface (such as IPv6 ::1 or IPv4, or any other private address, which is understood by and reachable by the SSH software that receives the initial tunnelled traffic, may be referenced.

To clarify that last statement using the example, if a VNC client sends traffic to a port that an SSH client listens to, and the SSH client sends that traffic through the tunnel to an SSH server, the SSH server may then send the traffic to a VNC server which is listening on a loopback or other private address which the SSH server can communicate with. This works even if routing rules, such as firewalling, would prevent the machine with the SSH client from reaching the same location as the SSH server when both machines use the specified loopback or other private address.

To further clarify this text, the term “address” may be a host name which resolves to a valid network address that is made up of numbers and punctuation marks. (The address itself does not need to be a valid network address made up of numbers and punctuation marks.)

Setting this up does present a great potential for some confusion. When setting up a local forwarding port from an SSH client, using a loopback address on the server may work but it can be a bit confusing. First, the loopback address is typed into the client even though it is referencing the server. Finally, after accepting that the loopback address is referencing the remote system when the port forwarding is configured, the configured port forwarding is generally tested and that may often involve typing a loopback address again, except this time the exact same loopback address is no longer referencing the same remote system that it was just referencing.

[#sshtnlpb]: Loopback with tunneling

This will not be doing what some people expect.

Some people may be misled by their knowledge that ::1 address is IPv6 loopback address, and address is the IPv4 loopback address. Essentially, these addresses are similar to the English word “myself”. The term may refer to Alice if Alice is the person who says the word, and yet the term may refer to Bob if Bob is the person who says the word.

Similarly, when people look at the machine with the SSH client, and they see a loopback address, they might naturally think that the IP address refers to the computer running the SSH client. That is commonly how loopback addresses work, but that might not be how it works in this case.

Consider these example screens. Assume that both of these screenshots came from the same computer.

SSH tunneling options:

VNC connection options:

Now, in these examples, which computer does the IPv4 address refer to?

The answer, which many people will not be expecting, is this: they refer to different computers. The exact same address, IPv4, ends up referring to different computers.

That's right. The IPv4 address seen in a couple of spots in that first screen refers to one computer, and the IPv4 in the other screen refers to another computer, even though these are both screens from windows running on the same computer.

Another example could be provided... PuTTY documentation shows an example command line of “plink -L”. That can probably be changed slightly to use an identical address multiple times in the exact some command line parameter, and to refer to different computers in each usage.)

Read on for the explanation.

Instead, the network address (e.g. 127.0.0.l) gets transmitted from the SSH client to the SSH server. Then, the SSH server looks at that address, and figures out where the traffic will go. So, this is like Alice telling Bob to read a message. Bob reads the message out loud, and said, “I am happy.” Consider things from the perspective of another person, Charlie. Now, let's assume that Charlie is blind, and doesn't see what Alice wrote a message and gave it to Bob. When Bob reads the message out loud and Charlie hears Bob speaking, who does Charlie think the word “I” refers to? Even though Alice wrote the word “I”, Charlie thinks the word “I” refers to Bob, because Bob is the one who was reading the message.

Even though the loopback address might be seen on the SSH client's screen, it actually will be referring to the SSH server when the address actually gets used to determine where the traffic goes. When the SSH server determines where the traffic gets forwarded to, the loopback address will be referring to the SSH server.

(At least, that is how it works for a Local port. For a ”Remote” port, perhaps the same concept gets applied in the opposite direction.)

Now, just to complicate things a bit further (I'm sorry... it's important to do so), the loopback address doesn't *always* refer to the remote system. When the computer running an SSH client and another piece of software, such as a VNC client, then the loopback address will refer to different systems depending on when it gets used. If the loopback address is used by the other software (e.g., the VNC client), the network address will be referring to the VNC client, which is the same computer as the computer running the SSH client.

This seems to have potential for some confusion. In some cases, the loopback address refers to the computer that runs the SSH client, and in other cases the loopback address refers to the computer that runs the SSH server. It's like if Alice sends herself a message (a “reminder note”) that says, “I should laugh today”. Also, Alice sends Bob a note, that says, “I should feel grateful today”. When Alice reads the first note in front of Charlie, the message will appear to refer to Alice. When Bob reads the second note in front of Charlie, the message will appear to refer to Bob. In both cases, Alice wrote the note, but the information in the note will refer to a different person based on who is reading the note. Just like the word “I” refers to different people at different times even though Alice wrote both notes, the loopback address may refer to different computers at different times, even though the loopback address might be typed and visually seen on just one computer. Keeping track of which computer it refers to may require some cautious effort.

Using OpenSSH client for port forwarding
OpenSSH info
Quick historical overview as noted by Wikipedia's article on SSH: section on OpenSSH and OSSH: In 1999, Björn Grönvall made an now-discontinued open source program called OSSH developed from version 1.2.12 of the latest open source version of the original SSH program. (That original SSH software was made by developers who went on to create Software from ssh.com/Tectia.com.) Later the OpenBSD developers forked OSSH to create OpenSSH.
[#oshpfwdc]: OpenSSH command line options for port forwarding
Basic information about the command line parameters

In addition to OpenSSH, this information should also be mostly applicable to using the PuTTY command line options for SSH port forwarding. This section specifically covers the command line options for port forwarding. (Other command line options, such as optionally referencing the port number and/or credential information, may also be used separately.)

First, before trying to craft the command line parameters to use, have ready the knowledge that is determined from making the SSH port forwarding decisions/choices. For example, knowing the location of the initial port (to determine whether it is local or remote to the SSH client) will be needed.

The port forwarding configuration is basically specified by two command line parameters. For standard TCP ports over IP (either IPv6 or IPv4), the first parameter is either a “-L ”, which indicates that the forwarded TCP port is local to the SSH client. Alternatively, the first command line parameter may be a “-R ”, which indicates that the forwarded TCP port is “remote” to the SSH client (and so it is a TCP port on the machine running the SSH server. Alternatively, the first command line parameter may be a “-D ” which will use SOCKS.

The second parameter related to the TCP port forwarding configuration, which must come right after the parameter that specifies which machine has the forwarded port, consists of multiple “fields” (a.k.a. “parts”). If using IPv6, the character that separates the parts/fields may be a colon or a slash. Using a slash may be easier because otherwise the IPv6 address(es) must be separated by square brackets, and those square brackets may commonly need to be escaped with many command line shells. If using IPv4, the parts are separated by a colon. There is a certain number of required fields.

The bind_address field
If using the “-D ” parameter
Further details may be added here at a later time.
If using the “-L ” or “-R ” parameter

With OpenSSH (although this does not seem to be true with using the PuTTY command line options for SSH port forwarding), there is one optional field that may exist before the TCP port number which is the first required field. This optional field is an address that may be either an IP (either IPv6 or IPv4) address, or the word “localhost”, or an asterisk. (It does not appear that a host name is commonly supported for this field.) In each case, if this parameter is used then it needs to be followed by an appropriate field separator. If this is an IPv6 address and if colons are used to separate the fields of the second parameter, then the IPv6 address needs to be surrounded with square brackets (which are escaped as needed). The supported special values are the word “localhost”, which limits connections to localhost, or an asterisk, which does not restrict connections based on which address they are coming from. If this parameter is omitted, the default value used depends on the value of the “GatewayPorts” setting in the configuration file /etc/ssh/ssh_config for OpenSSH. (This is a client option, and should not be confused with the “GatewayPorts” server-side setting in the sshd_config configuration file usually found in “/etc/ssh/.”)

(The section on PuTTY command line parameters for SSH port forwarding provides further details of doing something like this with PuTTY.)

If using the “-R ” or parameter

If using the “-R ” parameter and also trying to use this field, PuTTY documentation on SSH port forwarding may be noteworthy where it seems to be describing similar functionality. Specifically what is referred to here is where PuTTY's documentation does say that not all all servers support the “remote-to-local” version of this, and the documentation indicates that SSH version 1 does not support this. A specific example provided by PuTTY's documentation is that OpenSSH 3.0 does not support this. OpenSSH's latest version number is notably higher than 3.0 (at least version 5.5 has been released), although even then the setting is generally disabled (by default) unless overridden with the “GatewayPorts” setting in the configuration file (sshd_config) for OpenSSH usually found in “/etc/ssh/.” (This is a server option, and should not be confused with the “GatewayPorts” client-side setting in the ssh_config configuration file usually found in “/etc/ssh/.”)

Required fields for the second port forwarding parameter

The first required parameter is the port number of a TCP port to be listening to. If the “-R ” parameter is being used, this may be set to zero in order to accept a TCP port number that the SSH server dynamically chooses.

If using the “-L ” or “-R ” parameter, a destination “host” and TCP port must be specified. The host may be a name which is resolved to an address with (DNS) name resolution. Alternatively, the host may be an IPv6 or IPv4 address. If the host is an IPv6 address and if the field separator being used is a colon, then the specified IPv6 address will need to be surrounded with square brackets (which may need to be escaped).

[#putyfwdp]: Using PuTTY

If the client program is going to be run from Windows, we may create a forwarded port using PuTTY. The client machine will need to run a copy of PuTTY (version for Microsoft Windows), which is not part of the operating system. (So, the software will need to be obtained, unless it has been added alredy.) Find the latest version, and run PuTTY.

[#putyfwdc]: Using the PuTTY command line options for port forwarding over SSH

PuTTY documentation on command line options provides some more details. Specifically, PuTTY documentation on port forwarding command line options says about the “-L ” option and the “-R ” option: “The command-line options work just like the ones in Unix SSH programs.” (There same text does not indicate that there is any support for a “-D ” option.) Therefore, a more full discussion about the OpenSSH command line options for port forwarding provides more details about PuTTY, although there are some differences to note here, such as not supporting the “-D ” option, nor supporting a parameter before the first port number (as discussed below).

The examples shown in PuTTY's documentation on PuTTY documentation on port forwarding command line options setting up TCP port forwarding with command lines do not show an address before the first port number: they simply show a single address and two port numbers. Since PuTTY's graphical interface has a thinner field for entering the port number of the forwarded TCP port, it seems likely that PuTTY does not support the initial “bind_address” host name which is optional for OpenSSH. (This is still true as of version 0.60 of PuTTY.) As for something equivilent to the “localhost” or “*” values that OpenSSH supports, such functionality does seem to be supported by PuTTY even if that isn't done with OpenSSH-like parameter. PuTTY documentation on SSH port forwarding does refer to similar capabilitites with Tunnel options (specified through the GUI). These options are called “Local ports accept connections from other hosts” for local-to-remote (a.k.a. “local”) forwarded TCP ports, and “Remote ports do the same” for “remote-to-local” (a.k.a. “remote”) forwarded TCP ports. Note that this documentation does say that not all all servers support the “remote-to-local” version of this, and the documentation indicates that SSH version 1 does not support this.

[#putyfwdg]: Configuring with the PuTTY GUI interface
Reconfiguation screen

For short term use (like a single connection), a common method is to simply ignore the need for the forwarded port configuration and simply start by first creating the SSH connection. Then, later, worry about creating the SSH tunnel after the SSH connection is established and the user has sufficiently authenticated. Also, it is recommended to perform authentication, so that the server doesn't perform a “timeout” of a brief period of time where authentication is permitted.

The standard keyboard interface for windowed programs, of pressing Alt-Space, is actually not supported by the default options, which can be adjusted from the “Window” category of options, and specifically from the “Behaviour” screen of options. If people don't have a rodent available, they might want to specify all of the tunnel options before the SSH connection is made.

To reconfigure an existing option, adjusting the tunneling options of an existing SSH connection, first connect. After the SSH connection is already made, use the program's “system menu” by using a rodent to click on the icon in the upper-left corner. After choosing the “system menu”, choose “Change Settings...”. (Then, more details are provided after the brief section describing the alternate “Longer term configuration” process.)

Longer term configuration

For long term use, one may wish to not connect until after performing a series of steps:

  • configuring the SSH tunnel using the directions that follow
  • filling out other basic connectivity information
    • the Host Name
    • the connection type (which overwrites the TCP Port number when changed)
    • configuring the TCP Port number
  • then using the Save button to save the settings
  • and then ensuring that the program is looking at the right “Saved Sessions”
  • and using the Load button to make sure the settings were successfully saved, making sure the tunnel settings are still around,
  • and then finally opening the connection using the saved settings.

Connecting should be fairly straightforward. Simply make sure that the host name, protocol, and port number are set to the desired values, and then open the connection. Note that even though the default tab order of the fields has port customizable before the protocol, changing the protocol will (with at least some versions of PuTTY, if not all of them) change the port number to the default value (even if the port number was already customized). So, if changing the protocol, be careful to re-customize the port number of needed.


Once the session is created, then set up the tunnel if that hasn't already been done. Click on the system menu and choose “Change Settings...” (One may not use Alt+Space to access the system menu by default, although that may be changed in the Behavior section.)


Within the Configuration section, choose the “Connection” area and then the “SSH” category, and then the “Tunnels” configuration screen.

At this point, the screen may look more similar to the following options.


(However, the text fields will start out blank. Also, the title bar will say “PuTTY Reconfiguration” instead of “PuTTY Configuration” if this screen was reached by choosing to alter the properties related to an existing, active connection. e.g., puttun4.png, puttun5.png, and later in the process, puttuna.png and puttunb.png.)

Here are some details about the first fields to fill out:

Source port

For the “Source port”, specify a TCP port number. For example, we will use 5920. (This port number does not need to match the remote end, but it does make sense for it to.)


For the Destination, we will use an address and port combination which is recognized by the SSH server. (This port number does not need to match the remote end, but it does make sense for it to.) For example, This should be an address and TCP port number based on what the software on the SSH server is going to be listening to, so the refers to that address as viewed by the SSH server. (The example port numbers here are meant, as examples, to be used as VNC desktops.)

Note: The loopback addresses might not operate the way that is expected by a person who understands the typical behavior of a loopback address. Namely, the same address typed onto the same computer, visible on the same computer, may refer to different computers. See: SSH tunneling details: loopback address for details, including an explanation.

Presumably, if the address is a literal IPv6 address, then it should be surrounded by square brackets. PuTTY bug tracker: IPv6 addresses notes some issues with PuTTY 0.60 that got fixed in March 2015's release r10122 (PuTTY version 0.64), so users of older versions of PuTTY may wish to update. Some experimentation with 0.62 indicated more success with using a DNS name, while trying to use literal IPv6 addresses resulted in the local port not listening (as proven by “netstat -na”).


Use the “Local” radio button if the source port is on the “Local” computer. This is a common approach when performing typical port forwarding of an outgoing connection, like when using a VNC client that will be communicating with a remote resource. Since that is the scenario that this guide is discussing as an example, choosing “Local” is the correct option. Fortunately, that is the default, so no changes need to be made.

Further Understanding the Type option

(This section doesn't provide further details about actions needed to make the VNC client support the SSH tunnel, although it describes what is happening. These details may be useful for people who are trying to use SSH tunneling in other ways.)

For the sake of thoroughness, though, it is useful to understand what the option does. (This explanation explains a current understanding of these behaviors.) Using “Local” will cause the SSH client to take traffic from the local TCP port, and send that information into the SSH tunnel. Traffic will start to get encrypted based on traffic that gets sent to the TCP port on the local system, and so the SSH client will listen to traffic on the local system. The initial TCP traffic will enter the tunnel based on communication that starts with a TCP port that is listening for TCP traffic on the “Local” system.

In contrast, the ”Remote” option is used when traffic is initiated from the incoming port. With this method, the SSH server starts listening for traffic. This may be ideal if trying to use a server that is receiving traffic. With this setup, the SSH server is the computer that has a TCP port listening for TCP traffic. The traffic will start by establishing a TCP connection with the remote system's TCP port before the traffic is encrypted as part of the process of being sent through the SSH tunnel.

If all of those dry details feel a bit too complex, then the following guidelines will probably work in most cases. For connections where the communication starts by having the machine with the SSH client make an outgoing connections, use “Local”. For connections where where the communication starts by having the machine with the SSH server receive an incoming connections, choose “Remote”.

Address family

If “Auto” (which is the default option) is the selected address family, then PuTTY may create rules for both IPv6 IPv4. PuTTY might even try to do this intelligently, and start to listen on IPv4 (which is the IPv4 loopback address) if the address typed was [::1] (which is recongized as being an IPv6 loopback address). If this sort of behavior is undesirable, then make sure to not choose “Auto”, and specify IPv6 if only IPv6 addresses are dseired.

Then do not click Apply yet, but instead click the “Add” button, which will add the information to the section showing “Forwarded ports:”.

Before choosing the the “Apply” button, the information should show up in the “Forwarded ports:” text box which is above the words “Add new forwarded port:” (and is right below the “Remove” button), as shown in the above screen. The way to get information into that upper text box is to use the “Add” button. (This will likely move information from the lower text boxes into the upper text box. Having the information be seen in both the lower text boxes and the upper text box was just a contrived example, so don't worry if you don't see the information in both places at once.)

The port forwarding rule should show up in the “Forwarded ports” text box with the letter L before the TCP port number. If the address is specific to one address family (either IPv6 or IPv4), then there may be a number before that letter L. Here are some examples:

TCP Net address Description
L5920 [::1]:5930 Listens to IPv6 address ::1 on TCP port 5920. Since ::1 is recognized as the IPv6 loopback address, and the address family was set to Auto, this also listens to the IPv4 loopback address (which is on TCP port 5920. In either case, traffic goes to the SSH server's loopback address on TCP port 5930.
L5940 Listens to IPv4 address on TCP port 5940. Since IPv4 address IPv4 is recognized as the IPv4 loopback address, and the address family was set to Auto, this also listens to the IPv6 loopback address (which is ::1) on TCP port 5940. In either case, traffic goes to the SSH server's loopback address on TCP port 5950.
6L5960 [::1]:5970 Listens to IPv6 address ::1 on TCP port 5960. Traffic goes to the SSH server's IPv6 loopback address on TCP port 5970. Since this is an IPv6-only TCP port forwarding, IPv4 traffic will be ignored by this particular TCP port forwarding.
4L5980 Listens to IPv4 address on TCP port 5980. Traffic goes to the SSH server's IPv4 loopback address on TCP port 5990. Since this is an IPv4-only TCP port forwarding, IPv6 traffic will be ignored by this particular TCP port forwarding.

For instance, if both IPv4 and IPv6 is being supported, the output might look something like “L5920” followed by an address (like, perhaps, “”).

Seeing the letter (e.g.“L” for local ports) in that list of “Forwarded ports” is critically important for the SSH forwarding to effectively work. If the letter (e.g. “L”) isn't showing up before the TCP port number (e.g. “L5920”), then the forwarding will not work. The letter will be automatically inserted before the TCP port number when the “Add” button is used. Simlpy having the port number filled out in the lower “Source port” text field is insufficient. The “Apply button (for using the “PuTTY Reconfiguration” screen for existing connections) or the “Open” button (if using the “PuTTY Configuration” screen) will cause the PuTTY software program to leave this screen of options. (This is also true of the “Cancel” button.) These buttons effectively erase whatever is in the lower text boxes, and any text that is still in those boxes will have no ongoing effect. So, the configuration details must make it to the upper text box if those details will effectively change the behavior of SSH tunnels.

Then, after it shows up correctly in the “Forwarded ports:” section, choose the “Apply” button. This will make the “PuTTY Configuration” or “PuTTY Reconfiguration” screen disappear: That window needs to close because until that is done, PuTTY may not allow forwarded traffic over the connection.

Checking port forwarding

To check on the settings by using the GUI, go to the system menu. (That cannot be reached by pressing Alt-Space unless configured to allow that, so using a rodent may be needed. However, after choosing “Change Settings...”, this behavior may be changed in the Window category, specifically in the Behavior subcategory where there is a checkbox for “System menu appears on ALT-Space” checkbox to change that behavior.) In the “Connection” category, there is a subcategory called “SSH” and that has an option called “Tunnels”.

This will show a window titled “PuTTY Reconfiguration”. (graphic may not yet be made?)


After the desired forwarding settings correctly show up in the “Forwarded ports:” section, choose the “Apply” button. This will make the “PuTTY Configuration” or “PuTTY Reconfiguration” screen disappear: That window needs to close because until that is done, PuTTY may not allow forwarded traffic over the connection.

See the section about testing port forwarding.

Easily Using the same settings later

If the port forwarding settings are working and they are desirable for in the future, save the settings into “a stored session” from the Session screen. To do this, either use an existing connection and choose “New Session...” from the system menu, or start a new copy of PuTTY. Either task brings up a menu called “PuTTY Configuration”. The key thing about this window (on any of its screens) is to be careful not to select the “Open” button before desired. Change the port forwarding settings; also change any other options if desired, such as making PuTTY act like a normal Windows program by enabling the system menu when Alt-Space is pressed. (This is in the Category called Window, and the subcategory called Behavior.) After all of the settings are perfect, choose the “Session” Category. Create a name for the saved/stored session, and click the “Save” button. After it is successfully saved, these settings may be used later by choosing the session and clicking “Load”. (That may also be done immediately, having no real effect if they were just saved.) This session may also be specified by using PuTTY's “-load” command line parameter: e.g.

PuTTY.exe -load "Custom Session"

With the GUI showing, fill in the settings related to the destination (“Host Name (or IP address)”, “Connection type”, and “Port”) if they weren't part fo the saved settings, and then, finally, click Open.

[#sshcmtct]: About using software from ssh.com/tectia.com

Quick historical overview as noted by Wikipedia's article on SSH: section on OpenSSH and OSSH: Finnish designer Tatu Ylönen released a freeware SSH client in 1995 and later made commercial SSH software.

SSH software
PuTTY guide on agent forwarding says, “Note that at present, agent forwarding in SSH2 is only available when your SSH server is OpenSSH. The ssh.com server uses a different agent protocol which they have not published. If you would like PuTTY to be able to support agent forwarding to an ssh.com server, please write to ssh.com and explain to them that they are hurting themselves and their users by keeping their protocol secret.”
https://downloads.ssh.com/ has identified itself as the “Tectia Customer Download Center”. Tectia.com has said “SSH is now Tectia!”
[#tstptfwd]: Testing port forwarding

Send traffic to the required port. As an example, let's take a look at using TightVNC for Windows on a system that uses the PuTTY SSH client, and the Qemu virtual machine which uses the SSH server.

Like a lot of VNC software, the TCP port that will be used by Qemu's VNC server is determined by adding 5900 to whatever VNC desktop number is used. For example, if Qemu is using VNC desktop number of 30, then the TCP port number used by the VNC server may be 5930 (and possibly 5830 as well).

When using the client VNC software, a sensible address to specifiy is a loopback address: for IPv4 (and ::1 if IPv6 is supported and being used). (However, at least some versions of the VNC server built into Qemu might not support IPv6. (This should be investigated/tested.)) Then such software often expects a VNC desktop number. For instance, the “VNC server” to specify in the client may be “”. In this case, the :70 is not referencing a TCP port number (which would be the meaning generally implied from IPv4 notation when there is a colon and a number following an IP address), but rather in this it is referring to a VNC desktop number (which is implied by notation fairly common to VNC software). The loopback address being used ( for IPv4) refers to an address relative to the SSH client.

If following the PuTTY configuration guide above, the traffic is then sent through the SSH tunnel and the SSH server on the other side will then send the traffic to relative to the SSH server. This means that although both systems are using the same IP address, the destination address refers to a different system depending on which system is sending the traffic.

Realize that once the VNC session is successfully created, the VNC session requires that the port forwarding remains active and so the PuTTY window may need to remain open. (One probably may log out of the SSH command line session if desired, at which point the SSH client software needs to remain will remain open until the connection using the forwarded port becomes a closed connection. Some software, such as the PuTTY SSH client for Windows, may do that. However, this isn't recommended when learning an unfamiliar process, just in case the specific SSH software being used changes its behavior with a different version. Also, PuTTY may pause on forwarding any traffic if this SSH client software has a configuration screen showing in the foreground.)


This may be used in multiple ways. One way is to make it like a VPN, but restricting what resources get accessed. This may make things more secure than a VPN that allows an outsider to access all machines, but more convenient than trying to create a unique SSH tunnel for each port that needs to be accessed.