Thursday, October 16, 2008

Open SSH: Port Forwarding

prerequisite concepts: prelude, basic configuration

Port forwarding is a versatile feature which informs several popular concepts, including X Forwarding and tunneling which are briefly explained below; more advanced port magic will be addressed elsewhere.

X Forwarding
At the end of the previous installment of this series is an example SSH client configuration file, usually located at ~/.ssh/conf; a more complete description of the global declarations shown was deferred until this section, where they are more relevant.

# global declarationsThis line is a comment and while it is ignored by SSH, it is very helpful to use comments and white space to maximize readability, and maintainability.
Host *As previously stated, Host declarations define the context of all following lines until the next Host declaration. Because the '*' will match any host, these declarations will be applied to all hosts-- unless overridden by a later declaration or a command line option.
ForwardAgent yesThe key agent allows a user to store one or more authenticated keys in memory, enabling dual key authentication; this is sometimes (incorrectly) referred to as passwordless authentication, but a password check is still required to load the key into the agent. Agent forwarding allows one not only to rely on keys instead of passwords to connect to a remote server, but to use the same agent to connect to a third host and so on as long as the keys are recognized and ForwardAgent is enabled on each host.
ForwardX11 yesThis declaration turns on port forwarding for X Windows authentication; briefly put, this allows an X session (i.e. the active GUI environment) on a Linux workstation to interact with X Windows on a remote host using an encrypted tunnel. The practical benefit is that programs on a remote host needing or allowing a graphic interface may use one provided by the client. The canonical example is that I run xclock on a remote server and the clock appears on my screen.

X forwarding may be fun, but port forwarding has many more practical uses. Suppose you need to connect to a web application on, perhaps FreePBX to configure a Linux PBX, but you cannot connect directly because port 80 is blocked-- there are a few reasons why this might occur but port forwarding can work equally well in all likely scenarios.

If you log in to the remote host with ssh -L 8080:localhost:80 SSH will create an encrypted tunnel between port 8080 on your workstation and port 80 on the server, ergo you can now get to the web app by pointing your browser to http://localhost:8080. Because the connection is tunneled through SSH, it works even if port 80 is restricted by IP address or an interceding router, firewall, or cable modem; because of SSH's strong encryption, this technique also provides a secure connection to servers which do not offer SSL.

Many users mistakenly assume that the localhost in the preceding command is the one referenced in the subsequent URL; in fact, the given example is connecting (client) localhost:8080 to (server) localhost:80 and could be entered as:
ssh -L joe.telco@pb»
The notable concept is that the latter host:port pair is evaluated on the remote host, meaning it's a bit like saying:
"connect my self:8080 to your self:80"

ssh -L localhost:8080:localhost:80 joe.telco@pbx.exam»
ssh -L joe.telco@pbx.ex»
ssh -L *:8080:localhost:80
The explicit use of localhost in the first of the preceding examples restricts listening port 8080 for local use only; in contrast, the second example binds the port to a specific network interface, and other users on the network may use the forwarded port at the specified IP address; the last example avails the port on all interfaces. If the bind address is not specified, the port is bound to the loopback address unless GatewayPorts is enabled, wherein the wildcard address issued.

The config file is the place for complexity, and the following example specifies that connections to should be made as user joe.telco, and forwarded HTTP and MySQL connections should be available on all interfaces using the specified ports.
Host pbx
GatewayPorts yes
User joe.telco
LocalForward 8080 localhost:80
LocalForward 3306 localhost:3306
As previously illustrated, this simplifies the command line syntax such that in lieu of:
ssh -g -u joe.telco -L 8080:localhost:80 \
-L 3306:localhost:3306
one need only enter:
ssh pbxMuch more information on the port forwarding capabilities of SSH are available in the man pages as well as previously cited sources; however, the examples here lay the foundation for the next installment of this OpenSSH series: Proxy Connections.