X-Window结构分析与应用
X-Window結構分析與應用
- X-Window結構分析與應用
- 簡介
- 結構
- 組件
- X-Client
- X-Server
- Linux下的X-Server
- MacOS Windows
- X-Window-Manager
- X-Security
- 基于IP驗證
- 基于預共享密鑰驗證
- 協議
- NAT-sensitiveNAT敏感
- 結合SSH隧道運行遠端GUI應用
- 應用案例
- 本地MAC端運行遠端GUI應用
- 本地Ubuntu端運行遠端GUI應用
- 本地Windows端運行遠端GUI應用
簡介
*nix系統的圖形交互使用的是x-window系統. 基于C/S架構,即可完全運行在本地,也可以讓本端運行的GUI應用在遠端上進行交互(在遠端上顯示GUI 和 接收遠端上的鍵盤鼠標輸入).
結構
組件
X-Client
- X-Client就是GUI應用程序(如:xclock,xterm,firefox,…)
- Linux下GUI應用程序大多是通過庫Xlib(libX11)與X-Server通信
- X-Client自身不直接輸出圖形到屏幕或直接讀取鍵盤輸入,這些與外設的通信都由X-Server來處理
GUI應用程序通過加載Xlib,連接到X-Server建立通信通道,最終通過這通道將顯示需求發送到X-Server上 或 從這通道上接收用戶的鍵盤鼠標輸入, 從而實現GUI交互
每個終端可以配置使用指定的X-Server, 由終端當前的環境變量’DISPLAY’指定.DISPLAY字符串的格式如下:
[host]:[displayer-id].[screen-id]意思為: 哪個主機上的哪個顯示器上的哪個屏幕
其中[host]和[screen-id]可省略.host省略意為本機,screen-id省略為默認的屏幕.如:
# 本終端環境使用本地ID為0的顯示器的默認屏幕作為X-Server export DISPLAY=:0 # 使用主機(10.0.66.238)上ID為1的顯示器的ID為0的屏幕 export DISPLAY=10.0.66.238:1.0X-Server
- 顧名思義是X-Client們的服務端
- 負責與輸入輸出設備通信
- Linux上通常使用的實現為 Xorg
- MacOS上可使用 XQuartz
- Windows上可使用 Xmanager 或 Xming
負責將X-Client請求顯示的圖形顯示到屏幕上 和 將鍵盤鼠標的輸入事件發送到相應的X-Client上.
Linux下的X-Server
以ubuntu17為例,若安裝了桌面環境,即GNOME,則已經完全具備X-Server的服務能力(基于Xorg-server). 這完整的桌面環境不止X-Server,還包括一系列的X-Client應用程序(任務欄,文件夾管理器…)和X-Window-Manager等等.
但默認的情況下,該X-Server只提供給本地的X-Client使用,沒開啟TCP的對外服務渠道,只開啟了基于unix-socket的進程間通信的服務渠道.
開啟TCP方式則需要修改配置文件:/etc/gdm3/custom.conf
[security] DisallowTCP=false開放給遠端使用時可能會遇到X-Auth驗證失敗 或 NAT環境下不可用的情況,在后面的小節進行說明
下圖為GNOME桌面環境下, 終端默認使用了當前GNOME桌面所在的X-Server(Displayer1), 當執行X-Client(GUI應用xclock)時就把他顯示在當前GNOME桌面里了
當然也可以手動再開啟一個純凈的X-Server,如接下來這小節所示
先確認已安裝X-Server:
rock@ubuntu17:~$ sudo apt-get xorg手動開啟一個新的X-Server(Xorg為例):
## ':1'表示該X-Server標識為ID為2的Displayer ## Displayer1顯示在tty5 ## '-listen tcp'顯式表示要使用tcp方式 ## '-retro'表示背景為斜紋,不然默認為純黑,不好判斷啟動成功與否 rock@ubuntu17:~$ sudo X :2 vt5 -listen tcp -retro此時tty5終端已經成功啟動了X-Server了,顯示如下斜紋背景:
ctrl+alt+F3 切換到其他未使用的終端:
rock@ubuntu17:~$ sudo lsof -nPi tcp|grep X Xorg 3505 root 5u IPv6 37157 0t0 TCP *:6002 (LISTEN) Xorg 3505 root 6u IPv4 37158 0t0 TCP *:6002 (LISTEN)啟動后可以發現tcp6002端口已啟動監聽. 其實X-Server的端口號是從6000開始一一對應Displayer-ID,如:tcp6002對應Displayer2,tcp6010對應Displayer10.
在剛啟動的Displayer2上運行xclock:
rock@ubuntu17:~$ export DISPLAY=:2 rock@ubuntu17:~$ xclock& [1] 4103 rock@ubuntu17:~$ctrl+alt+F5 :
MacOS & Windows
其他操作系統,MacOS上運行XQuartz,Windows上運行Xmanager 即可看到相應的TCP端口開啟了監聽,即已經開啟了X-Server服務
- XQuartz
- Xmanager
X-Window-Manager
單一的X-Server是沒有窗口管理功能的,即多個X-Client窗口會重疊在一塊,無法移動任何一個窗口. X-Window-Manager就是為多窗口管理而生的
- X-Server(xorg) without X-Window-Manager
此時tty5的桌面顯示為下圖所示的倆重疊應用程序窗口, 鼠標無法拖動:
tty5:
- Xorg-server(xorg) with X-Window_Manager(twm)
此時tty5桌面上的倆應用程序窗口已經可以用鼠標自由拖放了:
- 所以現在應該理解了ubuntu上GNOME桌面提供的其中一個服務就是X-Window-Manager了:
- MacOS下XQuartz自身集成了X-Window-Manager
- Windows下XManager自身也集成了X-Window-Manager
X-Security
X-Window系統的’訪問控制(access control)’功能由X-Security來定義,X-Server端可配置基于IP級別的驗證和基于共享key的驗證.
確認當前X-Server的’訪問控制’功能已開啟
xhost配置的是當前終端環境變量DISPLAY所指向的X-Server.所以配置前先確認當前環境變量中的DISPLAY值
rock@rock-ubuntu17:~$ echo $DISPLAY :1 ## 顯示當前訪問控制的狀態,和xhost允許的X-Client的主機來源或用戶 rock@rock-ubuntu17:~$ xhost access control enabled, only authorized clients can connect SI:localuser:rock該輸出表示訪問控制功能已開啟,只允許通過IP驗證 或 通過共享密鑰驗證的才能訪問X-Server服務
## 關閉訪問控制. 不驗證xhost和xauth rock@rock-ubuntu17:~$ xhost + access control disabled, clients can connect from any host ## 開啟訪問控制. 驗證xhost和xauth rock@rock-ubuntu17:~$ xhost - access control enabled, only authorized clients can connect基于IP驗證
- 一個Displayer(X-Server)對應一個xhost列表
- 只需在X-Server端配置
- X-Client請求接入時, X-Server驗證X-Client的IP是否在放行列表中,不在則拒絕接入
- 使用xhost維護
以上設置重啟失效,永久設置需要寫入到對應的配置文件:/etc/X[n].hosts. n為X-Server顯示器ID.即:
/etc/X0.hosts: 配置Displayer0的放行列表
/etc/X1.hosts: 配置Displayer1的放行列表
基于預共享密鑰驗證
- 一個X-Server關聯一個Xauthority文件, 一個Xauthority文件可包含多個Displayer的預共享密鑰. X-Server只使用他所關聯的Xauthority文件里自身Displayer的密鑰記錄
- 需要在X-Server端和X-Client端配置一致的密鑰
- X-Client接入時帶上目標Displayer的密鑰,X-Server驗證該密鑰是否與本地Xauthority文件里配置的一致,不一致則拒絕
- 使用xauth維護
xauth默認配置的是環境變量XAUTHORITY所指向的Xauthority文件或用戶家目錄的.Xauthority(當環境變量’XAUTHORITY’不存在時); 可以用-f參數顯式指定
在X-Server端為Displayer2生成密鑰
rock@rock-ubuntu17:~$ xauth Using authority file /run/user/1000/gdm/Xauthority ## 生成DISPLAY=:2顯示器的共享key, '.'表示使用機制'MIT-MAGIC-COOKIE-1'明文共享密鑰 xauth> generate :2 . authorization id is 572 ## 查看當前顯示器共享key列表 xauth> list rock-ubuntu17/unix:1 MIT-MAGIC-COOKIE-1 5d8f557af058440ef69d6aaa665c91fb rock-ubuntu17/unix:2 MIT-MAGIC-COOKIE-1 578f3bb50f08cd4831277cc4397a2611 xauth> exit Writing authority file /run/user/1000/gdm/Xauthority在X-Client端配置對端Displayer2的密鑰
## 添加目標Displayer的訪問密鑰 root@dld:~# xauth add 10.211.55.5:2 . 578f3bb50f08cd4831277cc4397a2611 ## 配置當前終端使用上步驟的遠端Displayer2 root@dld:~# export DISPLAY=10.211.55.5:2 root@dld:~# xclock如果要編輯指定的Xauthority文件,則:
rock@rock-ubuntu17:~$ xauth -f /root/.XauthorityX-Server執行時可使用’-auth [auth-file]’選項指定使用的Xauthority文件
rock@rock-ubuntu17:~$ sudo X :1 vt5 -auth /run/user/121/gdm/Xauthority協議
NAT-sensitive(NAT敏感)
NAT敏感 通常是因為協議的應用報文中帶有對端的IP信息, 對端在處理應用邏輯里需要依賴這IP信息. 然而對端在NAT環境后面(即做了DNAT, 外網IP映射為內網IP), 本端是不知道你是做了DNAT的, 所以帶的對端的IP是對端的外網IP, 這時對端解釋到的IP信息是外網IP, 但他應用邏輯是用內網IP的, 因此導致應用邏輯上的混亂
X-Server與X-Client之間的遠程通信使用TCP方式, 在實際測試中發現X-Server和X-Client在同一個局域網內才能連接成功, X-Client連接NAT后的X-Server的話是不能成功的. 看來這協議是’NAT敏感’的. 解決方法通常是使用SSH隧道
還有一個內容本文章沒提及, 那就是XDM(X-Display-Manager), 他使用的是XDMCP協議, 走UDP177端口. 以后有機會再補充這塊內容
結合SSH隧道運行遠端GUI應用
為解決剛說的’NAT敏感’問題. 我們常常使用SSH隧道上的端口轉發功能來繞過問題, 其原理圖如下:
遠端上的X-Client應用程序訪問其本地SSH-Server開啟的轉發監聽端口PORT1, SSH-Server將其在Port1在監聽接入的數據通過已經建立好連接的SSH隧道轉發到我們本地的SSH-Client, SSH-Client再將數據轉發到本地X-Server所監聽的TCP端口PORT2
以PORT1為6010, PORT2為6002為例, 其SSH隧道建立及開啟轉發功能的連接命令為:
ssh -R 127.0.0.1:6010:127.0.0.1:6002 user@remotehostssh有個簡潔的-X參數能自動根據環境配置以上轉發參數及遠端SSH終端的DISPLAY環境變量. 可以自行翻閱文檔查看詳情, 這功能需要在SSH-Server開啟’X11 Forwarding’選項
這樣一來就避開了’NAT敏感’的問題, 從X-Client看來他只是訪問本地的X-Server, 從X-Server看來他只是接入本地的X-Client, 所有X層面上看到的IP都是127.0.0.1
同時這個做法避開了X-Security的f遠程主機驗證,因為都認為是本地主機的訪問,只需允許本地訪問即可
應用案例
本地MAC端運行遠端GUI應用
下面演示使用XQuartz結合SSH的’Forwarding’運行遠端GUI
先在本地運行XQuartz:
- 配置允許網絡客戶端接入(開啟使用TCP方式):
- 關閉XQuartz, 重新打開XQuartz. 此時已發現tcp6000端口已經在監聽:
允許本地主機訪問XQuartz. XQuartz默認沒允許本機IP訪問
xhost + 127.0.0.1
用ssh的’-R’選項在SSH會話上開啟隧道端口轉發功能:
意思為將本地XQuartz的X-Server端口tcp6000映射到遠端本地上的tcp6010
root@test:~# ssh -R 127.0.0.1:6010:127.0.0.1:6000 user@remotehost配置遠程終端的DISPLAY環境變量
root@test:~# export DISPLAY=:10如步驟2截圖
執行GUI
root@test:~# xterm& root@test:~# xeyes如步驟2截圖
?
使用X11-Forwarding(即’ssh -X user@host’)操作會比較簡單, 其實他自動做的事的步驟就是以上說的
本地Ubuntu端運行遠端GUI應用
下面演示使用Xorg結合SSH的’Forwarding’運行遠端GUI
先在本地的tty5運行Xorg
當前在tty2:
rock@ubuntu17:~$ sudo X :2 vt5 -listen tcp -retro&tty5:
ctrl+alt+F2回到tty2, 確認已經在本地開啟Displayer2對應是tcp6002監聽:
?
用ssh的’-R’選項在SSH會話上開啟隧道端口轉發功能:
ssh -R 127.0.0.1:6010:127.0.0.1:6002 user@remotehost確認SSH-Server已為我們啟動端口轉發功能:已開啟tcp6010監聽
?
配置遠程終端的DISPLAY環境變量, 執行GUI
配置DISPLAY=:10指向SSH啟動的轉發端口6010:
ctrl+alt+F5 :
最終已轉發到我們本地的6002端口:
使用X11-Forwarding(即’ssh -X user@host’)操作會比較簡單, 其實他自動做的事的步驟就是以上說的
本地Windows端運行遠端GUI應用
下面演示使用Xmanager套件結合SSH的’X11 Forwarding’運行遠端GUI
現在X-Server已啟動, 為Displayer0, 監聽tcp6000
注意: SSH服務端也需要開啟’X11 Forwarding’選項. 不開的話Xshell配置隧道中用’TCP/IP轉移’也行, 原理就是前面所說的
可看到’X11 Forwarding’已經幫我們終端配置好DISPLAY環境變量了
遠端的SSH Server在本地也開啟的相應的tcp6015監聽, 用于隧道上的端口轉發
總結
以上是生活随笔為你收集整理的X-Window结构分析与应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果笔记本怎样设置解除屏保时不需要输入密
- 下一篇: 高可用集群下的负载均衡(5):hapro