X11vnc

来自 ArchWiki

x11vnc 是一个 VNC 服务器,它允许使用任何 VNC 查看器远程访问、查看和控制真实的 X 显示器(即对应于物理显示器、键盘和鼠标的显示器)。虽然它的原始作者 Karl Runge 不再开发它,但 LibVNC 和 x11vnc 的 GitHub 社区 已经接管了开发。

TigerVNCxvnc 不同,x11vnc 默认连接到现有的 X 显示器。但是,可以使用 -create 选项启动并连接到新的无头(虚拟)X 服务器。

另请注意,x11vnc 未附带 VNC 客户端(VNC 查看器)。任何 VNC 查看器 都应该可以工作,并且与 x11vnc 服务器兼容,但不一定使用其所有功能。推荐使用 TigerVNC 的 vncviewer 客户端。

安装

安装 x11vnc 软件包。

用法

首先,启动一个 X 显示器,可以通过 startx 或通过 显示管理器。您也可以使用无头 X 显示器

然后,运行以下命令,所有可用选项都在 x11vnc(1) 中解释。

$ x11vnc
警告: 这将设置没有身份验证密码的 VNC 服务器。这意味着任何有权访问计算机网络的人都可以查看和控制您的 X 会话。您可以简单地设置密码,如下文所述

默认情况下,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 服务器

注意: 上面的密码“PASSWORD”是不安全的;任何可以在机器上运行 ps 的人都会看到它。另请注意,/var/log/x11vnc.log 需要手动创建,并且其所有权需要与运行它的用户匹配。

设置密码

注意: 密码仅加密登录过程本身。传输仍然是未加密的[1]。您可以使用 x11vnc 的内部 SSL 或使用 SSH 隧道传输您的流量。

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.servicedrop-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

注意: 较新版本的 GDM 软件包默认使用 Xwayland 作为显示服务器后端。但是,以下说明仅适用于使用 Xorg 时(否则不会创建 .Xauthorityx11vnc 无法启动)。因此,建议您取消注释 /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

您还需要运行 AvahimDNS 守护程序,并打开 UDP 的端口 5353,这取决于您的防火墙配置。

共享独立的 X 窗口

x11vnc 可以连接到 X 服务器,仅轮询该 X 显示器的一个窗口,而不是与客户端共享整个 X 显示器。这在使用 -view-only 选项时尤其有用。

为此,请使用 id idsid 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 已转发。

此文章或章节的事实准确性存疑。

原因: 请使用模板的第一个参数提供简要说明。 (在 Talk:X11vnc 中讨论)

2. 仅在 GNOME + GDM 上测试

如果您无法启动隧道,并收到类似 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 3x11vnc

如果您使用 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

注意: 这些说明仅在使用 Xorg 中的 GDM 和 GNOME shell 时有效。

执行以下步骤以在 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

现在,您需要记住以下几点

  1. 您可能会注意到,在 systemd 服务的 ExecStart 部分中,执行的命令可以分为两个任务:首先停止 x11vnc-gdm.service(杀死 GDM x11vnc 服务器),然后为 GNOME shell 会话中的用户启动 x11vnc 服务器。这样做是因为如果您保持 GDM x11vnc 服务器在后台运行,则用户的新 x11vnc 服务器将使用下一个可用端口,您将需要更改客户端连接设置以连接到 GDM x11vnc 服务器或您的用户特定的 x11vnc 服务器。像这样的设置很有用,因为 GDM x11vnc 服务器会在您登录到您的帐户后立即停止。
  2. 您需要为您希望拥有此功能的每个用户创建一个类似的服务。(不要忘记将 your_useruser_home 替换为您的实际用户名。)
  3. 您可能需要更改命令的 -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.servicex11vnc-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

参见