mirror of https://github.com/tLDP/LDP
1062 lines
39 KiB
Plaintext
1062 lines
39 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
|
|
<title>Remote X Apps mini-HOWTO
|
|
|
|
<author><htmlurl url="http://www.xs4all.nl/~zweije/"
|
|
name="Vincent Zweije">, <htmlurl url="mailto:zweije@xs4all.nl"
|
|
name="zweije@xs4all.nl">
|
|
|
|
<date>v0.7.5, 8 December 2001
|
|
|
|
<abstract>
|
|
|
|
This mini-HOWTO describes how to run remote X applications. That is, how
|
|
to have an X program display on a different computer than the one it's
|
|
running on. Or conversely: how to make an X program run on a different
|
|
computer than the one you're sitting at. The focus of this mini-HOWTO
|
|
is on security. This mini-HOWTO also contains information on running X
|
|
applications locally, but with a different user-id, and information on
|
|
setting up a computer as an X terminal.
|
|
|
|
</abstract>
|
|
|
|
<toc>
|
|
|
|
<sect> Introduction
|
|
|
|
<p>
|
|
This mini-HOWTO is a guide how to do remote X applications. It was
|
|
written for several reasons.
|
|
<enum>
|
|
<item> Many questions have appeared on usenet on how to run a remote
|
|
X application.
|
|
<item> I see many, many hints of ``use <tt/xhost +hostname/'' or even
|
|
``<tt/xhost +/'' to allow X connections. <bf/This is ridiculously
|
|
insecure/, and there are better methods.
|
|
<item> I do not know of a simple document that describes the options you
|
|
<em/do/ have. Please inform me <htmlurl url="mailto:zweije@xs4all.nl"
|
|
name="zweije@xs4all.nl"> if you know more.
|
|
</enum>
|
|
|
|
This document has been written with unix-like systems in mind. If either
|
|
your local or remote operating system are of another flavour, you may
|
|
find here how things work. However, you will have to translate examples
|
|
yourself to apply to your own system(s).
|
|
|
|
The most recent version of this document is always available on
|
|
WWW at <htmlurl url="http://www.xs4all.nl/~zweije/xauth.html"
|
|
name="http://www.xs4all.nl/˜zweije/xauth.html">. It
|
|
is also available as the Linux Remote X Apps mini-HOWTO at
|
|
<htmlurl url="http://sunsite.unc.edu/LDP/HOWTO/mini/Remote-X-Apps"
|
|
name="http://sunsite.unc.edu/LDP/HOWTO/mini/Remote-X-Apps">. Linux
|
|
(mini-)HOWTOs are available by http or ftp from <htmlurl
|
|
url="http://sunsite.unc.edu/LDP/HOWTO/HOWTO-INDEX-2.html"
|
|
name="sunsite.unc.edu">.
|
|
|
|
This is version 0.7.5. No guarantees, only good intentions. I'm open
|
|
to suggestions, ideas, additions, useful pointers, (typo) corrections,
|
|
etc... I want this to remain a simple readable document, though, in the
|
|
best-meant HOWTO style. Flames to <tt>/dev/null</tt>. This document is
|
|
released under version 1.1 of the <htmlurl url="http://www.gnu.org/"
|
|
name="GNU"> Free Documentation Licence.
|
|
|
|
Contents last updated on 8 December 2001 by <htmlurl
|
|
url="http://www.xs4all.nl/~zweije/index.html" name="Vincent Zweije">
|
|
|
|
<sect> Related Reading
|
|
|
|
<p>
|
|
A related document on WWW is ``What to do when Tk says that your display
|
|
is insecure'', <htmlurl url="http://ce-toolkit.crd.ge.com/tkxauth/"
|
|
name="http://ce-toolkit.crd.ge.com/tkxauth/">. It was written by <htmlurl
|
|
url="http://ce-toolkit.crd.ge.com/people/kennykb.html" name="Kevin
|
|
Kenny">. It suggests a similar solution to X authentication to that in
|
|
this document (xauth). However, Kevin aims more at using xdm to steer
|
|
xauth for you.
|
|
|
|
The X System Window System Vol. 8 ``X Window System Administrator's
|
|
Guide'' from <htmlurl url="http://www.ora.com/" name="O'Reilly and
|
|
Associates"> has also been brought to my attention and confirmed as a
|
|
good source of information. However, it has not been revised since its
|
|
original publication in 1992. As such it only covers X11R4 and X11R5,
|
|
anything specific to X11R6 will not be covered.
|
|
|
|
Yet another document much like the one you're reading
|
|
now, titled ``Securing X Windows'', is available at <htmlurl
|
|
url="http://ciac.llnl.gov/ciac/documents/ciac2316.html"
|
|
name="http://ciac.llnl.gov/ciac/documents/ciac2316.html">.
|
|
|
|
Also check out usenet newsgroups, such as <tt/comp.windows.x/,
|
|
<tt/comp.os.linux.x/, and <tt/comp.os.linux.networking/.
|
|
|
|
<sect> The Scene
|
|
|
|
<p>
|
|
You're using two computers. You're using the X window system of the first
|
|
to type to and look at. You're using the second to do some important
|
|
graphical work. You want the second to show its output on the display
|
|
of the first. The X window system makes this possible.
|
|
|
|
Of course, you need a network connection for this. Preferably a fast
|
|
one; the X protocol is a network hog. But with a little patience
|
|
and suitable protocol compression, you can even run applications
|
|
over a modem. For X protocol compression, you might want to check
|
|
out dxpc <htmlurl url="http://www.vigor.nu/dxpc/"
|
|
name="http://www.vigor.nu/dxpc/"> or LBX
|
|
<url url="http://www.paulandlesley.org/faqs/LBX-HOWTO.html"
|
|
name="http://www.paulandlesley.org/faqs/LBX-HOWTO.html"> (also
|
|
known as the <htmlurl url="http://sunsite.unc.edu/LDP/HOWTO/mini/LBX"
|
|
name="LBX mini-HOWTO">).
|
|
|
|
You must do two things to achieve all this:
|
|
|
|
<enum>
|
|
|
|
<item> Tell the local display (the server) to accept connections from
|
|
the remote computer.
|
|
|
|
<item> Tell the remote application (the client) to direct its output to
|
|
your local display.
|
|
|
|
</enum>
|
|
|
|
<sect> A Little Theory
|
|
|
|
<p>
|
|
The magic word is <tt/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:
|
|
|
|
<itemize>
|
|
|
|
<item> <tt/DISPLAY=light.uni.verse:0/
|
|
|
|
<item> <tt/DISPLAY=localhost:4/
|
|
|
|
<item> <tt/DISPLAY=:0/
|
|
|
|
</itemize>
|
|
|
|
The display consists of a hostname (such as <tt/light.uni.verse/ and
|
|
<tt/localhost/), a colon (<tt/:/), and a sequence number (such as <tt/0/
|
|
and <tt/4/). 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 usually 0 -- it can be varied if there are multiple
|
|
displays connected to one computer.
|
|
|
|
If you ever come across a display indication with an extra <tt/.n/
|
|
attached to it, that's the screen number. A display can actually have
|
|
multiple screens. Usually there's only one screen though, with number
|
|
<tt/n=0/, so that's the default.
|
|
|
|
Other forms of <tt/DISPLAY/ exist, but the above will do for our purposes.
|
|
|
|
For the technically curious:
|
|
<itemize>
|
|
|
|
<item> <tt/hostname:D.S/ means screen <tt/S/ on display <tt/D/ of host
|
|
<tt/hostname/; the X server for this display is listening at TCP
|
|
port <tt/6000+D/.
|
|
|
|
<item> <tt>host/unix:D.S</tt> means screen <tt/S/ on display <tt/D/
|
|
of host <tt/host/; the X server for this display is listening
|
|
at UNIX domain socket <tt>/tmp/.X11-unix/XD</tt> (so it's only
|
|
reachable from <tt/host/).
|
|
|
|
<item> <tt/:D.S/ is equivalent to <tt>host/unix:D.S</tt>, where <tt/host/
|
|
is the local hostname.
|
|
|
|
</itemize>
|
|
|
|
<sect> Telling the Client
|
|
|
|
<p>
|
|
The client program (for instance, your graphics application) knows
|
|
which display to connect to by inspecting the <tt/DISPLAY/ environment
|
|
variable. This setting can be overridden, though, by giving the client
|
|
the command line argument <tt/-display hostname:0/ when it's started. Some
|
|
examples may clarify things.
|
|
|
|
Our computer is known to the outside as light, and we're in domain
|
|
uni.verse. If we're running a normal X server, the display is known as
|
|
<tt/light.uni.verse:0/. We want to run the drawing program xfig on a remote
|
|
computer, called <tt/dark.matt.er/, and display its output here on light.
|
|
|
|
Suppose you have already telnetted into the remote computer,
|
|
<tt/dark.matt.er/.
|
|
|
|
If you have csh running on the remote computer:
|
|
|
|
<tscreen><verb>
|
|
dark% setenv DISPLAY light.uni.verse:0
|
|
dark% xfig &
|
|
</verb></tscreen>
|
|
|
|
or alternatively:
|
|
|
|
<tscreen><verb>
|
|
dark% xfig -display light.uni.verse:0 &
|
|
</verb></tscreen>
|
|
|
|
If you have sh running on the remote computer:
|
|
|
|
<tscreen><verb>
|
|
dark$ DISPLAY=light.uni.verse:0
|
|
dark$ export DISPLAY
|
|
dark$ xfig &
|
|
</verb></tscreen>
|
|
|
|
or, alternatively:
|
|
|
|
<tscreen><verb>
|
|
dark$ DISPLAY=light.uni.verse:0 xfig &
|
|
</verb></tscreen>
|
|
|
|
or, of course, also:
|
|
|
|
<tscreen><verb>
|
|
dark$ xfig -display light.uni.verse:0 &
|
|
</verb></tscreen>
|
|
|
|
It seems that some versions of telnet automatically transport the
|
|
<tt/DISPLAY/ variable to the remote host. If you have one of those,
|
|
you're lucky, and you don't have to set it by hand. If not, most versions
|
|
of telnet do transport the <tt/TERM/ environment variable; with some
|
|
judicious hacking it is possible to piggyback the <tt/DISPLAY/ variable
|
|
on to the <tt/TERM/ variable.
|
|
|
|
The idea with piggybacking is that you do some scripting to achieve
|
|
the following: before telnetting, attach the value of <tt/DISPLAY/
|
|
to <tt/TERM/. Then telnet out. At the remote end, in the applicable
|
|
<tt/.*shrc/ file, read the value of <tt/DISPLAY/ from <tt/TERM/.
|
|
|
|
<sect> Telling the Server
|
|
|
|
<p>
|
|
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 is ssh, the secure shell, that can forward X connections.
|
|
|
|
Notice that some X servers (from XFree86) can be configured not to
|
|
listen on the usual TCP port with the <tt/-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 <tt>/etc/X11/xinit/xserverrc</tt> for a start.
|
|
|
|
<sect1> Xhost
|
|
|
|
<p>
|
|
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 <em/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:
|
|
|
|
<tscreen><verb>
|
|
light$ xhost +dark.matt.er
|
|
</verb></tscreen>
|
|
|
|
This allows all connections from host <tt/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:
|
|
|
|
<tscreen><verb>
|
|
light$ xhost -dark.matt.er
|
|
</verb></tscreen>
|
|
|
|
You can disable host checking with:
|
|
|
|
<tscreen><verb>
|
|
light$ xhost +
|
|
</verb></tscreen>
|
|
|
|
This disables host access checking and thus allows <em/everyone/
|
|
to connect. You should <em/never/ do this on a network on which you
|
|
don't trust <em/all/ users (such as Internet). You can re-enable host
|
|
checking with:
|
|
|
|
<tscreen><verb>
|
|
light$ xhost -
|
|
</verb></tscreen>
|
|
|
|
xhost - by itself does <em/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).
|
|
|
|
<em/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).
|
|
|
|
<sect1> Xauth
|
|
|
|
<p>
|
|
Xauth allows access to anyone who knows the right secret. Such a secret
|
|
is called an authorization record, or a magic cookie. This authorization
|
|
scheme is formally called MIT-MAGIC-COOKIE-1.
|
|
|
|
The cookies for different displays are stored together in
|
|
<tt>˜/.Xauthority</tt>. Your <tt>˜/.Xauthority</tt> must
|
|
be inaccessible for group/other users. The xauth program manages these
|
|
cookies, hence the nickname xauth for the scheme.
|
|
|
|
You can specify a different cookie file with the <tt/XAUTHORITY/
|
|
environment variable, but you will rarely need this. If you're not sure
|
|
which cookie file your xauth is using, do an <tt/xauth -v/, and it will
|
|
tell you.
|
|
|
|
On starting a session, the server reads a cookie from the file that
|
|
is indicated by the <tt/-auth/ argument. After that, the server only
|
|
allows connections from clients that know the same cookie. When the
|
|
cookie in <tt>˜/.Xauthority</tt> changes, <em/the server will not pick
|
|
up the change/.
|
|
|
|
Newer servers can generate cookies on the fly for clients that ask for
|
|
it. Cookies are still kept inside the server though; they don't end up
|
|
in <tt>˜/.Xauthority</tt> unless a client puts them there. According to
|
|
David Wiggins:
|
|
|
|
<quote>
|
|
A further wrinkle was added in X11R6.3 that you may be interested in. Via
|
|
the new SECURITY extension, the X server itself can generate and return
|
|
new cookies on the fly. Furthermore, the cookies can be designated
|
|
``untrusted'' so that applications making connections with such cookies
|
|
will be restricted in their operation. For example, they won't be able
|
|
to steal keyboard/mouse input, or window contents, from other trusted
|
|
clients. There is a new ``generate'' subcommand to xauth to make this
|
|
facility at least possible to use, if not easy.
|
|
</quote>
|
|
|
|
Xauth has a clear security advantage over xhost. You can limit access to
|
|
specific users on specific computers. It does not suffer from spoofed
|
|
addresses as xhost does. And if you want to, you can still use xhost
|
|
next to it to allow connections.
|
|
|
|
<sect2> Making the Cookie
|
|
|
|
<p>
|
|
If you want to use xauth, you must start the X server with the <tt/-auth
|
|
authfile/ argument. If you use the startx script, that's the right place
|
|
to do it. Create the authorization record as below in your startx script.
|
|
|
|
Excerpt from <tt>/usr/X11R6/bin/startx</tt>:
|
|
|
|
<tscreen><verb>
|
|
mcookie|sed -e 's/^/add :0 . /'|xauth -q
|
|
xinit -- -auth "$HOME/.Xauthority"
|
|
</verb></tscreen>
|
|
|
|
Mcookie is a tiny program in the util-linux package,
|
|
primary site <htmlurl url="ftp://ftp.math.uio.no/pub/linux/"
|
|
name="ftp://ftp.math.uio.no/pub/linux/">. Alternatively, you
|
|
can use md5sum to massage some random data (from, for instance,
|
|
<tt>/dev/urandom</tt> or <tt/ps -axl/) into cookie format:
|
|
|
|
<tscreen><verb>
|
|
dd if=/dev/urandom count=1|md5sum|sed -e 's/^/add :0 . /'|xauth -q
|
|
xinit -- -auth "$HOME/.Xauthority"
|
|
</verb></tscreen>
|
|
|
|
If you can't edit the startx script (because you aren't root), get
|
|
your system administrator to set up startx properly, or let him set up
|
|
xdm instead. If he can't or won't, you can make a <tt>˜/.xserverrc</tt>
|
|
script. If you have this script, it is run by xinit instead of the real
|
|
X server. Then you can start the real X server from this script with the
|
|
proper arguments. To do so, have your <tt>˜/.xserverrc</tt> use the magic
|
|
cookie line above to create a cookie and then exec the real X server:
|
|
|
|
<tscreen><verb>
|
|
#!/bin/sh
|
|
mcookie|sed -e 's/^/add :0 . /'|xauth -q
|
|
exec /usr/X11R6/bin/X "$@" -auth "$HOME/.Xauthority"
|
|
</verb></tscreen>
|
|
|
|
If you use xdm to manage your X sessions, you can use
|
|
xauth easily. Define the DisplayManager.authDir resource in
|
|
<tt>/etc/X11/xdm/xdm-config</tt>. Xdm will pass the <tt/-auth/ argument
|
|
to the X server when it starts. When you then log in under xdm, xdm
|
|
puts the cookie in your <tt>˜/.Xauthority</tt> for you. See xdm(1)
|
|
for more information. For instance, my <tt>/etc/X11/xdm/xdm-config</tt>
|
|
has the following line in it:
|
|
|
|
<tscreen><verb>
|
|
DisplayManager.authDir: /var/lib/xdm
|
|
</verb></tscreen>
|
|
|
|
<sect2> Transporting the Cookie
|
|
|
|
<p>
|
|
Now that you have started your X session on the server host
|
|
<tt/light.uni.verse/ and have your cookie in <tt>˜/.Xauthority</tt>, you
|
|
will have to transfer the cookie to the client host, <tt/dark.matt.er/. There are several ways to do this.
|
|
|
|
<sect3> Shared Home Directories
|
|
|
|
<p>
|
|
The easiest is when your home directories on light and dark are
|
|
shared. The <tt>˜/.Xauthority</tt> files are the same, so the
|
|
cookie is transported instantaneously. However, there's a catch: when
|
|
you put a cookie for <tt/:0/ in <tt>˜/.Xauthority</tt>, dark will
|
|
think it's a cookie for itself instead of for light. You must use an
|
|
explicit host name when you create the cookie; you can't leave it out.
|
|
You can install the same cookie for both <tt/:0/ and <tt/light:0/ with
|
|
this little piece of sed wizardry:
|
|
|
|
<tscreen><verb>
|
|
#!/bin/sh
|
|
mcookie|sed -e 's/^/add :0 . /' -e p -e "s/:/$HOST&/"|xauth -q
|
|
exec /usr/X11R6/bin/X "$@" -auth "$HOME/.Xauthority"
|
|
</verb></tscreen>
|
|
|
|
<sect3> By the Remote Shell, <tt/rsh/
|
|
|
|
<p>
|
|
If the home directories aren't shared, you can transport the cookie by
|
|
means of rsh, the remote shell:
|
|
|
|
<tscreen><verb>
|
|
light$ xauth nlist "${HOST}:0" | rsh dark.matt.er xauth nmerge -
|
|
</verb></tscreen>
|
|
|
|
<enum>
|
|
|
|
<item> Extract the cookie from your local <tt>˜/.Xauthority</tt>
|
|
(<tt/xauth nlist :0/).
|
|
|
|
<item> Transfer it to dark.matt.er (<tt/| rsh dark.matt.er/).
|
|
|
|
<item> Put it in the <tt>˜/.Xauthority</tt> there (<tt/xauth nmerge -/).
|
|
|
|
</enum>
|
|
|
|
<p>
|
|
Notice the use of <tt/${HOST}/. You need to transport the cookie that is
|
|
explicitly associated with the local host. A remote X application would
|
|
interpret a display value of <tt/:0/ as referring to the remote machine,
|
|
which is not what you want!
|
|
|
|
<sect3> Manually, by Telnet
|
|
|
|
<p>
|
|
It's possible that rsh doesn't work for you. Besides that, rsh also has a
|
|
security drawback (spoofed host names again, if I remember correctly). If
|
|
you can't or don't want to use rsh, you can also transfer the cookie
|
|
manually, like:
|
|
|
|
<tscreen><verb>
|
|
light$ echo $DISPLAY
|
|
:0
|
|
light$ xauth list $DISPLAY
|
|
light/unix:0 MIT-MAGIC-COOKIE-1 076aaecfd370fd2af6bb9f5550b26926
|
|
light$ rlogin dark.matt.er
|
|
Password:
|
|
dark% setenv DISPLAY light.uni.verse:0
|
|
dark% xauth
|
|
Using authority file /home/zweije/.Xauthority
|
|
xauth> add light.uni.verse:0 . 076aaecfd370fd2af6bb9f5550b26926
|
|
xauth> exit
|
|
Writing authority file /home/zweije/.Xauthority
|
|
dark% xfig &
|
|
[15332]
|
|
dark% logout
|
|
light$
|
|
</verb></tscreen>
|
|
|
|
See also rsh(1) and xauth(1x) for more information.
|
|
|
|
<sect3> Automating the Telnet Way
|
|
|
|
<p>
|
|
It may be possible to piggyback the cookie on the <tt/TERM/ or
|
|
<tt/DISPLAY/ variable when you do a telnet to the remote host. This would
|
|
go the same way as piggybacking the <tt/DISPLAY/ variable on the <tt/TERM/
|
|
variable. See section 5: Telling the Client. You're on own here from
|
|
my point of view, but I'm interested if anyone can confirm or deny this.
|
|
|
|
Notice, however, that environment variables can be observed by others on
|
|
some unices, and you won't be able to prevent the cookie in <tt/$TERM/
|
|
from showing up if people are looking for it.
|
|
|
|
<sect2> Using the Cookie
|
|
|
|
<p>
|
|
An X application on dark.matt.er, such as xfig above, will automatically
|
|
look in <tt>˜/.Xauthority</tt> there for the cookie to authenticate
|
|
itself with.
|
|
|
|
<p>
|
|
There's a little wrinkle when using <tt/localhost:D/. X client
|
|
applications translate <tt/localhost:D/ into <tt>host/unix:D</tt> for
|
|
the purpose of cookie retrieval. Effectively, this means that a cookie
|
|
for <tt/localhost:D/ in your <tt>~/.Xauthority</tt> has <em/no/ effect.
|
|
|
|
If you think about it, it's only logical. The interpretation of
|
|
<tt/localhost/ depends entirely on the machine on which it's interpreted.
|
|
It would give a horrible mess when you have a shared home directory,
|
|
such as through NFS, with several hosts all interfering with each
|
|
other's cookies.
|
|
|
|
<sect1> Ssh
|
|
|
|
<p>
|
|
Authority records are transmitted over the network with no encryption.
|
|
If you're even worried someone might snoop on your connections, use ssh,
|
|
the secure shell. It can do X forwarding over encrypted connections.
|
|
|
|
To turn on X forwarding over ssh, use the command line switch <tt/-X/
|
|
or write the following in your local ssh configuration file:
|
|
|
|
<tscreen><verb>
|
|
Host remote.host.name
|
|
ForwardX11 yes
|
|
</verb></tscreen>
|
|
|
|
The ssh server (<tt/sshd/) at the remote end automatically sets
|
|
<tt/DISPLAY/ to point to its end of the X forwarding tunnel. The remote
|
|
tunnel end gets its own cookie; the remote ssh server generates it for
|
|
you and puts it in <tt>~/.Xauthority</tt> there. So, X authorisation
|
|
with ssh is fully automatic.
|
|
|
|
By the way, ssh is great in other ways too. It's a good structural
|
|
improvement to your system. For more information, visit <htmlurl
|
|
url="http://www.ssh.org/" name="http://www.ssh.org/">, the ssh home page.
|
|
|
|
<p>
|
|
Who knows anything else on authentication schemes or encrypting X
|
|
connections? Maybe kerberos?
|
|
|
|
<sect> X Applications from Another User-id
|
|
|
|
<p>
|
|
Suppose you want to run a graphical configuration tool that requires
|
|
root privileges. However, your X session is running under your usual
|
|
account. It may seem strange at first, but the X server will <em/not/
|
|
allow the tool to access your display. How is this possible when root
|
|
can normally do anything? And how do you work around this problem?
|
|
|
|
<p>
|
|
Let's generalise to the situation where you want to an X appliation
|
|
under a user-id <tt/clientuser/, but the X session was started
|
|
by <tt/serveruser/. If you have read the section on cookies,
|
|
it is clear why <tt/clientuser/ cannot access your display:
|
|
<tt>~clientuser/.Xauthority</tt> does not contain the right magic
|
|
cookie for accessing the display. The right cookie is found in
|
|
<tt>~serveruser/.Xauthority</tt>.
|
|
|
|
<sect1> Different Users on the Same Host
|
|
|
|
<p>
|
|
Of course, anything that works for remote X also works for X from
|
|
a different user-id as well (particularly <tt/slogin localhost -l
|
|
clientuser/). It's just that the client host and the server host happen
|
|
to be the same. However, when both hosts are the same, there are some
|
|
shortcuts for transferring the magic cookie.
|
|
|
|
<p>
|
|
We'll assume that you use <tt/su/ to switch user-ids. Basically, what
|
|
you have to do is write a script that will call <tt/su/, but wraps the
|
|
command that <tt/su/ executes with some code that does the necessary
|
|
things for remote X. These necessary things are setting the <tt/DISPLAY/
|
|
variable and transferring the magic cookie.
|
|
|
|
<p>
|
|
Setting <tt/DISPLAY/ is relatively easy; it just means defining
|
|
<tt/DISPLAY="$DISPLAY"/ before running the su command argument. So you
|
|
could just do:
|
|
|
|
<tscreen><verb>
|
|
su - clientuser -c "env DISPLAY=$DISPLAY clientprogram &"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
This doesn't work yet, because we still have to transfer the cookie.
|
|
We can retrieve the cookie using <tt/xauth list "$DISPLAY"/. This command
|
|
happens to list the cookie in a format that's suitable for feeding back
|
|
to the <tt/xauth add/ command; just what we need!
|
|
|
|
We shall want to pass the cookie through a pipe. Unfortunately, it
|
|
isn't easy to pass something through a pipe to the <tt/su/ command,
|
|
because <tt/su/ wants to read the password from its standard input.
|
|
Fortunately again, in a shell script we can joggle some file descriptors
|
|
around, and get it done.
|
|
|
|
So we write a script around this, parameterizing by <tt/clientuser/
|
|
and <tt/clientprogram/. Let's improve the script a little while we're
|
|
at it, making it less readable but more robust. It looks like this:
|
|
|
|
<tscreen><verb>
|
|
#!/bin/sh
|
|
|
|
if [ $# -lt 2 ]
|
|
then echo "usage: `basename $0` clientuser command" >&2
|
|
exit 2
|
|
fi
|
|
|
|
CLIENTUSER="$1"
|
|
shift
|
|
|
|
# FD 4 becomes stdin too
|
|
exec 4>&0
|
|
|
|
xauth list "$DISPLAY" | sed -e 's/^/add /' | {
|
|
|
|
# FD 3 becomes xauth output
|
|
# FD 0 becomes stdin again
|
|
# FD 4 is closed
|
|
exec 3>&0 0>&4 4>&-
|
|
|
|
exec su - "$CLIENTUSER" -c \
|
|
"xauth -q <&3
|
|
exec env DISPLAY='$DISPLAY' "'"$SHELL"'" -c '$*' 3>&-"
|
|
|
|
}
|
|
</verb></tscreen>
|
|
|
|
I think this is portable and works well enough in most circumstances.
|
|
The only shortcoming I can think of right now is that, due to using
|
|
<tt/'$*'/, single quotes in <tt/command/ will mess up quoting in the
|
|
<tt/su/ command argument (<tt/'$*'/). If there's anything else seriously
|
|
wrong with it, please drop me an email.
|
|
|
|
<p>
|
|
Call the script <tt>/usr/local/bin/xsu</tt>, and you can do:
|
|
|
|
<tscreen><verb>
|
|
xsu clientuser 'command &'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Can't be much easier, unless you get rid of the password. Yes, there
|
|
are ways for that too (<tt/sudo/), but this is not the place for that.
|
|
|
|
<p>
|
|
The tiny <tt/xsu/ script just mentioned has served as the basis for a
|
|
more extended script called <tt/sux/ which apparently has found its way
|
|
as a package into the <htmlurl url="http://www.debian.org/" name="Debian">
|
|
distribution.
|
|
|
|
<sect1> Client User Is Root
|
|
|
|
<p>
|
|
Obviously, anything that works for non-root client users is going to
|
|
work for root as well. However, with root you can make it even easier,
|
|
because root can read anyone's <tt>~/.Xauthority</tt> file. There's no
|
|
need to transfer the cookie. All you have to do is set <tt/DISPLAY/, and
|
|
point <tt/XAUTHORITY/ to <tt>~serveruser/.Xauthority</tt>. So you can do:
|
|
|
|
<tscreen><verb>
|
|
su - -c "exec env DISPLAY='$DISPLAY' \
|
|
XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
|
|
command"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Putting it into a script would give something like:
|
|
|
|
<tscreen><verb>
|
|
#!/bin/sh
|
|
if [ $# -lt 1 ]
|
|
then echo "usage: `basename $0` command" >&2
|
|
exit 2
|
|
fi
|
|
su - -c "exec env DISPLAY='$DISPLAY' \
|
|
XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
|
|
"'"$SHELL"'" -c '$*'"
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Call the script <tt>/usr/local/bin/xroot</tt>, and you can do:
|
|
|
|
<tscreen><verb>
|
|
xroot 'control-panel &'
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Although, if you've set up <tt/xsu/ already, there's no real reason to
|
|
do this.
|
|
|
|
<sect> Running a Remote Window Manager
|
|
|
|
<p>
|
|
A window manager (like <tt/twm/, <tt/wmaker/, or <tt/fvwm95/) is an
|
|
application like any other. The normal procedure should work.
|
|
|
|
<p>
|
|
Well, almost. At most one window manager can be running on a display at
|
|
any time. If you are already running a local window manager, you cannot
|
|
start the remote one (it will complain and exit). You have to kill
|
|
(or simply quit) the local one first.
|
|
|
|
<p>
|
|
Unfortunately, many X session scripts end with an
|
|
|
|
<tscreen><verb>
|
|
exec window-manager-of-choice
|
|
</verb></tscreen>
|
|
|
|
and this means that when the (local) window manager exits, your session
|
|
exits, and the X system (xdm or xinit) considers your session over and
|
|
effectively logs you out.
|
|
|
|
<p>
|
|
You have to jump through a few extra hoops, but it can be done and
|
|
it's not too difficult. Just play with your session script (normally
|
|
<tt>~/.xsession</tt> or <tt>~/.xinitrc</tt>) to get it as you want it.
|
|
|
|
<p>
|
|
Beware that a window manager often provides ways to run new programs,
|
|
and that these will run on the local machine. That is, local to where
|
|
the window manager runs. If you run a remote window manager, it will
|
|
spawn remote applications, and this may not be what you want. Of course,
|
|
they still display on the display that is local to you.
|
|
|
|
<sect> Setting Up an X Terminal
|
|
|
|
<p>
|
|
Make use of your old PC! Turn it into an extra work place! No need
|
|
for buying expensive new hardware! You've already got all it takes!
|
|
|
|
<p>
|
|
Seriously, you can set up an old PC as an X terminal. An X terminal
|
|
is a computer that basically runs nothing but an X server. You can log
|
|
in on it, and get an X session, with xterms, xbiff, xclock, every other
|
|
conceivable X client. However, all clients are running on a remote host,
|
|
and are using remote X to display their output on your local X terminal.
|
|
Even the window manager is running remotely.
|
|
|
|
<p>
|
|
An X terminal takes very few resources, compared to a full blown unix
|
|
machine. Over here I have an X terminal with a 486 CPU, 16M of RAM,
|
|
and 250M of disk space. Oh, and a network connection, of course.
|
|
It doesn't even have user home directories.
|
|
|
|
<p>
|
|
For some related reading, have a look at:
|
|
|
|
<itemize>
|
|
|
|
<item>
|
|
|
|
The <em/XDM and X Terminal mini-HOWTO/ (<htmlurl
|
|
url="http://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/other-formats/html_single/XDM-Xterm.html"
|
|
name="http://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/other-formats/html_single/XDM-Xterm.html">).
|
|
This document is an extensive description of what is possible with
|
|
XDMCP and xdm, applied for building X terminals. Definitely have
|
|
a look at this.
|
|
|
|
<item>
|
|
|
|
The <em/XDMCP HOWTO/ (<htmlurl
|
|
url="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/XDMCP.html"
|
|
name="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/XDMCP.html">).
|
|
This document describes the steps necessary to set up xdm for use
|
|
with remote X servers, such as from X terminals. The setup of the
|
|
X server in such a situation is described less extensively.
|
|
|
|
<item>
|
|
|
|
The <em/Xterminal mini-HOWTO/ (<htmlurl
|
|
url="http://metalab.unc.edu/pub/Linux/docs/HOWTO/unmaintained/mini/Xterminal"
|
|
name="http://metalab.unc.edu/pub/Linux/docs/HOWTO/unmaintained/mini/Xterminal">).
|
|
It is currently unmaintained, but it might contain some useful
|
|
information for you.
|
|
|
|
</itemize>
|
|
|
|
<p>
|
|
Contrasted to the above documents, this document (the Remote X Apps
|
|
mini-HOWTO) limits itself to a short description of XDMCP, but puts more
|
|
emphasis on the security issues involved.
|
|
|
|
<sect1> Once More, a Little Theory First
|
|
|
|
<p>
|
|
As far as X is concerned, the X terminal will be running nothing but an
|
|
X server. This X server will be configured to talk to a remote host
|
|
using XDMCP (the X Display Manager Control Protocol). It will ask
|
|
the remote host for an X session. The remote host will put up a login
|
|
window on the X terminal, and after login it will run an X session with
|
|
all bells and whistles, including the window manager, all using remote
|
|
X to display on the X terminal.
|
|
|
|
<p>
|
|
You will probably notice that the remote host is acting like a server,
|
|
though not an X server. The remote host is providing X sessions to X
|
|
servers that ask for one. So, with respect to XDMCP, the remote host is
|
|
actually a server, providing X sessions, also known as an XDMCP server.
|
|
The X server is playing the role of an XDMCP client! Are you still
|
|
with me?
|
|
|
|
<p>
|
|
The program that provides the XDMCP service on the XDMCP server is
|
|
<tt/xdm/. So, in order to get an X terminal up and running, you must
|
|
configure two programs: <tt/X/ (the XDMCP client) on the X terminal,
|
|
and xdm (the XDMCP server) on the remote host.
|
|
|
|
<p>
|
|
You must always remember that the X protocol (and the XDMCP protocol)
|
|
are not encrypted. If you use remote X, everything that goes over the
|
|
network can be sniffed by other hosts on the network. This is especially
|
|
bad with remote X sessions, since the first thing that happens is logging
|
|
in by giving a username and password. So, you must run remote X over
|
|
a trusted network only!
|
|
|
|
<sect1> Configuring <tt/X/ as an XDMCP Client
|
|
|
|
<p>
|
|
If you want to set up a Linux machine as an X terminal, you need very
|
|
few resources. Basically, you need what it takes to get a bare bones
|
|
Linux machine running, plus an X server. Specifically, you do <em/not/
|
|
need the X clients and libraries. It can be useful to install some X
|
|
fonts, but you can also use a font server somewhere on the network.
|
|
|
|
<p>
|
|
There are a few ways for an X server to get an X session from an XDMCP
|
|
server. The simplest one is to go straight to a known XDMCP server and
|
|
ask for one. Alternatively, the X server can broadcast a request for
|
|
an XDMCP service and use the first XDMCP server that responds. Lastly,
|
|
the X server can go to an XDMCP server, ask it for a list of hosts
|
|
willing to provide a session, and let the user choose a session host.
|
|
|
|
<enum>
|
|
|
|
<item>
|
|
When you know the host that is going to provide you with sessions,
|
|
go straight to it. Run
|
|
<tscreen><verb>
|
|
X -query sessionhost
|
|
</verb></tscreen>
|
|
and, assuming <tt/xdm/ is running on <tt/sessionhost/, you'll get a
|
|
login window, and after login, an X session.
|
|
|
|
<item>
|
|
When you don't really care on which host you're getting your session,
|
|
use the broadcast method. Run
|
|
<tscreen><verb>
|
|
X -broadcast
|
|
</verb></tscreen>
|
|
and, assuming <tt/xdm/ is running somewhere on the network, you'll get
|
|
a login window from the first (and hopefully quickest) <tt/xdm/ that
|
|
responds, and after login, an X session.
|
|
|
|
<item>
|
|
When you want to choose the host where you want to have your session,
|
|
ask an XDMCP server for a list. Run
|
|
<tscreen><verb>
|
|
X -indirect xdmcpserver
|
|
</verb></tscreen>
|
|
and, assuming <tt/xdm/ is configured right there, you'll be presented a
|
|
list of hosts to choose from. Choose one; you'll get the login window
|
|
for that host, and after login, the session you were looking for.
|
|
|
|
</enum>
|
|
|
|
<p>
|
|
You may have noticed the absence of the <tt/-auth/ option. The X
|
|
server will use XDMCP to negotiate a magic cookie with the XDMCP server.
|
|
The XDMCP server will put the cookie in your remote <tt>~/.Xauthority</tt>
|
|
after login.
|
|
|
|
<p>
|
|
After a session is over, the X server will loop and go back to the
|
|
original XDMCP server and ask for another session (or chooser list).
|
|
If you don't want that, you can use the <tt/-once/ option. Note:
|
|
this doesn't seem to work with the <tt/-indirect/ option due to the
|
|
implementation of the chooser.
|
|
|
|
<p>
|
|
When you have determined the way in which you want to run the
|
|
X server, you can also put it in a startup script, or even run
|
|
it straight from <tt>/etc/inittab</tt>. Please consult your own
|
|
distribution's documentation for how to modify your startup scripts
|
|
or <tt>/etc/inittab</tt>.
|
|
|
|
<p>
|
|
Do <em/not/ run an X server like this from the <tt/Xservers/ configuration
|
|
file. <tt/xdm/ expects to be able to connect to such servers, and may
|
|
kill them if it can't connect.
|
|
|
|
<sect1> Configuring <tt/xdm/ as an XDMCP Server
|
|
|
|
<p>
|
|
The program that provides the XDMCP service (the session service) is
|
|
usually <tt/xdm/. There are variants of this such as <tt/wdm/ or <tt/gdm/
|
|
on Linux, but these basically work the same way. So, make sure <tt/xdm/
|
|
or variant is installed on the host where you want to run your X sessions.
|
|
If you've got a local graphical login on the X session host, <tt/xdm/
|
|
is already installed; most Linux distributions come that way these days.
|
|
|
|
<p>
|
|
In addition to <tt/xdm/, you will need the programs that you wish to be
|
|
able to run in an X session. That is, all X clients like <tt/xterm/,
|
|
<tt/xfig/, <tt/xclock/, window managers and all that. However, for an
|
|
XDMCP server, you do <em/not/ have to install an X server; the X server
|
|
will be running on the X terminal instead.
|
|
|
|
<p>
|
|
From the X server story above, you can conclude that there are
|
|
basically two kinds of XDMCP service. There is the <em/direct/ service,
|
|
consisting of letting an XDMCP client log in, and then providing it
|
|
with an X session. Alternatively, there is the <em/indirect/ service,
|
|
in which an XDMCP client is provided with a list of hosts, providing a
|
|
direct service, to choose from.
|
|
|
|
<p>
|
|
All <tt/xdm/ services are configured in the access file, generally
|
|
located at <tt>/etc/X11/xdm/Xaccess</tt> or a similar location. This
|
|
location is actually defined in the general <tt/xdm/ configuration file
|
|
<tt>/etc/X11/xdm/xdm-config</tt>, through the <tt/accessFile/ resource.
|
|
See your <tt/xdm/ manual for the default location.
|
|
|
|
<enum>
|
|
|
|
<item>
|
|
<p>
|
|
If you want to allow <tt/xdm/ to provide connecting XDMCP clients with an
|
|
X session, whether by broadcast or not, you put the host name of the XDMCP
|
|
client (the X server, remember?) by itself on a line in <tt/Xaccess/.
|
|
Actually, you can put a pattern on the line matching multiple hosts.
|
|
Here are some valid patterns:
|
|
<tscreen><verb>
|
|
xterm023.my.domain # xterm023.my.domain can get an X session
|
|
*.my.domain # any host in my.domain can get an X session
|
|
* # any host on Internet can get an X session (unsafe)
|
|
</verb></tscreen>
|
|
|
|
<p>
|
|
Whether you should want to provide any host in Internet with an X
|
|
session is arguable. Obviously, any service you provide is one more
|
|
possible hole in your server's security. On the other hand, the server
|
|
should be secure itself, and an XDMCP client asking for an X session
|
|
has to provide a valid authentication before the X session is granted.
|
|
|
|
<p>
|
|
Furthermore, the X session uses a remote X connection, which is
|
|
not encrypted. The username/password pair for the login will be
|
|
transported on this connection. People out there could be sniffing valid
|
|
username/password combinations, just as with plain telnet connections.
|
|
This is even worse then having xauth magic cookies sniffed.
|
|
|
|
<p>
|
|
Make your own decisions here, but I recommend not enabling this service
|
|
to the world unless you have a good reason.
|
|
|
|
<item>
|
|
<p>
|
|
If you want to provide XDMCP clients (<tt/X -indirect xdmcpserver/) with a
|
|
chooser list (a list of hosts to choose from to get an X session), follow
|
|
the client pattern with the keyword <tt/CHOOSER/ and the list of hosts
|
|
that that client may choose from. Instead of the list of hosts to choose
|
|
from, you can also specify <tt/BROADCAST/; with this, <tt/xdm/ broadcasts
|
|
on the network to query for servers willing to provide the session. Some valid examples:
|
|
<tscreen><verb>
|
|
xterm023.my.domain CHOOSER seshost1 seshost2
|
|
*.my.domain CHOOSER BROADCAST
|
|
* CHOOSER extseshost1 extseshost2
|
|
</verb></tscreen>
|
|
The first lets <tt/xterm023/ choose between sessions on either
|
|
<tt/seshost1/ and <tt/seshost2/. The second lets any host in
|
|
<tt/my.domain/ choose from any host that is willing to provide an
|
|
X session. The third lets any host out there choose between a session
|
|
on <tt/extseshost1/ or <tt/etsseshost2/.
|
|
|
|
<p>
|
|
It is probably not a good idea to do <tt/* CHOOSER BROADCAST/. This will
|
|
allow hosts outside your network to get information about the hosts inside
|
|
your network. You probably don't want to pass out such information.
|
|
In fact, allowing a chooser to any outside host is probably not useful
|
|
anyway, since you should not be enabling arbitrary direct connections
|
|
either.
|
|
|
|
</enum>
|
|
|
|
<p>
|
|
When you have reconfigured <tt/xdm/, send it the <tt/HUP/ signal to make
|
|
it re-read its configuration files.
|
|
<tscreen><verb>
|
|
# kill -HUP pid-of-xdm
|
|
#
|
|
</verb></tscreen>
|
|
|
|
<sect1> XDMCP Technically
|
|
|
|
<p>
|
|
Technically, as far as I can see, XDMCP is not entirely what you would
|
|
expect from the above description. <tt/xdm/ can redirect connecting X
|
|
servers to another place, and uses this trick to implement the chooser.
|
|
So, the choosing happens inside xdm, not in the X server, although the
|
|
chooser list is represented on the X server's display. This is also
|
|
why the X server's <tt/-once/ option does not combine with <tt/-indirect/.
|
|
|
|
<sect> Troubleshooting
|
|
|
|
<p>
|
|
The first time you try to run a remote X application, it usually does
|
|
not work. Here are a few common error messages, their probable causes,
|
|
and solutions to help you on your way.
|
|
|
|
<tscreen><verb>
|
|
xterm Xt error: Can't open display:
|
|
</verb></tscreen>
|
|
|
|
There is no <tt/DISPLAY/ variable in the environment, and you didn't
|
|
tell the application with the <tt/-display/ flag either. The application
|
|
assumes the empty string, but that is syntactically invalid. To solve
|
|
this, be sure that you set the <tt/DISPLAY/ variable correctly in the
|
|
environment (with <tt/setenv/ or <tt/export/ depending on your shell).
|
|
|
|
<tscreen><verb>
|
|
_X11TransSocketINETConnect: Can't connect: errno = 101
|
|
xterm Xt error: Can't open display: love.dial.xs4all.nl:0
|
|
</verb></tscreen>
|
|
|
|
Errno 101 is ``Network is unreachable''. The application could not make
|
|
a network connection to the server. Check that you have the correct
|
|
<tt/DISPLAY/ set, and that the server machine is reachable from your
|
|
client (it should be, after all you're probably logged in to the server
|
|
and telnetting to the client).
|
|
|
|
<tscreen><verb>
|
|
_X11TransSocketINETConnect: Can't connect: errno = 111
|
|
xterm Xt error: Can't open display: love.dial.xs4all.nl:0
|
|
</verb></tscreen>
|
|
|
|
Errno 111 is ``Connection refused''. The server machine you're trying
|
|
to connect to is reachable, but the indicated server does not exist
|
|
there. Check that you are using the right host name and the right
|
|
display number.
|
|
|
|
Alternatively, it is possible that the X server was configured <em/not/
|
|
to listen to the usual TCP port. To find out if this is the case,
|
|
see if the X server is started with the <tt/-nolisten tcp/ argument,
|
|
and if so, remove it.
|
|
|
|
<tscreen><verb>
|
|
Xlib: connection to ":0.0" refused by server
|
|
Xlib: Client is not authorized to connect to Server
|
|
xterm Xt error: Can't open display: love.dial.xs4all.nl:0.0
|
|
</verb></tscreen>
|
|
|
|
The client could make a connection to the server, but the server does
|
|
not allow the client to use it (not authorized). Make sure that you have
|
|
transported the correct magic cookie to the client, and that it has not
|
|
expired (the server uses a new cookie when a new session starts).
|
|
|
|
</article>
|