TigerVNC - Arch Linux 中文维基

跳至內容

# TigerVNC

出自 Arch Linux 中文维基
翻譯狀態：

- 本文（或部分內容）譯自 TigerVNC，最近一次同步於 2021-06-13，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

相關文章

- x11vnc

TigerVNC 是 Virtual Network Computing (VNC) 協議的一種實現。本文著重介紹服務端的功能。

## 安裝

安裝 tigervnc包 軟體包。

## 為虛擬（無界面）會話運行 vncserver

### 初始設置

注意：在內存允許的條件下，Linux 系統可以啟動任意數量的 VNC 服務端，它們同時並行運行，互不干擾。

簡易教程如下。推薦用戶閱讀 vncserver 的 man 手冊來了解所有的配置項。

1. 用 `vncpasswd` 創建密碼，它會將哈希處理之後的密碼存儲在 `$XDG_CONFIG_HOME/tigervnc/config`。
2. 編輯 `/etc/tigervnc/vncserver.users` 來定義用戶映射。該文件中定義的每個用戶都會擁有對應的埠來運行會話。該文件中的數字對應的是 TCP 埠。默認情況下，:1 是 TCP 埠 5901 (5900+1)。如果需要運行一個並行的服務端，第二個實例可以運行在下一個最大的、未被占用的埠，即 5902 (5900+2)。
3. 創建 `$XDG_CONFIG_HOME/tigervnc/config`，其中至少要有一行定義會話的類型，比如 `session=foo` （將foo替換為你想要運行的桌面環境）。你可以通過查看 `/usr/share/xsessions/` 裡的 `.desktop` 文件來知道有哪些桌面環境在當前系統上可以使用。

文件內容舉例：

    $XDG_CONFIG_HOME/tigervnc/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

#### 通過系統服務啟動

該選項允許用戶訪問當前顯示界面，包括由顯示管理器提供的登錄界面。

該服務將在用戶退出會話後自動重新啟動。

下面的例子使用了LightDM，但可以通過修改 `XAUTHORITY` 變量來將其適用於其他顯示管理器。

    /etc/systemd/system/x0vncserver.service

    [Unit]
    Description=Remote desktop service (VNC) for :0 display
    Requires=display-manager.service
    After=network-online.target
    After=display-manager.service

    [Service]
    Type=simple
    Environment=HOME=/root
    Environment=XAUTHORITY=/var/run/lightdm/root/:0
    ExecStart=x0vncserver -display :0 -rfbauth $XDG_CONFIG_HOME/tigervnc/passwd
    Restart=on-failure
    RestartSec=500ms

    [Install]
    WantedBy=multi-user.target

這是一個 system unit, `-rfbauth $XDG_CONFIG_HOME/tigervnc/passwd` 指向 `/root/.vnc/passwd`

Start/enable `x0vncserver.service`.

#### 通過用戶服務啟動

對大多數用戶來說，快速遠程訪問當前桌面的最簡單方法是運行 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

警告：TigerVNC 默認的連接方式不安全，它缺乏身份驗證，且在連接建立過程中無法防止中間人攻擊。請確保知曉當前伺服器的安全設置，並且不要以不安全的方式連接到可信網絡之外的 vncserver。
注意：TigerVNC 默認使用 TLSVnc 作為驗證和加密方式，也可以用 `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)

### 圖形界面客戶端示例

- gtk-vnc包
- krdc包
- vinagre包
- remmina
- virt-viewer包
- vncviewer-jarAUR

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 服務端，可以進行以下設置：

1. 伺服器運行 SSH
2. 伺服器運行 vncserver（帶有 `-localhost` 標誌以確保安全）
3. Android 設備上的 SSH 客戶端：ConnectBot 是一個流行的選擇，本例中將使用它
4. 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

    $ sudoedit /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

## 另外參見

- https://github.com/TigerVNC/tigervnc

分類：​

- 遠程伺服器
- 伺服器
- 包含失效連結的頁面

TigerVNC
新增話題