如何在 CentOS 7 上为 GNOME 桌面安装和配置 VNC 远程访问
介绍
VNC 或虚拟网络计算是一种独立于平台的协议,使用户能够连接到远程计算机系统并从图形用户界面 (GUI) 使用其资源。
这就像远程控制一个应用程序:客户端计算机的击键或鼠标点击通过网络传输到远程计算机。 VNC 还允许在两台计算机之间共享剪贴板。如果您有 Microsoft Windows 服务器背景,VNC 很像远程桌面服务,只是它也可用于 OS X、Linux 和其他操作系统。
与网络世界中的其他一切一样,VNC 基于客户端服务器模型:VNC 服务器在远程计算机上运行——您的 Droplet——它为传入的客户端请求提供服务。
目标
在本教程中,我们将学习如何在 CentOS 7 上安装和配置 VNC 服务器。我们将安装可从 TigerVNC GitHub 存储库免费获得的 TigerVNC 服务器。
为了演示 VNC 的工作原理,我们还将在您的 CentOS 服务器上安装 GNOME 桌面。我们将创建两个用户帐户并为它们配置 VNC 访问。然后,我们将测试它们与远程桌面的连接性,最后,学习如何通过 SSH 隧道保护远程连接。
先决条件
本教程中显示的命令、包和文件在 CentOS 7 的最小安装上进行了测试。我们建议如下:
- 发行版:CentOS 7,64 位
- 资源要求:具有 2 GB RAM 的 Droplet
- 要学习本教程,您应该使用 sudo 用户。要了解 sudo 权限的工作原理,您可以参考此 DigitalOcean 教程
警告:您不应在生产 Linux 服务器上运行本教程中的任何命令、查询或配置。这可能会导致安全问题和停机。
第 1 步 — 创建两个用户帐户
首先,我们将创建两个用户帐户。这些帐户将从 VNC 客户端远程连接到我们的 CentOS 7 服务器。
- 乔文克
- 珍妮弗
运行以下命令为 joevnc 添加用户帐户:
sudo useradd -c "User Joe Configured for VNC Access" joevnc
然后运行passwd命令修改joevnc的密码:
sudo passwd joevnc
输出将要求我们输入新密码。提供后,该帐户就可以登录了:
Changing password for user joevnc.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
接下来,为 janevnc 创建一个帐户:
sudo useradd -c "User Jane Configured for VNC Access" janevnc
为 janevnc 设置密码:
sudo passwd janevnc
第 2 步 — 安装 GNOME 桌面
现在我们将安装 GNOME 桌面。 GNOME 是一项协作成果:它是构成非常流行的桌面环境的免费和开源软件的集合。还有其他桌面环境,如 KDE,但 GNOME 更受欢迎。我们的 VNC 用户将使用 GNOME 从桌面与服务器交互:
sudo yum groupinstall -y "GNOME Desktop"
根据您的网络速度,这可能需要几分钟时间。
安装软件包组后,重新启动服务器:
sudo reboot
故障排除——服务器卡在引导阶段
根据您的服务器设置方式,当机器启动时,它可能会停留在启动阶段并显示如下消息:
Initial setup of CentOS Linux 7 (core)
1) [!] License information (Licence not accepted)
Please make your choice from above ['q' to quit | 'c' to continue | 'r' to refresh]:
要解决此问题,请按 1(已读取许可),然后按 2(接受许可),然后按 C(继续)。您可能需要按 C 两次或更多次。下图显示了这一点:

如果您没有看到此错误并且引导过程顺利,那就更好了——您可以继续下一步。
第 3 步 — 安装 TigerVNC 服务器
TigerVNC 是允许我们建立远程桌面连接的软件。
安装 Tiger VNC 服务器:
sudo yum install -y tigervnc-server
这应该显示如下输出:
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
. . .
Running transaction
Installing : tigervnc-server-1.2.80-0.30.20130314svn5065.el7.x86_64 1/1
Verifying : tigervnc-server-1.2.80-0.30.20130314svn5065.el7.x86_64 1/1
Installed:
tigervnc-server.x86_64 0:1.2.80-0.30.20130314svn5065.el7
Complete!
现在我们已经安装了 VNC 服务器和 GNOME 桌面。我们还创建了两个用于通过 VNC 连接的用户帐户。
第 4 步 — 为两个客户端配置 VNC 服务
VNC 服务器在首次安装时不会自动启动。要检查这一点,请运行以下命令:
sudo systemctl status vncserver@:.service
输出将是这样的:
vncserver@:.service - Remote desktop service (VNC)
Loaded: loaded (/usr/lib/systemd/system/vncserver@.service; disabled)
Active: inactive (dead)
您还可以运行此命令:
sudo systemctl is-enabled vncserver@.service
这应该显示如下输出:
disabled
那么为什么它被禁用了呢?这是因为每个用户都会启动一个单独的 VNC 服务守护进程实例。换句话说,VNC 不会作为一个单独的进程运行来满足每个用户的请求。每个通过 VNC 连接的用户都必须启动一个新的守护进程实例(或者系统管理员可以自动执行此操作)。
CentOS 7 使用 systemd 守护进程启动其他服务。在 systemd 下本机运行的每个服务都有一个 服务单元文件,由 yum 安装程序放置在 /lib/systemd/system
目录下。在启动时自动启动的进程有一个指向此服务单元文件的链接,该文件位于 /etc/systemd/system/
目录中。
在我们的例子中,在 /lib/systemd/system/
目录中创建了一个通用服务单元文件,但在 /etc/systemd/system/
下没有建立链接。要对此进行测试,请运行以下命令:
sudo ls -l /lib/systemd/system/vnc*
你应该看到:
-rw-r--r--. 1 root root 1744 Jun 10 16:15 /lib/systemd/system/vncserver@.service
然后在/etc/systemd/system/
下查看:
sudo ls -l /etc/systemd/system/*.wants/vnc*
这个不存在:
ls: cannot access /etc/systemd/system/*.wants/vnc*: No such file or directory
因此,第一步是为我们的两个用户启动两个新的 VNC 服务器实例。为此,我们需要在 /etc/system/system
下制作两个通用 VNC 服务单元文件的副本。在下面的代码片段中,您使用两个不同的名称制作了两个副本:
sudo cp /lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:4.service
sudo cp /lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:5.service
那么为什么我们要在复制的文件名中添加两个数字(连同冒号)呢?
同样,这又回到了个人 VNC 服务的概念。 VNC 本身在端口 5900 上运行。由于每个用户都将运行自己的 VNC 服务器,因此每个用户都必须通过单独的端口进行连接。在文件名中添加一个数字告诉 VNC 将该服务作为 5900
的子端口运行。所以在我们的例子中,joevnc 的 VNC 服务将在端口 5904 (5900 + 4) 上运行,而 janevnc 的将在 5905 (5900 + 5) 上运行。
接下来为每个客户端编辑服务单元文件。使用 vi 编辑器打开 /etc/systemd/system/vncserver@:4.service
文件:
sudo vi /etc/systemd/system/vncserver@:4.service
看一下 \Quick HowTo 部分告诉我们我们已经完成了第一步。现在我们需要完成剩余的步骤。评论还告诉我们 VNC 是一个不受信任的连接。我们稍后会讨论这个.
现在,编辑文件的 [Service]
部分,将
的实例替换为 joevnc
。此外,在 ExecStart
参数的末尾添加 -geometry 1280x1024
子句。这只是告诉 VNC 它应该开始的屏幕尺寸。您将总共修改两行。编辑后的文件应该是这样的(注意没有显示整个文件):
# The vncserver service unit file
#
# Quick HowTo:
# 1. Copy this file to /etc/systemd/system/vncserver@:<display>.service
# 2. Edit <USER> and vncserver parameters appropriately
# ("runuser -l <USER> -c /usr/bin/vncserver %i -arg1 -arg2")
# 3. Run `systemctl daemon-reload`
# 4. Run `systemctl enable vncserver@:<display>.service`
#
. . .
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target
[Service]
Type=forking
# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/sbin/runuser -l joevnc -c "/usr/bin/vncserver %i -geometry 1280x1024"
PIDFile=/home/joevnc/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
[Install]
WantedBy=multi-user.target
保存文件并退出 vi。
同样,在 vi 中打开 /etc/systemd/system/vncserver@:5.service
文件并为用户 janevnc 进行更改:
sudo vi /etc/systemd/system/vncserver@:5.service
这里只是标记了更改的 [Service]
部分:
[Service]
Type=forking
# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/sbin/runuser -l janevnc -c "/usr/bin/vncserver %i -geometry 1280x1024"
PIDFile=/home/janevnc/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
接下来,运行以下命令以重新加载 systemd 守护程序,并确保 VNC 在启动时为两个用户启动。
sudo systemctl daemon-reload
启用第一个服务器实例:
sudo systemctl enable vncserver@:4.service
输出:
ln -s '/etc/systemd/system/vncserver@:4.service' '/etc/systemd/system/multi-user.target.wants/vncserver@:4.service'
启用第二个服务器实例:
sudo systemctl enable vncserver@:5.service
输出:
ln -s '/etc/systemd/system/vncserver@:5.service' '/etc/systemd/system/multi-user.target.wants/vncserver@:5.service'
现在您已经配置了两个 VNC 服务器实例。
第 5 步 — 配置您的防火墙
接下来,我们需要将防火墙配置为仅允许 VNC 流量通过端口 5904 和 5905。 CentOS 7 通过firewalld 守护进程使用动态防火墙;该服务不需要重新启动以使更改生效。
firewalld 服务应该在系统启动时自动启动,但检查一下总是好的:
sudo firewall-cmd --state
这应该显示:
running
如果由于任何原因状态为“未运行”,请执行以下命令以确保其正在运行:
sudo systemctl start firewalld
现在添加端口 5904 和 5905 的规则:
sudo firewall-cmd --permanent --zone=public --add-port=5904-5905/tcp
输出:
success
重新加载防火墙:
sudo firewall-cmd --reload
输出:
success
第 6 步 — 设置 VNC 密码
我们距离实际使用 VNC 仅一步之遥。在此步骤中,用户需要设置他们的 VNC 密码。这些不是用户的 Linux 密码,而是登录 VNC 会话的密码。
打开另一个终端连接到 CentOS 7 服务器,这次以 joevnc 身份登录。
ssh joevnc@your_server_ip
执行以下命令:
vncserver
如下面的输出所示,服务器将要求 joevnc 设置 VNC 密码。输入密码后,程序还会显示在用户主目录中创建的一些文件:
You will require a password to access your desktops.
Password:
Verify:
xauth: file /home/joevnc/.Xauthority does not exist
New 'localhost.localdomain:1 (joevnc)' desktop is localhost.localdomain:1
Creating default startup script /home/joevnc/.vnc/xstartup
Starting applications specified in /home/joevnc/.vnc/xstartup
Log file is /home/joevnc/.vnc/localhost.localdomain:1.log
让我们看一下 New localhost.localdomain:1 (joevnc) desktop is localhost.localdomain:1
这行。 localhost.localdomain 是我们示例中的服务器名称;在您的情况下可能会有所不同。请注意服务器名称后的数字:(1,以冒号分隔)。这不是 joevnc 的服务单元文件中的数字(它是 4)。这是因为这是 joevnc 会话将在此服务器上运行的显示编号,而不是服务 (5904
) 本身的端口号。
接下来打开一个新的终端会话并以 janevnc 身份登录。同样在这里,启动 VNC 服务器并为 janevnc 设置密码:
vncserver
您应该会看到类似的输出,表明 janevnc 的会话将在显示器 2 上运行。
最后,从主终端会话重新加载服务:
sudo systemctl daemon-reload
sudo systemctl restart vncserver@:4.service
sudo systemctl restart vncserver@:5.service
第 7 步 — 使用 VNC 客户端连接到远程桌面
对于本教程,我们假设用户 joevnc 和 janevnc 正在尝试从他们的 Windows 计算机连接到 CentOS 7 服务器。
他们每个人都需要一个用于 Windows 的 VNC 客户端来登录远程桌面。这个客户端就像 PuTTY 这样的终端客户端,除了它显示图形输出。有多种可用的 VNC 客户端,但我们将使用的是 RealVNC,可在此处获得。适用于 Mac OS X 的 VNC 查看器可在同一页面上下载,Mac 版本与 Windows 版本非常相似。
当 VNC Viewer 启动时,它会显示如下对话框:

在 VNC 服务器字段中,添加 CentOS 7 服务器的 IP 地址。在服务器IP后指定端口号5904,用冒号(:)隔开。我们使用 5904 因为这是 joevnc 的 VNC 服务端口。
我们还决定让 VNC Viewer 选择加密方法。此选项将只加密通过网络发送的密码。与服务器的任何后续通信都将是未加密的。 (我们将在最后一步设置一个安全的 SSH 隧道。)

事实上,一条警告消息仅表明:

暂时接受警告。显示密码提示:

输入之前设置的 joevnc 的 VNC 密码。
将打开一个新窗口,显示我们远程 CentOS 服务器的 GNOME 桌面:

接受默认的欢迎消息。
现在 joevnc 可以启动像 GNOME 计算器这样的图形工具了:


您可以让此桌面连接保持打开状态。
现在 janevnc 还可以与 CentOS 服务器启动另一个 VNC 会话。 IP地址相同,端口为5905:

当 janevnc 通过 VNC 查看器登录时,会显示一个带有欢迎消息的空桌面,就像为 joevnc 显示的那样。换句话说,这两个用户没有共享桌面实例。 joevnc 的桌面应该仍然显示计算器。
要关闭远程桌面会话,只需关闭窗口即可。但是,这不会停止服务器后台用户的 VNC 服务。如果服务没有停止或重新启动,并且机器没有重新启动,则下次登录时将显示相同的桌面会话。
关闭 joevnc 和 janevnc 的 VNC 查看器窗口。也关闭他们的终端会话。在主终端窗口中,检查 VNC 服务是否仍在运行:
sudo systemctl status vncserver@:4.service
输出显示远程桌面仍在运行:
vncserver@:4.service - Remote desktop service (VNC)
Loaded: loaded (/etc/systemd/system/vncserver@:4.service; enabled)
Active: active (running) since Sat 2014-11-01 12:06:49 EST; 58min ago
Process: 2014 ExecStart=/sbin/runuser -l joevnc -c /usr/bin/vncserver %i -geometry 1280x1024 (code=exited, status=0/SUCCESS)
. . .
检查第二个服务:
sudo systemctl status vncserver@:5.service
这个也在运行:
vncserver@:5.service - Remote desktop service (VNC)
Loaded: loaded (/etc/systemd/system/vncserver@:5.service; enabled)
Active: active (running) since Sat 2014-11-01 12:42:56 EST; 22min ago
Process: 3748 ExecStart=/sbin/runuser -l janevnc -c /usr/bin/vncserver %i -geometry 1280x1024 (code=exited, status=0/SUCCESS)
. . .
如果此时你想重新登录到 joevnc 的桌面,你会看到相同的计算器应用程序打开。
这给系统管理员带来了一些有趣的挑战。如果您有许多用户通过 VNC 连接到服务器,您可能想设计一些方法在不再需要时停止他们的 VNC 服务。这可能会节省一些宝贵的系统资源。
故障排除——VNC 服务崩溃
当您测试和使用 VNC 时,有时您可能会发现该服务已崩溃且无法恢复。当您尝试检查状态时:
sudo systemctl status vncserver@:4.service
可能会出现这条长错误消息:
vncserver@:4.service - Remote desktop service (VNC)
Loaded: loaded (/etc/systemd/system/vncserver@:4.service; enabled)
Active: failed (Result: exit-code) since Fri 2014-11-07 00:02:38 EST; 2min 20s ago
Process: 2221 ExecStart=/sbin/runuser -l joevnc -c /usr/bin/vncserver %i -geometry 1280x1024 (code=exited, status=2)
Process: 1257 ExecStartPre=/bin/sh -c /usr/bin/vncserver -kill %i > /dev/null 2>&1 || : (code=exited, status=0/SUCCESS)
尝试启动服务不起作用:
sudo systemctl start vncserver@:4.service
启动失败:
Job for vncserver@:4.service failed. See 'systemctl status vncserver@:4.service' and 'journalctl -xn' for details.
通常原因很简单。检查 /var/log/messages
:
sudo tail /var/log/messages
相关错误将如下所示:
Nov 7 00:08:36 localhost runuser: Warning: localhost.localdomain:4 is taken because of /tmp/.X11-unix/X4
Nov 7 00:08:36 localhost runuser: Remove this file if there is no X server localhost.localdomain:4
Nov 7 00:08:36 localhost runuser: A VNC server is already running as :4
Nov 7 00:08:36 localhost systemd: vncserver@:4.service: control process exited, code=exited status=2
Nov 7 00:08:36 localhost systemd: Failed to start Remote desktop service (VNC).
Nov 7 00:08:36 localhost systemd: Unit vncserver@:4.service entered failed state.
Nov 7 00:08:36 localhost systemd: Failed to mark scope session-c3.scope as abandoned : Stale file handle
解决办法是删除/tmp文件夹下的文件:
sudo rm -i /tmp/.X11-unix/X4
输出:
rm: remove socket ‘/tmp/.X11-unix/X4’? y
然后启动VNC服务:
sudo systemctl start vncserver@:4.service
一般故障排除
尽管相对较少,但您在使用 VNC 时可能会遇到其他错误。例如,您的远程桌面屏幕可能会变成空白或挂起,会话可能会崩溃并出现神秘的错误消息,VNC 查看器可能无法正确连接或无法将命令传输到 GUI 以启动应用程序等。
我们建议检查 /var/log/messages
文件以获得更好的理解。有时您可能需要重新启动服务器,或者在极端情况下重新创建 VNC 服务。
系统资源也可能是罪魁祸首;您可能需要为您的 Droplet 等添加额外的 RAM。
第 8 步 — 通过 SSH 隧道保护 VNC 会话
到目前为止,joevnc 和 janevnc 都是通过未加密的通道访问他们的远程桌面。正如我们之前看到的,VNC 查看器会在连接时警告我们;只有密码在会话开始时被加密。任何后续的网络流量和数据传输都是开放的,任何人都可以在中间拦截。
关于 SSH 隧道
这是 Secure Shell (SSH) 会话可以提供帮助的地方。使用 SSH,VNC 可以在 SSH 加密会话的上下文中运行。这称为隧道。实际上,VNC 流量搭载在 SSH 协议上,导致它与服务器的所有通信都被加密。之所以称为 隧道,是因为 SSH 为 VNC 提供环绕式保护,而 VNC 就像在 SSH 内的隧道中一样运行。 SSH 隧道也可用于其他协议,如 POP、X 或 IMAP。
SSH 隧道与端口转发 一起工作,这基本上是一种将访问从一个特定端口转换到另一台机器上的不同端口的方法。通过端口转发,当客户端应用程序连接到机器 A 上运行的端口 A 时,它会透明地转发到机器 B 上运行的端口 B。客户端应用程序不知道这种转换,并认为它连接到原始端口。端口转发是 SSH 协议的特性之一。
有关 SSH 隧道的更多详细信息,请阅读本教程。
在本教程中,我们将 VNC 配置为在端口 5904(对于 joevnc)和 5905(对于 janevnc)上运行。
通过端口转发,我们可以将本地 VNC 客户端设置为连接到本地客户端计算机上的端口 5900,这可以映射到远程服务器上的端口 5905。这是用于 janevnc 连接的示例,但您可以轻松地对任何其他客户端执行相同的步骤。
当VNC客户端应用程序启动时,它可以指向本地主机上的5900端口,我们的端口转发将它透明地传输到远程服务器上的5905端口。
注意:您必须每次都启动 SSH 部分以确保连接安全。
操作系统
在 Mac 上,打开“终端”。
输入以下连接信息,确保将 your_server_ip
替换为远程服务器的 IP 地址:
ssh -L 5900:your_server_ip:5905 janevnc@your_server_ip -N
输入 janevnc 的 UNIX 密码。连接似乎挂起;只要您使用远程桌面,您就可以让它一直运行。
现在跳到 VNC 查看器说明。
视窗
为了保护 janevnc 的 VNC 会话,我们假设本地 Windows 计算机安装了 PuTTY。 PuTTY 是免费的,可以从这里下载。
如果 janevnc 的 VNC 和终端会话尚未关闭,请立即关闭它们。
启动腻子。在会话屏幕中,确保指定服务器 IP 地址并为连接提供描述性名称,然后单击保存按钮以保存连接详细信息。注意我们是如何在 Hostname 字段中指定 username@your_server_ip
的:

接下来,展开左侧导航窗格中的 SSH 菜单项,然后选择 X11 项。这显示了会话的 X11 转发属性。确保选中启用 X11 转发复选框。这确保 SSH 加密在服务器和客户端之间流动的 X Windows 流量:

最后,选择 SSH > 隧道。在源端口字段中键入 5900
。在目标字段中,指定服务器的名称或 IP 地址,后跟冒号和目标用户的 VNC 端口号。在我们的例子中,我们指定了 your_server_ip:5905
。
或者,您可以使用端口 5902。在这种情况下,2 将是 janevnc 的显示编号(记住 janevnc 运行 vncserver
命令时显示的消息)。
单击添加按钮,映射将添加到转发端口下。这是我们为 SSH 会话添加端口转发的地方;当用户通过端口 5900 连接到本地主机时,连接将自动通过 SSH 隧道连接到远程服务器的端口 5905。

返回 Sessions 项并保存 janevnc 的会话。单击“打开”按钮,将为 janevnc 打开一个新的终端会话。使用适当的 UNIX 密码以 janevnc 身份登录:

VNC 查看器
接下来再次启动 VNC 查看器。这次在VNC Server地址输入<^>,让VNC server选择加密方式:

单击“连接”按钮。
您仍然会看到对话框警告您有关未加密的会话,但这次您可以安全地忽略它。 VNC 查看器不知道它被转发到的端口(这是在刚刚启动的 SSH 会话中设置的)并假定您正在尝试连接到本地计算机。
接受此警告将显示熟悉的密码提示。输入 janevnc 的 VNC 密码以访问远程桌面。
那么你怎么知道会话是加密的呢?如果您考虑一下,我们已经在 SSH 会话中设置了端口转发。如果没有建立 SSH 会话,端口转发就不会起作用。事实上,如果您关闭终端窗口并注销 PuTTY 会话,然后尝试单独连接 VNC 查看器,则尝试连接到 localhost:5900
会显示以下错误消息:

因此,如果 localhost:5900
连接有效,您可以确信该连接已加密。
请记住,每次使用 VNC 时都需要先建立 SSH 连接,以确保您的连接始终是加密的。
结论
从 GUI 前端访问您的 CentOS Linux 系统可以使系统管理更加简单。您可以从任何客户端操作系统进行连接,而不必依赖基于 Web 的托管控制面板。与大多数控制面板相比,VNC 的占用空间要小得多。
尽管我们展示了两个普通用户如何连接他们的 VNC 客户端,但这在严肃的生产环境中几乎不实用。实际上,用户将具有用于访问服务器的定制应用程序或浏览器。为每个用户运行多个 VNC 服务还会对系统资源造成不必要的负担,更不用说与之相关的固有风险了。
如果您决定在生产 Linux 服务器上安装和运行 VNC,我们强烈建议仅将其用于管理目的。