X11vnc
x11vnc 是一个 VNC 服务器,它允许使用任何 VNC 查看器远程访问、查看和控制真实的 X 显示器(即对应于物理显示器、键盘和鼠标的显示器)。虽然它的原始作者 Karl Runge 不再开发它,但 LibVNC 和 x11vnc 的 GitHub 社区 已经接管了开发。
与 TigerVNC 的 xvnc 不同,x11vnc 默认连接到现有的 X 显示器。但是,可以使用 -create
选项启动并连接到新的无头(虚拟)X 服务器。
另请注意,x11vnc 未附带 VNC 客户端(VNC 查看器)。任何 VNC 查看器 都应该可以工作,并且与 x11vnc 服务器兼容,但不一定使用其所有功能。推荐使用 TigerVNC 的 vncviewer 客户端。
安装
用法
首先,启动一个 X 显示器,可以通过 startx 或通过 显示管理器。您也可以使用无头 X 显示器。
然后,运行以下命令,所有可用选项都在 x11vnc(1) 中解释。
$ x11vnc
默认情况下,x11vnc 尝试连接到 -display
选项提供的 X 显示器,或者环境变量 DISPLAY
变量的值(如果存在),否则连接到 :0 显示器(如果两者都未提供)。
$ x11vnc -display :1
另一种选择是将 x11vnc 命令行放在登录时调用的脚本中,例如
x11vnc -wait 50 -noxdamage -passwd PASSWORD -display :0 -forever -o /var/log/x11vnc.log -bg
-wait
选项设置从 X 服务器帧缓冲区轮询之间暂停的时间(以毫秒为单位)。
-noxdamage
选项禁用 X Damage 扩展。请参阅#会话意外关闭。
-forever
选项保持 x11vnc 服务器运行,监听进一步的客户端连接,即使在第一个客户端断开连接后也是如此。请参阅#持久 x11vnc 服务器。
ps
的人都会看到它。另请注意,/var/log/x11vnc.log
需要手动创建,并且其所有权需要与运行它的用户匹配。设置密码
x11vnc 提供了许多选项来设置和管理身份验证密码;本节介绍其中的一些选项。阅读 x11vnc(1) 手册页以查找和阅读所有这些选项。
-usepw
选项用作通用密码标志
$ x11vnc -usepw
它使用在 ~/.vnc/passwd
中找到的密码,其中密码使用 VNC 兼容格式的固定密钥进行模糊处理,否则使用在 ~/.vnc/passwdfile
中找到的密码。如果找不到这些文件中的任何一个,它会提示用户输入密码,该密码保存在 ~/.vnc/passwd
中并立即使用。
然后,VNC 查看器在连接时应提示输入密码。
-showrfbauth
、-rfbauth
和 -storepasswd
选项允许分别查看、使用或设置 RFB 的身份验证密码。
-passwdfile
选项可用于提供 LibVNCServer 密码文件,该文件允许设置多个密码以及只读连接的密码。
端口设置
默认情况下,x11vnc 搜索从 5900 开始的第一个空闲端口,并将其用于 IPv4 和 IPv6 VNC 连接,无论它连接到的 X 显示器编号是什么。
-N
参数,将端口设置为 5900 加上显示器编号。例如
$ x11vnc -display :3 -N
这将导致此 VNC 服务器使用端口号 5903。
-autoport n
参数,将端口设置为从数字 n 开始的第一个空闲端口。
-rfbport n
参数可用于将 VNC 端口显式设置为 n。
在上述所有三种情况下,额外的端口将用于 IPv6 连接,端口号相同;除了 5900 IPv6 端口,如果空闲,它也将被使用。因此,您将最终为该 x11vnc 服务器获得三个打开的端口,一个用于 IPv4,两个用于 IPv6。例如
$ x11vnc -display :2 -rfbport 5905
这将连接到显示器编号为 2 的 X 服务器,并侦听 IPv4 端口 5905 和 IPv6 端口 5905 和 5900 以进行 VNC 客户端连接。
要直接设置 IPv6 端口,请使用 -rfbportv6 n
选项。
传递 X 授权文件
为了使 x11vnc 服务器连接到 X 显示服务器,它需要访问显示器的 X 授权文件,以授权自身。
要将目标显示器的 X 授权文件传递给 x11vnc 服务器,您可以在调用 x11vnc 命令之前或通过 -env
选项将 XAUTHORITY
环境变量设置为适当的文件路径
$ x11vnc -display :0 -env XAUTHORITY=/home/user/.Xauthority
其中 user 是运行 X 服务器的用户的用户名。
您也可以使用 -auth
参数,后跟 X 授权文件地址
$ x11vnc -display :0 -auth ~/.Xauthority
或者,您可以使用 -auth guess
选项,它将尝试猜测目标 X 显示器的 XAUTHORITY 文件名并使用它
$ x11vnc -display :1 -auth guess
通常,如果所需的 X 显示器不是由当前用户启动的,则访问其 X 授权文件需要以 root 用户或具有读取目标 X 显示器的 X 授权文件权限的用户身份运行 x11vnc
# x11vnc -display :1 -auth /home/user/.Xauthority
从 xinetd 运行
可以使用 xinetd 服务运行 X11vnc,该服务仅在用户连接后才启动 X11vnc。
为 x11vnc 创建一个 xinetd 服务条目,例如
/etc/xinetd/x11vnc
service x11vncservice { port = 5900 type = UNLISTED socket_type = stream protocol = tcp wait = no user = root server = /usr/bin/x11vnc server_args = -inetd -o /var/log/x11vnc.log -noxdamage -display :0 -auth guess disable = no }
重新加载 xinetd.service
后,X11vnc 将在客户端连接到端口 5900 后启动。
作为 systemd 服务
要在系统启动时运行 x11vnc,请使用 x11vnc.service
的 drop-in unit 文件。内容应如下所示
/etc/systemd/system/x11vnc.service.d/override.conf
[Service] ExecStart= ExecStart=/usr/bin/x11vnc -many -display :0 -no6 -rfbport 5901 -auth /var/run/lightdm/root/:0 [Install] WantedBy=graphical.target
将第二个 ExecStart 替换为您以交互方式运行的命令。如果需要,启用 x11vnc.service
。
随显示管理器启动
典型的用例是在任何用户登录到 X 会话之前,为登录会话本身启动 x11vnc 服务器。显示管理器通常将其 X 授权文件放在常规用户无法访问的目录中,因此启动 x11vnc 需要 root 权限。
自动发现显示管理器的 X 授权文件
当 x11vnc 命令被提供 -auth guess
选项且环境变量 FD_XDM
变量绑定到 1
时,它会尝试查找当前显示管理器的 X 授权文件
$ x11vnc -find -env FD_XDM=1 -auth guess
GDM
.Xauthority
,x11vnc 无法启动)。因此,建议您取消注释 /etc/gdm/custom.conf
中的 #WaylandEnable=false
设置以便继续。# x11vnc -display :0 -auth /var/lib/gdm/:0.Xauth
较新版本的 GDM 使用 /run/user。用户 120 (gdm) 的示例,用于登录屏幕。
# x11vnc -display :0 -auth /run/user/120/gdm/Xauthority
或参见下面的故障排除部分
LightDM
在 bash 中运行
# x11vnc -display :0 -auth /var/run/lightdm/root/\:0
LXDM
# x11vnc -display :0 -auth /var/run/lxdm/lxdm-\:0.auth
SDDM
SDDM 为授权文件使用不可预测的 UUID [2],因此需要
# x11vnc -display :0 -auth $(find /var/run/sddm/ -type f)
将此嵌入到 systemd .service 文件中将需要一个技巧来评估 find 命令,如此处所示 [3]。
如果上述方法不起作用,另一种方法是在 SDDM 运行 Xsetup 脚本时启动 x11vnc。为此,请将以下行添加到 /usr/share/sddm/scripts/Xsetup
/usr/bin/x11vnc -auth /var/run/sddm/* -display :0 >/dev/null 2>&1 &
SLIM
# x11vnc -display :0 -auth /var/run/slim.auth
持久 x11vnc 服务器
默认情况下,x11vnc 在客户端(VNC 查看器)断开连接和/或 X 服务器终止时终止。但是,在这些情况下,有几种方法可以保持 x11vnc 服务器运行。
-many
或 -forever
参数指定 x11vnc 在查看器断开连接后不终止,并等待进一步可能的连接,没有超时。下一个连接请求可以来自相同或任何其他客户端
$ x11vnc -many
但是,任何方式的显示器终止仍然会终止 x11vnc。
-loop
标志创建一个循环,该循环尝试在 x11vnc 服务器因任何原因终止后再次启动它。默认情况下,这将无限期地每两秒尝试一次。
$ x11vnc -loop
可以按如下方式调整重试次数和频率
$ x11vnc -loop5000,5
这将有效地使服务器在其终止后重启 5 次,每次 5 秒,直到建立连接;重新连接到显示服务器和 VNC 客户端。
可以组合使用 -loop
和 -forever
标志;使 x11vnc 服务器根本不会因客户端断开连接而停止,并且如果 X 显示器终止,也会重新启动,直到具有相同显示器编号和 X 授权文件的 X 服务器再次启动。
$ x11vnc -display :1 -forever -loop5000
只读连接
默认情况下,VNC 客户端既可以查看也可以控制它们连接到的 X 桌面。-view-only
使当前服务器只读,以便 VNC 查看器只能观看桌面而不能与之交互。
多播 DNS 广播
许多 VNC 客户端都能够发现其本地网络上通告的 zeroconf VNC 服务器。
要使用 zeroconf 协议广播 VNC 服务器,请使用 -avahi
或 -mdns
或 -zeroconf
选项启动它。这三个选项是别名。例如
$ x11vnc -display :0 -mdns
您还需要运行 Avahi 或 mDNS 守护程序,并打开 UDP 的端口 5353,这取决于您的防火墙配置。
共享独立的 X 窗口
x11vnc 可以连接到 X 服务器,仅轮询该 X 显示器的一个窗口,而不是与客户端共享整个 X 显示器。这在使用 -view-only
选项时尤其有用。
为此,请使用 id id
或 sid id
选项启动 x11vnc;其中 id 表示 X 窗口的 ID,可以使用 xwininfo(1) 获取。可以使用 pick
参数代替,这将使 x11vnc 直接调用 xwininfo
,然后交互式地提取所选 X 窗口的 ID。例如
$ x11vnc -id pick
-id
选项将直接轮询 X 窗口,这将省略该窗口打开的新窗口;可能看不到弹出菜单和瞬态顶层窗口。相比之下,-sid
选项会将根视图移到该窗口,从而解决了该问题。
请注意,关闭 x11vnc 服务器连接到的 X 窗口会终止 x11vnc。
访问
在另一台计算机上获取 VNC 客户端,并键入运行 x11vnc 的计算机的 IP 地址。点击连接,您应该就可以设置好了。
如果您尝试从其网络外部访问 VNC 服务器/计算机(运行 x11vnc),则需要确保它已转发端口 5900。
SSH 隧道
您需要安装并配置 SSH。
将 -localhost
标志与 x11vnc 一起使用,使其绑定到本地接口。完成此操作后,您可以使用 SSH 隧道传输端口;然后,通过 SSH 连接到 VNC。
简单示例(来自 http://www.karlrunge.com/x11vnc/index.html#tunnelling)
$ ssh -t -L 5900:localhost:5900 remote_host 'x11vnc -localhost -display :0'
(您可能需要提供密码/密码短语才能从您当前的位置登录到您的 remote_host Unix 帐户;我们假设您在 remote_host 上有一个登录帐户,并且它正在运行 SSH 服务器)
然后在当前机器的另一个终端窗口中运行命令
$ vncviewer -PreferredEncoding=ZRLE localhost:0
故障排除
1. 您可以访问 此[死链 2020-04-03 ⓘ] 网站检查您的 IP 地址,并确保端口 5900 已转发。
如果您无法启动隧道,并收到类似 XOpenDisplay(":0") 失败的错误,请检查您是否有一个 ~/.Xauthority
目录。如果该目录不存在,您可以轻松创建一个(实际上是到实际目录的符号链接),方法是以普通用户身份运行以下命令,而不是 ROOT 或使用 Sudo,如下所示
$ ln -sv $(dirname $(xauth info | awk '/Authority file/{print $3}')) ~/.Xauthority
然后尝试上面的 隧道 示例,它应该可以正常工作。此外,如果您希望每次 Xorg 重新启动时自动完成此操作,请创建 xprofile 文件并使其可执行,如下所示
$ ln -sf $(dirname $(xauth info | awk '/Authority file/{print $3}')) ~/.Xauthority
3. GNOME 3 和 x11vnc
如果您使用 GNOME 3 和 x11vnc,并且收到以下错误
*** XOpenDisplay failed (:0) *** x11vnc was unable to open the X DISPLAY: ":0", it cannot continue.
尝试像这样运行 x11vnc
$ x11vnc -noxdamage -many -display :0 -auth /var/run/gdm/$(sudo ls /var/run/gdm | grep $(whoami))/database -forever -bg
如果这适用于/不适用于任何其他 显示管理器 或 桌面环境,请更新。
屏幕保护程序问题
如果屏幕保护程序每 1-2 秒启动一次,请使用 -nodpms
键启动 x11vnc。
IPv6 端口与 IPv4 端口不同
命令的默认行为
$ x11vnc -display :0 -rfbport 5908
是服务器侦听 TCP 端口 5908 和 TCP6 端口 5900。为了使服务器也侦听相同的 TCP6 端口,请使用 -rfbportv6
选项强制 IPv6 侦听端口。例如
$ x11vnc -display :0 -rfbport 5908 -rfbportv6 5908
复制和粘贴
如果复制和粘贴未按预期工作,特别是如果粘贴到远程端不起作用或剪贴板行为不符合预期,请尝试添加 -xkb
$ x11vnc -xkb -display :0
尽管文档未明确指出 -xkb
用于剪贴板问题,但它解决了 vim 抱怨 *
寄存器中没有任何内容的问题。
会话意外关闭
x11vnc 默认启用 X Damage 扩展,这在屏幕变化不大时显着降低负载,并更快地检测到更改的区域。已知此扩展会导致问题[4][5]FS#71685[6],并且它可能导致会话意外关闭,日志中出现 caught XIO error
消息。可以使用 -noxdamage
选项来规避此问题。
技巧与窍门
在(GDM 和 GNOME Shell)中“系统范围”运行 x11vnc
执行以下步骤以在 GDM 中运行 x11vnc 以登录,然后在 GNOME shell 用户会话中运行 x11vnc 以实现“系统范围”的 x11vnc
首先,我们需要创建一个 systemd 服务以在 GDM 中启动 x11vnc 服务器
/etc/systemd/system/x11vnc-gdm.service
[Unit] Description=x11vnc server for GDM After=display-manager.service [Service] ExecStart= ExecStart=/usr/bin/x11vnc -many -shared -display :0 -auth /run/user/120/gdm/Xauthority -noxdamage -rfbauth user_home/.vnc/passwd Restart=on-failure RestartSec=3 [Install] WantedBy=graphical.target
这将启动一个受存储在 user_home/.vnc/passwd
中的密码保护的 x11vnc 服务器,该服务器向任何连接的 VNC 客户端显示 GDM,但是您可能会注意到,如果您单击任何用户,一旦您登录,所有 VNC 客户端都将显示黑屏。为了解决这个问题,我们需要创建另一个 systemd 服务,该服务将在您登录后立即在 GNOME Shell 会话中启动另一个 x11vnc 服务器
/etc/systemd/system/x11vnc-gnome-shell-YOUR_USER.service
[Unit] Description=x11vnc server for Gnome shell session of your_user [Service] User=YOUR_USER Type=simple ExecStartPre=/bin/sh -c 'while ! pgrep -U "your_user" Xorg; do sleep 2; done' ExecStart=/bin/sh -c 'sudo systemctl stop x11vnc-gdm.service && /usr/bin/x11vnc -many -shared -display :1 -auth user_home/.Xauthority -rfbauth user_home/.vnc/passwd' Restart=on-failure RestartSec=3 [Install] WantedBy=graphical.target
现在,您需要记住以下几点
- 您可能会注意到,在 systemd 服务的
ExecStart
部分中,执行的命令可以分为两个任务:首先停止x11vnc-gdm.service
(杀死 GDM x11vnc 服务器),然后为 GNOME shell 会话中的用户启动 x11vnc 服务器。这样做是因为如果您保持 GDM x11vnc 服务器在后台运行,则用户的新 x11vnc 服务器将使用下一个可用端口,您将需要更改客户端连接设置以连接到 GDM x11vnc 服务器或您的用户特定的 x11vnc 服务器。像这样的设置很有用,因为 GDM x11vnc 服务器会在您登录到您的帐户后立即停止。 - 您需要为您希望拥有此功能的每个用户创建一个类似的服务。(不要忘记将
your_user
和user_home
替换为您的实际用户名。) - 您可能需要更改命令的
-display :X
部分以匹配您的系统设置。您可以通过运行echo $DISPLAY
查看当前显示器。使用结果输出以匹配 systemd 服务。
现在,您可能会注意到,x11vnc-gnome-shell.service
是以您的(可能)非特权用户身份执行的。如果我们想停止 x11vnc-gdm.service
,这会带来问题,因此我们需要允许用户停止 GDM 服务。这可以使用 sudo 完成,但我们需要允许在没有密码的情况下执行仅该特定命令。
编辑 sudoers 文件以添加
YOUR_USER ALL=(root) NOPASSWD: /usr/bin/systemctl stop x11vnc-gdm.service
现在,您只需启用 x11vnc-gdm.service
和 x11vnc-gnome-shell-your_user.service
。当您重新启动计算机时,它们都将开始运行,您可以使用 VNC 连接到您的 GDM 和 GNOME Shell。
在(SDDM 和 Plasma)中“系统范围”运行 x11vnc
要在系统启动到 SDDM 时运行 x11vnc(如果上述方法对您不起作用),只需 编辑 x11vnc.service
如下
/etc/systemd/system/x11vnc.service.d/override.conf
[Service] ExecStart= ExecStart=/bin/bash -c "/usr/bin/x11vnc -auth /var/run/sddm/* -display :0 -forever -loop -noxdamage -repeat -rfbauth /home/your_user/.vnc/passwd -shared" ExecStartPre=/usr/bin/sleep 1
记住更改路径中的 your_user
,或使用首选的身份验证方法。禁用 旧的 x11vnc.service
并重新加载 systemd 管理器配置。重新启用 之后的 x11vnc.service
单元。您可能需要让服务休眠一段时间,否则它将无法正确启动。
每次启动时更改 x11vnc 密码
如果您需要与您不信任的几个人共享您的桌面,并且您不想每次都手动更改密码,那么这样的设置可能很有用。这样的设置将生成启动唯一的密码,因此如果您与某人共享密码,您只需要重新启动计算机(或重新运行 systemd 服务)即可更改密码。
新的生成密码将以纯文本形式存储在 ~/.vnc/autovncpass
中,因此可以使用以下命令访问它
$ cat /home/$USER/.vnc/autovncpass
为了完成此操作,请执行以下步骤
首先安装 expect 软件包。
然后,在您的主目录中的任何位置创建以下脚本
~/Automatic-x11vnc-Password-Changer.exp
#!/usr/bin/expect -f set timeout -1 log_user 0 #Change your username here set USER "your_user" #First we need to generate the password, if you want to #change the password generation, change the "openssl rand -hex 4" line set NewVNCPassword [exec openssl rand -hex 4] #Now we invoke x11vnc to change the password spawn x11vnc --storepasswd match_max 100000 expect -exact "Enter VNC password: " send -- "$NewVNCPassword\r" expect -exact "\r Verify password: " send -- "$NewVNCPassword\r" expect -exact "\r Write password to /home/$USER/.vnc/passwd? \[y\]/n " send -- "y\r" expect eof #Save the Password to the /home/$USER/.vnc/ directory as plaintext, exec echo "$NewVNCPassword" > /home/$USER/.vnc/autovncpass
现在我们需要创建一个 systemd 单元文件,该文件将在启动时执行脚本
/etc/systemd/system/vnc-automatic-password-changer.service
[Unit] Description=x11vnc automatic password changer Before=display-manager.service [Service] User=YOUR_USER Type=oneshot ExecStart=/path/to/script/Automatic-x11vnc-Password-Changer.exp [Install] WantedBy=graphical.target
最后,启动/启用 服务以更改密码。您可以使用以下命令访问当前密码
$ cat /home/$USER/.vnc/autovncpass