TigerVNC
TigerVNC 是 Virtual Network Computing (VNC) 協議的一種實現。本文著重介紹服務端的功能。
安裝[編輯 | 編輯原始碼]
為虛擬(無界面)會話運行 vncserver[編輯 | 編輯原始碼]
初始設置[編輯 | 編輯原始碼]
簡易教程如下。推薦用戶閱讀 vncserver 的 man 手冊來了解所有的配置項。
- 用
vncpasswd
創建密碼,它會將哈希處理之後的密碼存儲在~/.vnc/passwd
。 - 編輯
/etc/tigervnc/vncserver.users
來定義用戶映射。該文件中定義的每個用戶都會擁有對應的埠來運行會話。該文件中的數字對應的是 TCP 埠。默認情況下,:1 是 TCP 埠 5901 (5900+1)。如果需要運行一個並行的服務端,第二個實例可以運行在下一個最大的、未被占用的埠,即 5902 (5900+2)。 - 創建
~/.vnc/config
,其中至少要有一行定義會話的類型,比如session=foo
(將foo替換為你想要運行的桌面環境)。你可以通過查看/usr/share/xsessions/
裡的.desktop
文件來知道有哪些桌面環境在當前系統上可以使用。
文件內容舉例:
~/.vnc/config
session=lxqt geometry=1920x1080 localhost alwaysshared
啟動與停止 tigervnc[編輯 | 編輯原始碼]
start vncserver@.service
,如果需要讓它隨系統啟動,enable 它。注意 /etc/tigervnc/vncserver.users
中定義的編號需要在@符號後面指定,比如啟動:1的命令是:
# systemctl start vncserver@:1
/usr/bin/vncserver
了,因為這樣做不會建立完整可用的會話環境。systemd 服務是唯一受支持的使用 TigerVNC 的方式。參見 Issue #1096。直接轉發本地顯示內容[編輯 | 編輯原始碼]
Tigervnc 帶有 libvnc.so,它可以在 X 初始化過程中直接加載,以提供更好的性能。 創建如下文件並重啟 X:
/etc/X11/xorg.conf.d/10-vnc.conf
Section "Module" Load "vnc" EndSection Section "Screen" Identifier "Screen0" Option "UserPasswdVerifier" "VncAuth" Option "PasswordFile" "/root/.vnc/passwd" EndSection
運行 x0vncserver 來直接控制本地顯示內容[編輯 | 編輯原始碼]
tigervnc包 同時也提供 x0vncserver
,允許直接控制物理 X 會話。在使用 vncpasswd 定義了會話密碼後,請這樣啟動服務端:
$ x0vncserver -rfbauth ~/.vnc/passwd
更多信息請參閱 x0vncserver(1)。
- x11vnc 是另一個可以直接控制當前 X 會話的 VNC 服務端。
x0vncserver
目前不支持客戶端和服務端之間的剪貼板共享(即使有autocutsel
支持也不行)。參閱 Issue #529。
從 xprofile 啟動 x0vncserver[編輯 | 編輯原始碼]
一種啟動 x0vncserver 的簡單方法是在某個 xprofile 文件中添加如下行:
~/.xprofile
... x0vncserver -rfbauth ~/.vnc/passwd &
通過 systemd 啟動與停止 x0vncserver[編輯 | 編輯原始碼]
對大多數用戶來說,快速遠程訪問當前桌面的最簡單方法是運行 x0vncserver 來得到一個 VNC 伺服器。為此可以創建一個 systemd unit,將其中的用戶和選項替換為實際值:
~/.config/systemd/user/x0vncserver.service
[Unit] Description=Remote desktop service (VNC) [Service] Type=simple # wait for Xorg started by ${USER} ExecStartPre=/bin/sh -c 'while ! pgrep -U "$USER" Xorg; do sleep 2; done' ExecStart=/usr/bin/x0vncserver -rfbauth %h/.vnc/passwd # or login with your username & password #ExecStart=/usr/bin/x0vncserver -PAMService=login -PlainUsers=${USER} -SecurityTypes=TLSPlain [Install] WantedBy=default.target
在 systemd用戶服務 模式下 start 並 enable x0vncserver.service
服務,也就是帶上 --user
參數。
使用 XDMCP 為需要的會話運行 Xvnc[編輯 | 編輯原始碼]
可以讓 systemd socket activation 與 XDMCP 結合使用,為每個想登錄的用戶自動生成 VNC 伺服器,這樣無需為每個用戶都準備伺服器或埠。這種方法使用顯示管理器來驗證用戶和登錄,所以也不需要設置 VNC 密碼。這種方法的缺點是會話無法在伺服器上保持運行,退出後無法重新連接到它。
該方法首先需要設置 XDMCP,並確保顯示管理器正在運行。 然後創建:
/etc/systemd/system/xvnc.socket
[Unit] Description=XVNC Server [Socket] ListenStream=5900 Accept=yes [Install] WantedBy=sockets.target
/etc/systemd/system/xvnc@.service
[Unit] Description=XVNC Per-Connection Daemon [Service] ExecStart=-/usr/bin/Xvnc -inetd -query localhost -geometry 1920x1080 -once -SecurityTypes=None User=nobody StandardInput=socket StandardError=syslog
使用 systemctl 來 start 並 enable xvnc.socket
。現在多個用戶同時連接到 5900 埠,均可獲得單獨的桌面。
如果 VNC 伺服器直接暴露在公網,請在 xvnc@.service
裡給 Xvnc
添加 -localhost
選項(注意 -query localhost
和 -localhost
是不同的開關),然後遵循 #通過 SSH 隧道連接到 vncserver。由於我們只在連接後才選擇用戶,所以 VNC 服務端以 nobody 用戶運行,且直接使用了 Xvnc
而不是 vncserver
腳本,所以忽略了 ~/.vnc
中的選項。或者也可以 自動啟動 vncconfig 來打開剪貼板共享(在非 VNC 會話中 vncconfig 將立即退出)。一種自動啟動的方法是創建:
/etc/X11/xinit/xinitrc.d/99-vncconfig.sh
#!/bin/sh vncconfig -nowin &
連接到 vncserver[編輯 | 編輯原始碼]
SecurityTypes
參數來改成其他方式。TLSVnc 意味著標準的 VNC 身份驗證,使用 GNUTLS 加密流量,但不會驗證伺服器的身份。TigerVNC 支持更換其他安全方案,如 X509Vnc,它結合了標準 VNC 身份驗證、GNUTLS 加密、伺服器身份識別,推薦將它用於安全連接。
如果伺服器上的 SecurityTypes
設置了非加密方式(如 None, VncAuth, Plain, TLSNone, TLSPlain, X509None, X509Plain)為高優先級,這樣無法使用加密,是不明智的。運行 vncviewer 時,更安全的方式是明確指定 SecurityTypes
且不接受未加密的流量。其他的模式僅在 #通過 SSH 隧道連接到 vncserver 時使用。連接到 vncserver 的客戶端不限數量。下面是一個簡單的例子,其中 vncserver 運行在 10.1.10.2 的 5901 埠上,埠可以用縮寫 :1 來表示:
$ vncviewer 10.1.10.2:1
無密碼驗證[編輯 | 編輯原始碼]
-passwd
開關允許我們定義伺服器上 ~/.vnc/passwd
文件的位置。用戶在伺服器上必須有權訪問該文件,可以是通過 SSH 訪問,也可以是實體訪問。兩種情況下都應將該文件放在客戶端文件系統的一個安全位置,比如一個僅給期望用戶以讀取權限的位置。
$ vncviewer -passwd /path/to/server-passwd-file
直接提供密碼也是可以的。
ps
的人都可以看到密碼。$ vncviewer -passwd <(echo MYPASSWORD | vncpasswd -f)
圖形界面客戶端示例[編輯 | 編輯原始碼]
TigerVNC 的 vncviewer 也帶有一個簡單的圖形界面,不帶參數運行即可:
$ vncviewer
通過 SSH 隧道連接到 vncserver[編輯 | 編輯原始碼]
對於提供 SSH 的伺服器來說,這種方法有一個優點,除了已經打開的 SSH 埠外不需要再打開其他埠,因為 VNC 流量是在 SSH 隧道中傳輸的。
服務端配置[編輯 | 編輯原始碼]
服務端必須運行 vncserver 或 x0vncserver。
無論運行哪個服務端,都建議在 ~/.vnc/config
添加 localhost
選項或使用 -localhost
開關(適用於 x0vncserver),只允許來自 localhost 的連接,這樣可以確保連接都來自於 ssh 或實體機上認證過的用戶。例如:
~/.vnc/config
session=lxqt geometry=1920x1080 localhost alwaysshared
確保已經 start 或 restart vncserver@.service
。例如(參見 #初始設置):
# systemctl start vncserver@:1
對於 x0vncserver 則是:
$ x0vncserver -localhost -SecurityTypes none
客戶端配置[編輯 | 編輯原始碼]
遠程計算機上的 VNC 服務端已被設置為僅接受本地連接。 現在,客戶端必須與遠程計算機(本例中為 10.1.10.2)建立 SSH 連接,並在客戶端的某個埠(如 9901)和伺服器的 5901 埠之間建立隧道。關於該功能的詳細信息,參見 OpenSSH#Forwarding other ports 和 ssh(1)。
$ ssh 10.1.10.2 -L 9901:localhost:5901
當通過 SSH 建立連接後,請保持該 shell 窗口打開,它現在是與伺服器之間的安全隧道。或者也可以使用 -f
選項直接在後台運行 SSH。客戶端要想通過這一加密隧道連接到服務端,請指定 vncviewer 連接到客戶端 localhost 上的轉發埠。
$ vncviewer localhost:9901
實際上就是 vncviewer 連接到了本地的 9901 埠,而該埠映射到了伺服器本地的 5901 埠。通過 SSH,向正確的埠建立了連接。
$ ssh -fL 9901:localhost:5901 10.1.10.2 sleep 10; vncviewer localhost:9901
上述命令中 -f
選項使 ssh 在後台運行,它將因為 sleep 10
而保持運行。接著運行 vncviewer,在 vncviewer 使用隧道期間,ssh 在後台繼續運行。當隧道不再使用,ssh 將關閉,這正是我們所需要的行為。
另外,vncviewer 的 -via
選項提供了上述命令的快捷方式:
$ vncviewer -via 10.1.10.2 localhost::5901
(注意雙冒號:vncviewer 的語法是 [host]:[display#]
或 [host]::[port]
。)
從 Android 設備通過 SSH 連接到 vncserver[編輯 | 編輯原始碼]
為了用 Android 設備作為客戶端,通過 SSH 連接到 VNC 服務端,可以進行以下設置:
- 伺服器運行 SSH
- 伺服器運行 vncserver(帶有
-localhost
標誌以確保安全) - Android 設備上的 SSH 客戶端:ConnectBot 是一個流行的選擇,本例中將使用它
- Android 設備上的 VNC 客戶端:此處採用 androidVNC
在 ConnectBot 中連接到目標主機。輕點 options 按鈕,選擇 Port Forwards 並添加一個埠:
Type: Local Source port: 5901 Destination: 127.0.0.1:5901
在 androidVNC 中連接到 VNC 埠,即 SSH 連接中設置的本地埠:
Password: the vncserver password Address: 127.0.0.1 Port: 5901
提示和技巧[編輯 | 編輯原始碼]
連接到 OS X 系統[編輯 | 編輯原始碼]
參見 https://help.ubuntu.com/community/AppleRemoteDesktop 。 已在 Remmina 上測試。
推薦的安全設置[編輯 | 編輯原始碼]
#通過 SSH 隧道連接到 vncserver 中,SSH 處理身份驗證和加密,如果沒有採用該方法,則建議用 X509Vnc,因為 TLSVnc 缺乏身份驗證。
$ vncserver -x509key /path/to/key.pem -x509cert /path/to/cert.pem -SecurityTypes X509Vnc :1
頒發 x509 證書超出了本指南的範圍,而 Let's Encrypt 提供了一種簡便方法。也可以使用 OpenSSL 來頒發證書,然後與客戶端共享公鑰並使用 -X509CA
參數指定證書。下面是一個示例(伺服器運行在 10.1.10.2 上):
$ vncviewer 10.1.10.2 -X509CA /path/to/cert.pem
切換全屏[編輯 | 編輯原始碼]
從 VNC 客戶端的菜單可以切換全屏。默認快捷鍵是 F8
。
滑鼠後退和前進按鈕失效的解決方法[編輯 | 編輯原始碼]
VNC 協議目前只支持 7 個滑鼠按鈕(左、中、右、向上滾動、向下滾動、向左滾動、向右滾動),如果滑鼠有後退和前進按鈕,這些按鈕無法使用,按鈕的輸入將被忽略。
在單擊滑鼠後退/前進按鈕時,evrouter 將其改為鍵盤按鍵發送,可以解決此限制。如果需要,可以在伺服器上使用 xautomation包 和 xbindkeys包 中的 xte 將鍵盤按鍵映射回滑鼠單擊。
用鍵盤 XF86Back/XF86Forward 按鍵代替滑鼠後退/前進按鈕[編輯 | 編輯原始碼]
如果只需要在用 Web 瀏覽器或文件瀏覽器時後退/前進,則此方法既簡單又合適。
客戶端安裝 evrouterAUR 和 xautomation包。配置 evrouter,想知道如何查找設備名稱、窗口名稱、按鈕名稱等,請參閱 Mouse buttons#evrouter 和 evrouter 手冊頁。以下是示例配置:
~/.evrouterrc
Window "OtherComputer:0 - TigerVNC": # 篩選窗口標題 # 使用 Shell 防止重複按鍵(參見 evrouter 手冊) "USB mouse" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/275 "Shell/xte 'key XF86Back'" "USB mosue" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/276 "Shell/xte 'key XF86Forward'" # 如果需要重複按鍵,請使用下面的 XKey(參見 evrouter 手冊) #"Logitech Gaming Mouse G400" "/dev/input/by-id/usb-Logitech_Gaming_Mouse_G400-event-mouse" none key/275 "XKey/XF86Back" #"Logitech Gaming Mouse G400" "/dev/input/by-id/usb-Logitech_Gaming_Mouse_G400-event-mouse" none key/276 "XKey/XF86Forward"
客戶端啟動 evrouter。按照上面的配置,點擊滑鼠後退按鈕時,向 VNC 伺服器發送鍵盤按鍵 XF86Back,點擊前進按鈕時發送 XF86Forward。
在服務端將鍵盤按鍵映射回的滑鼠點擊[編輯 | 編輯原始碼]
必要時可以在服務端將鍵盤按鍵映射回滑鼠點擊。此時最好使用客戶端或服務端都不使用的按鍵值。下面的例子將按鍵值 XF86Launch8/XF86Launch9 用作滑鼠按鈕 8/9。
客戶端上的 evrouter 配置:
~/.evrouterrc
Window "OtherComputer:0 - TigerVNC": # 窗口標題 # 使用 Shell 防止重複按鍵(參見 evrouter 手冊) "USB mouse" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/275 "Shell/xte 'key XF86Launch8'" "USB mosue" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/276 "Shell/xte 'key XF86Launch9'"
服務端安裝 xautomation包 和 xbindkeys包。配置 xbindkeys,配置中使用 xte 將鍵盤按鍵 XF86Launch8/XF86Launch9 映射到滑鼠按鈕 8/9。
~/.xbindkeysrc
"xte 'mouseclick 8'" XF86Launch8 "xte 'mouseclick 9'" XF86Launch9
啟用 xbindkeys $ xbindkeys -f ~/.xbindkeysrc
。服務端將 XF86Launch8/XF86Launch9 映射為滑鼠按鈕 8/9。
疑難解答[編輯 | 編輯原始碼]
vncserver 內的終端起始於 / (根目錄)[編輯 | 編輯原始碼]
這是上游引入的已知問題。參閱:https://github.com/TigerVNC/tigervnc/issues/1108
無法輸入 '<' 符號[編輯 | 編輯原始碼]
如果在客戶端上按下 <
卻發送了 >
字符,請嘗試重新映射鍵盤 [1][失效連結 2020-04-03 ⓘ]:
$ x0vncserver -RemapKeys="0x3c->0x2c"
窗口顯示為黑色方框[編輯 | 編輯原始碼]
這種情況很可能是應用程式依賴於 Xorg 的 Composite 擴展。如基於 webkit 的應用程式:midori、psi-plus 等。
這種情況下使用下列命令重啟 vncserver:
$ vncserver -geometry ... -depth 24 :1 +extension Composite
VNC 下的 Composite 擴展僅在 24 位色深時才能正常工作。
沒有滑鼠指針[編輯 | 編輯原始碼]
當使用 x0vncserver
時沒有可見的滑鼠指針,請使用下列命令啟動 vncviewer:
$ vncviewer DotWhenNoCursor=1 <server>
或者將 DotWhenNoCursor=1
寫入 tigervnc 配置文件,配置文件默認存放在 ~/.vnc/default.tigervnc
。
從遠程主機複製剪貼板內容[編輯 | 編輯原始碼]
如果無法從遠程主機複製到本地,請在服務端運行 autocutsel
,如 [2] 中所述:
$ autocutsel -fork
然後按下 F8 打開 VNC 菜單,選擇 Clipboard: local -> remote
選項。
啟動 GNOME 3 時顯示 "Authentication is required to create a color managed device" 對話框[編輯 | 編輯原始碼]
一種解決方法是創建一個 "vnc" 組,將 gdm 用戶和其他使用 vnc 的用戶添加到該組。按如下方式 [3] 修改 /etc/polkit-1/rules.d/gnome-vnc.rules
:
polkit.addRule(function(action, subject) { if ((action.id == "org.freedesktop.color-manager.create-device" || action.id == "org.freedesktop.color-manager.create-profile" || action.id == "org.freedesktop.color-manager.delete-device" || action.id == "org.freedesktop.color-manager.delete-profile" || action.id == "org.freedesktop.color-manager.modify-device" || action.id == "org.freedesktop.color-manager.modify-profile") && subject.isInGroup("vnc")) { return polkit.Result.YES; } });
沒有窗口裝飾/邊框/標題欄/無法移動窗口[編輯 | 編輯原始碼]
啟動一個窗口管理器來修復一個空的 xterm frame。例如在 xfce 上,可在終端中運行 `xfwm4 &`。
按用戶運行 systemd service unit[編輯 | 編輯原始碼]
$ sudo nano /usr/lib/systemd/system/tigervnc@.service
[Unit] Description=Remote desktop service (VNC) After=syslog.target network.target [Service] Type=simple ExecStart=/sbin/runuser -l USERNAME -c "/usr/bin/vncserver %i" [Install] WantedBy=multi-user.target
假設在 display 9 上啟動服務:
$ sudo systemctl start tigervnc@:9
在啟動時運行:
$ sudo systemctl enable tigervnc@:9