TigerVNC
TigerVNC 是虚拟网络计算 (VNC) 协议的实现。本文重点介绍服务器功能。
安装
运行 vncserver 以进行虚拟(无头)会话
初始设置
为了快速开始,请参阅以下步骤。 建议用户阅读 vncserver(8) 以获取完整的配置选项列表。
- 使用
vncpasswd
创建密码,它会将哈希密码存储在$XDG_CONFIG_HOME/tigervnc/passwd
中。 确保文件权限设置为0600
。 如果为另一个用户创建 vncserver 访问权限,则必须先以该用户身份登录,然后再运行 vncpasswd。 - 编辑
/etc/tigervnc/vncserver.users
以定义用户映射。 此文件中定义的每个用户都将有一个对应的端口,其会话将在该端口上运行。 文件中的数字对应于 TCP 端口。 默认情况下,:1 是 TCP 端口 5901 (5900+1)。 如果需要另一个并行服务器,则第二个实例可以在下一个最高的空闲端口上运行,即 5902 (5900+2)。 - 创建
$XDG_CONFIG_HOME/tigervnc/config
,并且至少使用session=foo
这样的行定义所需的会话类型,其中 foo 对应于要运行的桌面环境。 可以通过查看/usr/share/xsessions/
中相应的 .desktop 文件来查看系统上可用的桌面环境。 例如
$XDG_CONFIG_HOME/tigervnc/config
session=lxqt geometry=1920x1080 localhost alwaysshared
启动和停止 tigervnc
启动 vncserver@.service
模板的一个实例,并可选择 启用 它以在启动/关闭时运行。 请注意,在这种情况下,实例标识符是显示编号(例如,显示编号 :1
的实例 vncserver@:1.service
)。
- 不支持直接调用
/usr/bin/vncserver
,因为它们不会建立适当的会话范围。 systemd 服务是使用 TigerVNC 的唯一受支持方法。 请参阅:Issue #1096。 - 在启动 vncserver 之前,删除为早期版本的 TigerVNC 创建的 drop-in 服务文件。 早期版本需要为每个显示器提供 drop-in 服务文件,例如,对于显示器 :1
/etc/systemd/system/vncserver@:1.service
。 如果在使用新的模板化服务文件启动时,旧的 drop-in 文件仍然存在,则 vncserver 将无法启动。
直接暴露本地显示
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(1),它允许直接控制物理 X 会话。 使用 vncpasswd 工具定义会话密码后,像这样调用服务器
$ x0vncserver -rfbauth $XDG_CONFIG_HOME/tigervnc/passwd
- x11vnc 是另一种 VNC 服务器,它也可以直接控制当前的 X 会话。
x0vncserver
当前不支持客户端和服务器之间的剪贴板共享(即使在autocutsel
的帮助下)。 请参阅:Issue #529。
使用 xprofile
启动 x0vncserver 的一种简单方法是在 xprofile 文件之一中添加一行,例如
~/.xprofile
... x0vncserver -rfbauth $XDG_CONFIG_HOME/tigervnc/passwd &
使用 systemd
使用系统服务
此选项将允许用户访问当前显示,包括显示管理器提供的登录屏幕。
每次用户注销会话时,该服务都会自动重新启动。
以下示例使用了 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
由于这是一个系统单元,-rfbauth $XDG_CONFIG_HOME/tigervnc/passwd
指的是 /root/.vnc/passwd
启动/启用 x0vncserver.service
。
使用用户服务
为了拥有运行 x0vncserver 的 VNC 服务器,这是大多数用户快速远程访问当前桌面的最简单方法,请创建如下 systemd 单元,并将用户和选项替换为所需的选项
~/.config/systemd/user/x0vncserver.service
[Unit] Description=Remote desktop service (VNC) [Service] Type=simple ExecStartPre=/bin/sh -c 'while ! pgrep -U "$USER" Xorg; do sleep 2; done' ExecStart=/usr/bin/x0vncserver -rfbauth %h/.vnc/passwd [Install] WantedBy=default.target
ExecStartPre
行等待 Xorg 由 ${USER}
启动。
要使用特定的用户名和密码登录,请将 ExecStart
替换为 /usr/bin/x0vncserver -PAMService=login -PlainUsers=${USER} -SecurityTypes=TLSPlain
。
启动/启用 x0vncserver.service
用户单元。
运行 Xvnc 与 XDMCP 以按需会话
可以结合使用 systemd 套接字激活和 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
启动/启用 xvnc.socket
。 现在,任意数量的用户都可以通过连接到端口 5900 来获得唯一的桌面。
如果 VNC 服务器暴露在互联网上,请在 xvnc@.service
中的 Xvnc
中添加 -localhost
选项(请注意 -query localhost
和 -localhost
是不同的开关),并按照 #通过 SSH 隧道访问 vncserver 进行操作。 由于我们仅在连接后选择用户,因此 VNC 服务器以用户 nobody 身份运行,并直接使用 Xvnc
而不是 vncserver
脚本,因此 $XDG_CONFIG_HOME/tigervnc
中的任何选项都将被忽略。 可选地,自动启动 vncconfig 以使剪贴板工作(vncconfig 在非 VNC 会话中立即退出)。 一种方法是创建
/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
开关使您可以指定服务器的 $XDG_CONFIG_HOME/tigervnc/passwd
文件的位置。 预计用户可以通过 SSH 或物理访问服务器来访问此文件。 在任何一种情况下,都将文件放置在客户端文件系统中的安全位置,即只有预期用户具有读取访问权限的位置。
$ vncviewer -passwd /path/to/server-passwd-file
密码也可以直接提供。
ps
的人都会看到它。$ vncviewer -passwd <(echo MYPASSWORD | vncpasswd -f)
GUI 客户端示例
TigerVNC 的 vncviewer 在没有任何参数的情况下运行时也具有简单的 GUI
$ vncviewer
通过 SSH 隧道访问 vncserver
对于提供 SSH 连接的服务器,此方法的优势在于无需打开除已打开的 SSH 端口之外的任何其他端口,因为 VNC 流量是通过 SSH 端口隧道传输的。
在服务器端
在服务器端,必须运行 vncserver 或 x0vncserver。
在运行其中任何一个时,建议在 $XDG_CONFIG_HOME/tigervnc/config
中使用 localhost
选项或 -localhost
开关(对于 x0vncserver),因为它只允许来自 localhost 的连接,并且类似地,只允许来自在框上 ssh 并经过身份验证的用户。 例如
$XDG_CONFIG_HOME/tigervnc/config
session=lxqt geometry=1920x1080 localhost alwaysshared
确保启动或重启 vncserver@.service
,例如(另请参阅 #初始设置)
# systemctl start vncserver@:1
或对于 x0vncserver
$ x0vncserver -localhost -SecurityTypes none
在客户端
VNC 服务器已在远程计算机上设置为仅接受本地连接。 现在,客户端必须使用远程计算机(在此示例中为 10.1.10.2)打开安全 shell,并创建从客户端端口(例如 9901)到远程服务器 5901 端口的隧道。 有关此功能的更多详细信息,请参阅 OpenSSH#端口转发 和 ssh(1)。
$ ssh 10.1.10.2 -L 9901:localhost:5901
通过 SSH 连接后,保持此 shell 窗口打开,因为它充当与服务器的安全隧道。 或者,使用 -f
选项直接在后台运行 SSH。 在客户端,要通过此加密隧道连接,请将 vncviewer 指向 localhost 上的转发客户端端口。
$ vncviewer localhost:9901
实际发生的情况是 vncviewer 在本地连接到端口 9901,该端口隧道传输到服务器的 localhost 端口 5901。 连接在安全 shell 内建立到正确的端口。
$ 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]
。)
通过 SSH 从 Android 设备连接到 vncserver
要使用 Android 设备作为客户端通过 SSH 连接到 VNC 服务器,请考虑进行以下设置
- SSH 在服务器上运行
- vncserver 在服务器上运行(带有
-localhost
标志以提高安全性) - Android 设备上的 SSH 客户端:ConnectBot 是一个流行的选择,将在本指南中用作示例
- Android 设备上的 VNC 客户端:此处使用 androidVNC
在 ConnectBot 中,连接到所需的机器。 点击选项键,选择端口转发并添加一个端口
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
提示和技巧
连接到 macOS 系统
请参阅 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 客户端的菜单完成。 默认情况下,vnc 客户端的 mkey 是 F8
。
鼠标后退和前进按钮无法工作的解决方法
VNC 协议当前仅使用 7 个鼠标按钮(左、中、右、向上滚动、向下滚动、向左滚动、向右滚动),这意味着如果鼠标有后退和前进按钮,则这些按钮不可用,并且输入将被忽略。
evrouter 可用于解决此限制,方法是在单击鼠标后退/前进按钮时发送键盘按键。 可选地,服务器上可以使用 xautomation 和 xbindkeys 中的 xte 将键盘按键映射回鼠标按钮点击(如果需要)。
使用键盘按键 XF86Back/XF86Forward 替代鼠标后退/前进按钮
如果您只需要一种在使用 Web 浏览器或文件浏览器时向后/向前导航的方法,则此方法简单且适用。
在客户端上安装 evrouterAUR 和 xautomation。 配置 evrouter,有关如何查找正确的设备名称、窗口名称、按钮名称等的说明和提示,请参阅 鼠标按钮#evrouter 和 evrouter 手册页。 示例配置
~/.evrouterrc
Window "OtherComputer:0 - TigerVNC": # Window title used as filter # Using Shell to avoid repeating key presses (see evrouter manual) "USB mouse" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/275 "Shell/xte 'key XF86Back'" "USB mouse" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/276 "Shell/xte 'key XF86Forward'" # Use XKey below instead if repeating keys is desired (see evrouter manual) #"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。 使用上述配置,当单击鼠标上的后退按钮时,键盘按键 XF86Back
将发送到 VNC 服务器,当单击前进按钮时,将发送 XF86Forward
。
将键盘按键映射回服务器上的鼠标按钮点击
如果需要,可以将键盘按键映射回服务器上的鼠标按钮点击。 在这种情况下,使用客户端或服务器上永远没有的键盘按键可能是一个好主意。 在下面的示例中,键盘按键 XF86Launch8
/XF86Launch9
用作鼠标按钮 8/9。
客户端上的 Evrouter 配置
~/.evrouterrc
Window "OtherComputer:0 - TigerVNC": # Window title # Using Shell to avoid repeating key presses (see evrouter manual) "USB mouse" "/dev/input/by-id/usb-Mouse-name-event-mouse" none key/275 "Shell/xte 'key XF86Launch8'" "USB mouse" "/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。
故障排除
黑色矩形而不是窗口
很可能,这是由于应用程序严格要求合成 Xorg 扩展。 例如,基于 webkit 的应用程序:midori、psi-plus 等。
在这种情况下,使用如下命令重新启动 vncserver
$ vncserver -geometry ... -depth 24 :1 +extension Composite
看起来 VNC 中的 Composite 扩展仅适用于 24 位深度。
带有鼠标光标的空白黑色窗口或 xinit: 与 X 服务器的连接丢失
验证用户是否未登录到物理 X 会话,除非此选项已使用 x0vncserver 配置。 不支持单个用户的多个 X 会话,请参阅 684#issuecomment-494385395 和 #1634。
相反,当 VNC 服务器服务正在为该用户运行时,尝试登录本地 X 会话可能无法正常工作,并且在使用桌面环境时可能会卡在启动画面上。
没有鼠标光标
如果在使用 x0vncserver 时没有鼠标光标可见,请按如下方式启动 vncviewer
$ vncviewer DotWhenNoCursor=1 server
或者,将 DotWhenNoCursor=1
放入 TigerVNC 配置文件中,默认情况下该文件位于 $XDG_CONFIG_HOME/tigervnc/default.tigervnc
。
从远程机器复制剪贴板内容
如果从远程机器复制到本地机器不起作用,请在服务器上运行 autocutsel
,如 [1] 中所述
$ autocutsel -fork
现在,按 F8
显示 VNC 菜单弹出窗口,然后选择剪贴板:本地 -> 远程选项。
没有窗口装饰 / 边框 / 标题栏 / 无法移动窗口
启动窗口管理器以修复空的 xterm 框架。 例如,在 Xfce 上,运行 xfwm4 &
。
桌面环境仅显示字体框
某些桌面环境可能缺少显示 ASCII 字符所需的字体。 Install ttf-dejavu。
使用 xfce4 会话时 VNC 服务器立即终止
在 /usr/share/xsessions
下创建一个新的 .desktop 文件。 例如
/usr/share/xsessions/xfce4vnc.desktop
[Desktop Entry] Version=1.0 Name=Xfce4vnc Session Exec=dbus-launch startxfce4 Icon= Type=Application DesktopNames=XFCE4VNC
确保 Exec
键使用 dbus-launch
在新的会话总线实例上下文中启动 xfce4。 记住将 $XDG_CONFIG_HOME/tigervnc/config
中的 session
值更改为 xfce4vnc
。