How X Over SSH really works
2012-07-11 11:27
141 查看
http://dustwell.com/how-x-over-ssh-really-works.html
Imagine you are sitting in front of a machine named "home" that has a keyboard, mouse, display, and is running an X server. Now you open a terminal and ssh to a machine called "remote" (which doesn't need to have an X server running), and run a program like
"firefox" which pops a window in your screen. How does this all work?
First, let's clear up the client/server terminology confusion. When talking about X:
X client: a process (like firefox or xemacs) which uses the X client API to display things and receive mouse/keyboard events.
X server: a process (usually just "X") which X clients connect to. At times (as we'll see below) other processes can act as X servers.
Whenever an X client starts up, it reads the local $DISPLAY environment variable, whose value looks like: [hostname]:display_number[.screen_number]. The X client immediately opens a connection to that X server. If it can't, it fails:
user@home: echo $DISPLAY
:0 # hostname is "localhost" by default
user@home: xcalc # pops up a calculator on my screen
user@home: DISPLAY="nosuchhost:99"
user@home: xcalc
Error: Can't open display: nosuchhost:99
Now let's see what happens when you ssh to another machine:
user@home: ps aux | grep X # yep, X server running @home
root ... /usr/bin/X :0 ...
user@home: ssh -X user@remote # -X enables X-forwarding
user@remote: ps aux | grep X # nope, no X server here
user@remote: echo $DISPLAY
:11.0
user@remote: xcalc # pops up screen @home
Wait a minute, the $DISPLAY variable is pointing to the localhost ("remote"). Natural questions to ask at this point:
There is no X server @remote, so why didn't xcalc just fail on startup?
Why was the display number "11".
How did xcalc show something @home?
The answer has to do with the ssh-daemon running @remote:
user@remote: ps aux | grep user
root ... sshd:user@pts/11
What's happening is that there's an "X emulator" running @remote that was setup just for your ssh session, that is listening on display 11.
To review, here's a play-by-play:
You type "ssh -X user@remote" in your terminal
The ssh process connects to the sshd server @remote.
sshd spawns a new process that is an X-server-emulator listening on some display number, e.g. "11"
sshd sets the $DISPLAY to point to that local "X-server" (e.g. ":11")
xcalc reads this $DISPLAY and conncects to this X-server. xcalc thinks it's displaying to the local machine.
the X-server-emulator simply forwards the X commands from xcalc through the ssh connection, to the original ssh process.
The ssh process @home now acts as a normal X-client and sends those commands to the X-server @home.
Some of you might be wondering: wasn't the X protocol designed to go over the network? Can't you do all this without ssh? You might be tempted to try something like:
user@remote: DISPLAY="home:0"
user@remote: xcalc
This doesn't work because the X server @home won't let other hosts connect to it. To change this (not that you should -- see below) you can do:
user@home: xhost +remote
xhost is a command which says "that host can connect to our X-server". However, everybody uses ssh X forwarding instead. Here are some security reasons why:
Normally, X-traffic (like your keystrokes) is sent unencrypted from X-client to X-server.
Ssh nicely sends that data through an encrypted channel, so it doesn't go over the internet in the clear.
"xhost +remote" is putting a lot of trust in 'remote' being a nice guy. If remote ever gets hacked, it could connect to the X-server @home and listen to all its keystrokes.
There's also an issue with firewalls: by doing "DISPLAY=home:0", you're assuming that a connection can be established from remote -> home. But this isn't always possible -- home might be sitting behind a firewall (like your Netgear router). Since the ssh-connection
was setup from home-> remote, it takes advantage of this already-established connection.
Other notes for the curious:
- if $DISPLAY is set to "localhost:0" (or any explicitly named host) it uses tcp-ip to send the X-traffic locally.
- if $DISPLAY is just ":0" it uses a special (more efficient, non-tcp-ip) connection.
Imagine you are sitting in front of a machine named "home" that has a keyboard, mouse, display, and is running an X server. Now you open a terminal and ssh to a machine called "remote" (which doesn't need to have an X server running), and run a program like
"firefox" which pops a window in your screen. How does this all work?
First, let's clear up the client/server terminology confusion. When talking about X:
X client: a process (like firefox or xemacs) which uses the X client API to display things and receive mouse/keyboard events.
X server: a process (usually just "X") which X clients connect to. At times (as we'll see below) other processes can act as X servers.
Whenever an X client starts up, it reads the local $DISPLAY environment variable, whose value looks like: [hostname]:display_number[.screen_number]. The X client immediately opens a connection to that X server. If it can't, it fails:
user@home: echo $DISPLAY
:0 # hostname is "localhost" by default
user@home: xcalc # pops up a calculator on my screen
user@home: DISPLAY="nosuchhost:99"
user@home: xcalc
Error: Can't open display: nosuchhost:99
Now let's see what happens when you ssh to another machine:
user@home: ps aux | grep X # yep, X server running @home
root ... /usr/bin/X :0 ...
user@home: ssh -X user@remote # -X enables X-forwarding
user@remote: ps aux | grep X # nope, no X server here
user@remote: echo $DISPLAY
:11.0
user@remote: xcalc # pops up screen @home
Wait a minute, the $DISPLAY variable is pointing to the localhost ("remote"). Natural questions to ask at this point:
There is no X server @remote, so why didn't xcalc just fail on startup?
Why was the display number "11".
How did xcalc show something @home?
The answer has to do with the ssh-daemon running @remote:
user@remote: ps aux | grep user
root ... sshd:user@pts/11
What's happening is that there's an "X emulator" running @remote that was setup just for your ssh session, that is listening on display 11.
To review, here's a play-by-play:
You type "ssh -X user@remote" in your terminal
The ssh process connects to the sshd server @remote.
sshd spawns a new process that is an X-server-emulator listening on some display number, e.g. "11"
sshd sets the $DISPLAY to point to that local "X-server" (e.g. ":11")
xcalc reads this $DISPLAY and conncects to this X-server. xcalc thinks it's displaying to the local machine.
the X-server-emulator simply forwards the X commands from xcalc through the ssh connection, to the original ssh process.
The ssh process @home now acts as a normal X-client and sends those commands to the X-server @home.
Some of you might be wondering: wasn't the X protocol designed to go over the network? Can't you do all this without ssh? You might be tempted to try something like:
user@remote: DISPLAY="home:0"
user@remote: xcalc
This doesn't work because the X server @home won't let other hosts connect to it. To change this (not that you should -- see below) you can do:
user@home: xhost +remote
xhost is a command which says "that host can connect to our X-server". However, everybody uses ssh X forwarding instead. Here are some security reasons why:
Normally, X-traffic (like your keystrokes) is sent unencrypted from X-client to X-server.
Ssh nicely sends that data through an encrypted channel, so it doesn't go over the internet in the clear.
"xhost +remote" is putting a lot of trust in 'remote' being a nice guy. If remote ever gets hacked, it could connect to the X-server @home and listen to all its keystrokes.
There's also an issue with firewalls: by doing "DISPLAY=home:0", you're assuming that a connection can be established from remote -> home. But this isn't always possible -- home might be sitting behind a firewall (like your Netgear router). Since the ssh-connection
was setup from home-> remote, it takes advantage of this already-established connection.
Other notes for the curious:
- if $DISPLAY is set to "localhost:0" (or any explicitly named host) it uses tcp-ip to send the X-traffic locally.
- if $DISPLAY is just ":0" it uses a special (more efficient, non-tcp-ip) connection.
相关文章推荐
- Javascript – How Prototypal Inheritance really works(vjeux)
- Javascript – How Prototypal Inheritance really works
- How Garbage Collection Really Works 垃圾清理究竟是如何工作的
- OpenCV+VS, tell you how it really works
- How Scaling Really Works in Apache HBase
- OMAP3530 DSP Howto ( Really works by DSPLINK)
- 每日英语:How the Brain Really Works
- How Garbage Collection Really Works
- How Garbage Collection Really Works
- Garbage Collection in .NET - How it really works
- How Garbage Collection Really Works
- How Scaling Really Works in Apache HBase
- How Spring Web MVC Really Works
- How Siri really works
- How Pair Programming Really Works
- How to mount a remote directory over ssh on Linux(LInux通过ssh挂载远程目录)
- How tomcat works——6 生命周期
- How the Web works
- MBR:How It Works -- Master Boot Record
- How Tomcat Works(四)