I love explaining this kind of thing through visualization. :-)
Think of your SSH connections as tubes. Big tubes. Normally, you'll reach through these tubes to run a shell on a remote computer. The shell runs in a virtual terminal (tty). But you know this part already.
Think of your tunnel as a tube within a tube. You still have the big SSH connection, but the -L or -R option lets you set up a smaller tube inside it.
Every tube has a beginning and an end. The big tube, your SSH connection, started with your SSH client and ends up at the SSH server you connected to. All the smaller tubes have the same endpoints, except that the role of "start" or "end" is determined by whether you used -L
or -R
(respectively) to create them.
(You haven't said, but I'm going to assume that the "remote" machine you've mentioned, the one behind the firewall, can access the Internet using Network Address Translation (NAT). This is kind of important, so please correct this assumption if it is false.)
When you create a tunnel, you specify an address and port on which it will answer, and an address and port to which it will be delivered. The -L
option tells the tunnel to answer on the local side of the tunnel (the host running your client). The -R
option tells the tunnel to answer on the remote side (the SSH server).
So... To be able to SSH from the Internet into a machine behind a firewall, you need the machine in question to open an SSH connection to the outside world and include a -R
tunnel whose "entry" point is the "remote" side of his connection.
Of the two models shown above, you want the one on the right.
From the firewalled host:
ssh -f -N -T -R22222:localhost:22 yourpublichost.example.com
This tells your client to establish a tunnel with a -R
emote entry point. Anything that attaches to port 22222 on the far end of the tunnel will actually reach "localhost port 22", where "localhost" is from the perspective of the exit point of the tunnel (i.e. your ssh client).
The other options are:
-f
tells ssh to background itself after it authenticates, so you don't have to sit around running something on the remote server for the tunnel to remain alive.
-N
says that you want an SSH connection, but you don't actually want to run any remote commands. If all you're creating is a tunnel, then including this option saves resources.
-T
disables pseudo-tty allocation, which is appropriate because you're not trying to create an interactive shell.
There will be a password challenge unless you have set up DSA or RSA keys for a passwordless login.
Note that it is STRONGLY recommended that you use a throw-away account (not your own login) that you set up for just this tunnel/customer/server.
Now, from your shell on yourpublichost, establish a connection to the firewalled host through the tunnel:
ssh -p 22222 username@localhost
You'll get a host key challenge, as you've probably never hit this host before. Then you'll get a password challenge for the username
account (unless you've set up keys for passwordless login).
If you're going to be accessing this host on a regular basis, you can also simplify access by adding a few lines to your ~/.ssh/config
file:
host remotehostname
User remoteusername
Hostname localhost
Port 22222
Adjust remotehostname
and remoteusername
to suit. The remoteusername
field must match your username on the remote server, but remotehostname
can be any hostname that suits you, it doesn't have to match anything resolvable.
See also:
I think the state of the art for the maximum bandwidth is NX, an X11 protocol compression program. It should perform well with respect to latency too. Try using the Windows NX client and the free NX server on Linux.
If possible, use a direct TCP connection instead of SSH. Of course, this is only viable in a controlled environment with no security worries.
I think in most setups a virtual machine running locally will give you the best latency. Even better, run Emacs and Eclipse under Windows; make them edit remote files, or (for even better results) make them edit local files which you then synchronize with Unison or through a version control system.
Best Answer
If you're on a secure network, why encrypt? You can directly X forward without ssh, and get better speed and latency.
See for example this (old but still valid) tutorial; here you could use the (insecure) Xhost mechanism:
A Little Theory
The magic word is
DISPLAY
. In the X window system, a display consists (simplified) of a keyboard, a mouse and a screen. A display is managed by a server program, known as an X server. The server serves displaying capabilities to other programs that connect to it.A display is indicated with a name, for instance:
The display consists of a hostname (such as
light.uni.verse
andlocalhost
), a colon (:
), and a sequence number (such as0
and4
). The hostname of the display is the name of the computer where the X server runs. An omitted hostname means the local host. The sequence number is usually0
-- it can be varied if there are multiple displays connected to one computer.If you ever come across a display indication with an extra
.n
attached to it, that's the screen number. A display can actually have multiple screens. Usually there's only one screen though, with numbern
=0
, so that's the default.Other forms of
DISPLAY
exist, but the above will do for our purposes.Telling the client
The client program (for instance, your graphics application) knows which display to connect to by inspecting the
DISPLAY
environment variable.Our computer is known to the outside as
light
, and we're in domainuni.verse
. If we're running a normal X server, the display is known aslight.uni.verse:0
. We want to run the drawing programxfig
on a remote computer, calleddark.matt.er
, and display its output here onlight
.Suppose you have already
telnet
/rsh
/ssh
-ed into the remote computer,dark.matt.er
.If you have
sh
running on the remote computer:or, alternatively:
Telling the Server
The server will not accept connections from just anywhere. You don't want everyone to be able to display windows on your screen. Or read what you type -- remember that your keyboard is part of your display!
Too few people seem to realise that allowing access to your display poses a security risk. Someone with access to your display can read and write your screens, read your keystrokes, and read your mouse actions.
Most servers know two ways of authenticating connections to it: the host list mechanism (
xhost
) and the magic cookie mechanism (xauth
). Then there isssh
, the secure shell, that can forward X connections.Notice that some X servers can be configured not to listen on the usual TCP port with the
-nolisten tcp
argument. Notably the default configuration of Debian GNU/Linux is to disable the X server listening on the TCP port. If you wish to use remote X on a Debian system, you should re-enable this by altering the way the X server is started. Look at/etc/X11/xinit/xserverrc
for a start.Xhost
Xhost allows access based on hostnames. The server maintains a list of hosts which are allowed to connect to it. It can also disable host checking entirely. Beware: this means no checks are done, so every host may connect!
You can control the server's host list with the
xhost
program. To use this mechanism in the previous example, do:This allows all connections from host dark.matt.er. As soon as your X client has made its connection and displays a window, for safety, revoke permissions for more connections with:
You can disable host checking with:
This disables host access checking and thus allows everyone to connect. You should never do this on a network on which you don't trust all users (such as Internet). You can re-enable host checking with:
xhost -
by itself does not remove all hosts from the access list (that would be quite useless - you wouldn't be able to connect from anywhere, not even your local host).Xhost is a very insecure mechanism. It does not distinguish between different users on the remote host. Also, hostnames (addresses actually) can be spoofed. This is bad if you're on an untrusted network (for instance already with dialup PPP access to Internet).