My understanding about X11 was wrong
https://en.wikipedia.org/wiki/X_Window_System

My understanding about X11 was wrong

Recently worked on X11 issues both personally and at work. I had faced X11 display errors in the past and fixed them but didn't get a chance to understand X11 architecture in-depth.?

But this time, I wanted to understand why I was executing particular X11 command mentioned in multiple articles about X11 display issues. After spending a couple of days, I gained a basic understanding of X11. I plan to share my basic knowledge about X11 in this article.?

Note:- I am no expert on the X11 application. There might be some mistakes in my understanding. All the X11 commands have been executed only on Amazon Linux 2 and Mac OS, So few commands might not work on other operating systems.

What is X11?

The X Window System is software that helps to display text and graphics. It can show the GUI application over the network. 'X' Windows System is cross-platform and runs on multiple OS. The 'X' protocol is a display server protocol. It helps communication between the 'X' client and the 'X' server. X11 means version 11, which is the 'X' protocol version.

X Window System Architecture

No alt text provided for this image

[1]

No alt text provided for this image

[2]

What is the DISPLAY variable, and why is it needed?

'DISPLAY' variable beautifully informs the 'X' client where the 'display server' or 'X' server is running. 'X' server is the one that interacts with Kernel and hardware and displays the GUI.

Format of 'DISPLAY' variable is '<hostname>:<displaynumber>.<screen number>

Hostname: refers to the server which displays the GUI. Default value 'localhost.'

Display number:??Each X Server that is running gets a number. The default value is 0. By default 'X' server starts on port '6000', and this value is added to '6000' to get the 'X' server port. For example, if the display number value is '0', 'X' server runs on port 6000. If the display number is '10', 'X' server runs on port 6010.

Screen Number:?It tells which physical monitor to display the GUI. Default value is '0'. Allows moving GUI across all the physical monitors. If the value is '1' displays GUI on physical monitor 1.

Few examples

export DISPLAY=:0 means "X Server is running on localhost on port 6000".

export DISPLAY=:10.0 means "X Server is running on localhost on port 6010."

export DISPLAY=192.168.1.230:10.0 means "X Server is running on the server 192.168.1.230 on port 6010."

X Server Authorization

'X' server will not accept connections from just anywhere. We can authorize 'X' clients with the below methods.

1) xhost?allows authorization based on hostnames. This setting is applied at the server level. The server maintains a list of servers(X Clients) allowed to connect. We can also disable host checking entirely, which means any host can connect 'X' server but this is a huge security risk.

It is better to choose 'ssh' or 'xauth' authorization for security risks with 'xhost' authorization.?

Example:

xhost +1.2.3.4 # allows 'X' client from 1.2.3.4

2) xauth?allows access to anyone who has the 'MIT-MAGIC-COOKIE-1'. The ~/.Xauthority file stores the cookie. The 'X' client presents the cookie to the 'X' server, and I guess the 'X' server matches the client cookie with the cookie it has. If the cookies don't match, the 'X' Server will reject the connection from the 'X' Client and throws an 'authentication' error.

commands:

xauth list # lists the authorization entries for each specified display

xauth generate #generates authorization token and adds to 'X' server.

xauth add # adds the authorization entry to ~/.Xauthority file.

3) ssh?allows X11 forwarding over an encrypted connection. To display over SSH, we need to turn on 'ForwardX11' on 'sshd' daemon and connect using the '-X' option using 'ssh.'

sudo cat /etc/ssh/sshd_config | grep -i X11 | grep -v '#'

X11Forwarding yes

ssh -X -i <private_key> ec2-user@<server>

Examples

1) ssh(Amazon Linux 2)

This example shows the 'X' server and 'X' client setup using 'ssh.' In this example, the 'X' server and 'X' client runs on the remote server, and X11 packets are forwarded to the laptop over an encrypted SSH connection.

Prerequisites

1) Make sure 'X11Forwarding' is enabled on 'sshd'.

sudo cat /etc/ssh/sshd_config | grep -i X11 | grep -v '#'

2) Install 'xauth' package. This package contains 'xauth'.

sudo yum install xorg-x11-xauth -y

3) Install 'xorg-x11-apps'. This package contain 'X' client tools.

sudo yum install xorg-x11-apps -y?

4) Install 'xorg-x11-utils'. This package contain 'X' utilities like 'xdpyinfo'.

sudo yum install xorg-x11-utils -y
        

ssh

ssh -X -i <private_key> <user>@<server>
$ echo $DISPLAY
localhost:10.0
$ sudo netstat -anp | grep -i 6010
$ xauth list
$ xeyes # opens the GUI.
        

What's happening in the background?

Without the ' X ' option, let's connect to the remote server using 'ssh.'

1) DISPLAY variable is empty.
$echo $DISPLAY

2) 'X' server is not running.
$sudo netstat -anp | egrep -i '6000|6010'

3) 'X' client will not work.
xeyes
Error: Can't open display:?
        

Now let's connect to the remote server using 'ssh' using the '-X' option.

When we launch the 'ssh' connection using the '-X' option, 'sshd' daemon starts proxy 'X' server, updates '~/.Xauthority' file with 'MAGIC COOKIE' and sets the DISPLAY variable to the 'X' server.

1) 'sshd' daemon starts the proxy 'X' server.
$sudo netstat -anp | egrep -i '6000|6010' | grep -i '\<tcp\>' | grep -i LISTEN
tcp? ? ? ? 0? ? ? 0 127.0.0.1:6010? ? ? ? ? 0.0.0.0:*? ? ? ? ? ? ? ?LISTEN? ? ? 30924/sshd: ec2-use?

2) Updates ~/.Xauthority file with MAGIC COOKIE
$ cat ~/.Xauthority
$ xauth list

3) Sets the DISPLAY variable.
$ echo $DISPLAY
localhost:10.0

4) 'X' client tools work now. For example 'xeyes'.
$ xeyes

        

2) xhost(Mac OSX)

In this example, we run the 'JMeter' docker container which runs JMeter GUI('X' Client) and this 'X' client connects to the 'X' Server which is the 'XQuartz' server running on Mac OSX.

Prerequisites

1) Install 'XQuartz' which is 'X' server for Mac OSX.

brew install --cask xquartz

2) Open 'xquartz'. This starts the 'X' server and sets the DISPLAY variable. Also we can see 'X' server running on port 6000.

$ netstat -an | grep -i 6000 | grep -i tcp4 | grep -i LISTEN
tcp4 ? ? ? 0? ? ? 0? *.6000 ? ? ? ? ? ? ? ? *.*? ? ? ? ? ? ? ? ? ? LISTEN 
$ echo $DISPLAY

        

xhost

1) Now we will use 'xhost' authorization to allow 'X' clients to connect to 'X' server

2) ip=$(ifconfig en0 | grep -i '\<inet\>' | cut -d " " -f2)

3) Before 'xhost' authorization, we get below error, even though 'DISPLAY' variable is set by 'XQuartz' server.
$ docker run -e DISPLAY=$ip:0.0 docker.io/justb4/jmeter:5.4
An error occurred: Can't connect to X11 window server using '192.1.1.40:0.0' as the value of the DISPLAY variable.

4) Enable 'xhost' authorization
xhost +$ip

192.1.1.40 being added to access control list

5) Now run the docker container again. It will display the JMeter GUI.

docker run -e DISPLAY=$ip:0.0 docker.io/justb4/jmeter:5.4
        

What's happening in the background?

In this scenario, 'X Client' is 'JMeter' GUI. And we set the DISPLAY to the 'X' Server, the 'XQuartz' server.

Let's try to run the JMeter container without the 'X' Server(XQuartz Server). The 'X' Client cannot display the GUI because the 'X' Server is not running.

1) Lets run the JMeter docker container.
$ ip=$(ifconfig en0 | grep -i '\<inet\>' | cut -d " " -f2)
$ docker run -e DISPLAY=$ip:0.0 docker.io/justb4/jmeter:5.4?

2) Docker container throws below error.
An error occurred: Can't connect to X11 window server using '192.1.1.40:0.0' as the value of the DISPLAY variable.

3) Above error means 'XClient'(JMeter GUI) is trying to connect to the 'X' server running at '192.1.1.40' on port '6000'.

4) We can confirm nothing is running on port '6000'
$ netstat -an | egrep -i '6000|6010' | grep -i LISTEN
        

'X' Client is not working with Sudo

Let's suppose we ssh into the remote server using the 'ec2-user' with the '-X' option. 'ec2-user' will not have any issues displaying 'X' Client tools like 'xeyes' because 'sshd' daemon sets 'X' Server authorization using 'xauth' in the file '~/.Xauthority'.

But the '~/.Xauthority' file is created in the user home directory, and this home directory changes when we 'sudo'. Also, the DISPLAY variable is unavailable when we 'sudo' to another user. Due to these reasons, 'X,' Client applications don't work when we 'sudo'.

How to fix 'sudo' issue

We can fix this issue using the below solution. In the below example let's suppose we try to 'sudo' to 'ssm-user'.

# Below command updates sudo user ~/.Xauthority with MAGIC Cookie
$echo "xauth add $(xauth list | grep unix$(echo $DISPLAY | cut -c10-12))" | sudo su - ssm-user

# Below command sets the DISPLAY variable for the sudo user.
$sudo -Eu ssm-user bash -c 'echo export DISPLAY=$DISPLAY >> ~/.bash_profile'

# We can see 'MAGIC COOKIE' of sudo user 'ssm-user' and original user 'ec2-user' is same. If the 'MAGIC COOKIE' is different, we will get authentication error because the cookies of 'X' Server and 'X' Client doesn't match.
$xauth list        

Note:- The above commands need to be executed every time we log in using 'ssh -X' because 'MAGIC COOKIE' is changed by 'sshd' every time. This process can be automated using ec2 'user data', which updates the login user profile.

Important utilities/tools

  • xdpyinfo : displays 'X' Server information. We can find where the 'X' server is running and set the DISPLAY variable based on that. For example

$xdpyinfo | grep -i 'name of display'        

  • xlsclients: lists the client's application running on the display server.

$xlsclients        

Conclusion

Before this journey of understanding how the 'X' Windows system works, I was always under the impression that the 'X' Server runs on the remote server and the 'X' client is a local machine. But I was wrong. Recent issues helped me understand how the 'X' Windows system works. No more random copy and paste of DISPLAY variable.

References

  1. https://learning.lpi.org/en/learning-materials/102-500/106/106.1/106.1_01/
  2. https://unix.stackexchange.com/questions/345344/difference-between-xorg-and-gnome-kde-xfce
  3. https://techviewleo.com/install-and-configure-x11-server-on-linux/
  4. https://www.x.org/wiki/
  5. https://www.biac.duke.edu/library/documentation/xwin32/security.html
  6. https://tldp.org/HOWTO/Remote-X-Apps-1.html
  7. https://aws.amazon.com/blogs/compute/how-to-enable-x11-forwarding-from-red-hat-enterprise-linux-rhel-amazon-linux-suse-linux-ubuntu-server-to-support-gui-based-installations-from-amazon-ec2/
  8. https://docstore.mik.ua/orelly/networking_2ndEd/ssh/ch09_03.htm
  9. https://en.wikipedia.org/wiki/X_Window_System

要查看或添加评论,请登录

Vijay Bheemineni的更多文章

  • Simplify Automation for Startups and Small Teams Using CfCT - Part 4/4(Final)

    Simplify Automation for Startups and Small Teams Using CfCT - Part 4/4(Final)

    In the previous article (Part 3 of this series), we explored implementing custom solutions using CfCT. In this final…

    1 条评论
  • Simplify Automation for Startups and Small Teams Using CfCT - Part 3/4

    Simplify Automation for Startups and Small Teams Using CfCT - Part 3/4

    In the previous article (Part 2 of this series), we discussed the process of setting up CfCT. In this article, we will…

  • Simplify Automation for Startups and Small Teams Using CfCT - Part 2/4

    Simplify Automation for Startups and Small Teams Using CfCT - Part 2/4

    In the previous article (Part 1 of this series), we explored the Customizations for Control Tower (CfCT) solution and…

    1 条评论
  • Simplify Automation for Startups and Small Teams Using CfCT - Part 1/4

    Simplify Automation for Startups and Small Teams Using CfCT - Part 1/4

    Startups and small teams often operate under tight constraints, balancing limited resources, restricted budgets, and…

    1 条评论
  • ACM Certificate Expiring Notification

    ACM Certificate Expiring Notification

    When a client's SSL/TLS certificate expires, several critical issues can arise, negatively impacting their services and…

  • DNSSEC-Part3(Route53)(Final)

    DNSSEC-Part3(Route53)(Final)

    In the last two articles, I discussed how DNSSEC works and how to validate DNSSEC. In this final article of the DNSSEC…

  • DNSSEC-Part2

    DNSSEC-Part2

    In the last article, I discussed DNSSEC implementation. This article discusses my interpretation of how DNSSEC works.

  • DNSSEC :- Part 1

    DNSSEC :- Part 1

    I knew 'DNSSEC' is important and why it's required. But I never got a chance to understand in depth or implement it.

  • AWS and OnPrem DNS Resolving

    AWS and OnPrem DNS Resolving

    Recently one of our customers had a requirement to resolve the 'Private' domain from AWS VPC and vice versa. This…

    1 条评论
  • AWS Site-to-Site VPN Series(Final)

    AWS Site-to-Site VPN Series(Final)

    In this final article of 'AWS Site-to-Site VPN Series,' we will implement 'Site-to-Site' VPN in AWS. For Demo purposes,…

    1 条评论

社区洞察

其他会员也浏览了