有些时候,使用远程控制能够简化不少运维和操作的事情。

本篇文章分享如何通过开源工具 “Urch(Ubuntu Remote Control Helper)” 让 Ubuntu 原生的远程控制(远程桌面)功能稳定可靠。

方案已经经过 Ubuntu 22.04 LTS 和最新版本的 Ubuntu 22.10 两个版本的验证。

写在前面

虽然 Ubuntu Desktop 版本的操作系统默认提供了 “远程桌面” 的功能。但是官方功能使用起来有一些限制,尤其是对于无人职守的自动化场景来说

  1. 原生的登录功能,需要我们的设备连接显示器,并解锁登录才能够使用。
  2. 原生的桌面共享,设置的用于连接的用户密码,会随着系统重启而使用随机字符串填充,影响我们登录。
  3. 因为开关远程共享功能,并不像设置密码这类操作需要二次确认,导致可能出现误关闭功能,无法连接设备。

或许,从官方设计的初衷来看,最推荐使用的场景是类似从前的“QQ远程协助”的场景:默认启动的模式,是使用“用户在界面中准许连接”的连接认证模式。

但如果,我们有靠谱的方式来控制远程桌面服务的开启关闭,确保我们开启的时候,不论是让连接密码稳定,还是系统相关的服务配置始终保持可用的,“原生的远程控制”功能,足够我们的日常使用,不需要安装任何三方的远程桌面控制软件

为了解决上面的问题,我又写了一个程序。

开源软件 Ubuntu Remote Control Helper

这次的程序依旧是使用 Golang 完成的,大概花了 200 多行来进行实现。

Urch 项目 GitHub 开源仓库

项目完整代码开源在soulteary/ubuntu-remote-control-helper,欢迎自取、提交反馈和 PR,以及 “一键三连”。

关于项目的使用和介绍,下文中会聊到。

系统安装和前置准备

关于 Ubuntu 系统的安装,你可以参考这篇文章《在笔记本上搭建高性价比的 Linux 学习环境:基础篇》。本文中测试了 Ubuntu 22.04 和 Ubuntu 22.10 两个 Desktop 版本。

不过,默认的桌面环境不支持我们使用 ssh 连接设备,我们需要先在机器上执行命令,安装 openssh-server

sudo apt install -y openssh-server

在完成 SSH 服务器软件的安装后,我们就能够使用自己的顺手的设备,通过 ssh 来连接这台设备/服务器啦。

关于服务器的其他配置,你也可以参考上面文章中“进行系统基础配置”部分来搞定,就不过多赘述了。

首次登录系统后的相关设置

首次登录系统后,我们需要打开“系统设置”,找到“桌面共享”,点击一次打开共享桌面,让系统自动配置和生成一次“登录凭证”。

初始化“远程控制”功能

为了避免一些预期之外的事情,我们在“系统设置”中选择当前用户,打开“自动登录”。

另外,为了避免在使用软件过程中,尤其是软件自动化职守的过程中,系统会弹出“认证登录框”影响程序运行。我们需要阅读本文中的 “聊聊原理:解决系统会弹出认证登录框的问题”,更新系统设置,解决这个问题。

好了,接下来我们来使用开源软件 “Urch(Ubuntu Remote Control Helper)” 完成剩余的操作。

快速配置稳定的 Ubuntu 远程控制

想要快速的让 Ubuntu 的远程控制功能稳定可靠,最快的方式是使用下面的两行命令,完成 Urch 安装脚本的下载和快速配置。

# 下载安装程序,并使用 bash 执行安装程序
wget https://github.com/soulteary/ubuntu-remote-control-helper/raw/main/example/installer.sh
bash installer.sh

如果你遇到了网络问题,那么可以在命令前添加 https_proxy 变量来解决问题,比如这样:

https_proxy=xx.xx.xx.xx:xx wget https://github.com/soulteary/ubuntu-remote-control-helper/raw/main/example/installer.sh
https_proxy=xx.xx.xx.xx:xx bash installer.sh

当我们完成安装之后,需要先重启一次系统,让相关依赖生效。重启完毕之后,我们先执行一次 urch 命令,完成必要的远程控制相关的配置更新。

命令执行完毕,不错意外,你将看到类似下面的日志输出:

# urch
Remote Control Helper
check remote control credentials and correct the problem...
the configuration has been ensured to be correct.

当你看到 “the configuration has been ensured to be correct” 的时候,所有的基础配置就都完毕啦。

不过,如果执行程序的时候,并没有指定参数的话,用户和密码会设置为默认的 soulteary

为了让我们能够使用自己喜欢的账号和密码来登录系统,我们可以在执行命令的时候,通过下面的两种方法,来配置我们期望的用户名和密码。

设置用户:通过环境变量指定

第一种方式,是通过在使用命令时,指定环境变量,例如 UBUNTU_REMOTE_USER=admin UBUNTU_REMOTE_PASS=password urch

# UBUNTU_REMOTE_USER=admin UBUNTU_REMOTE_PASS=password urch
Remote Control Helper
set remote username by env: admin
set remote password by env: password
check remote control credentials and correct the problem...
[gnome-remote-desktop] Find Process: 2152.
[gnome-remote-desktop] Process has been killed.
the configuration has been ensured to be correct.

程序执行完毕,你的用户设置就生效啦。

设置用户:通过命令行参数指定

第二种方式,是通过指定命令行参数,来指定用户名和密码,例如 urch --user=user --pass=pass

# urch --user=user --pass=pass
Remote Control Helper
set remote username by cli: user
set remote password by cli: pass
check remote control credentials and correct the problem...
[gnome-remote-desktop] Find Process: 4489.
[gnome-remote-desktop] Process has been killed.
the configuration has been ensured to be correct.

好了,了解完程序的两种设置用户、密码的方式,我们来更新系统中唯一一处需要调整的配置内容。

确保 Urch 程序能够持续运行

在系统的 /etc/supervisor/conf.d/urch.conf 路径下,保存着 Urch 的 supervisor 配置文件,能够帮助我们让 Urch 始终稳定运行在系统中。

而 Urch 能够持续运行,能够确保我们远程控制账号始终正确的设置为我们想要的内容。

默认的配置如下:

[program:urch]
command=xvfb-run --auto-servernum --server-num=1 urch --daemon=1 --user=soulteary --pass=soulteary
user=soulteary
autostart=true
startsecs=3
startretries=100000
autorestart=true
stderr_logfile=/tmp/urch.err.log
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=10
stdout_logfile=/tmp/urch.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10

和上文提到的一样,我们需要调整这里参数中的内容,将默认的 --user=soulteary --pass=soulteary 替换为你自己想要使用的用户名和密码。

我们使用 sudo vi /etc/supervisor/conf.d/urch.conf 可以对配置进行相同的调整。在完成配置中的参数调整之后,执行下面的命令,来重启 supervisor,让我们的新配置内容生效:

sudo service supervisor restart

等待程序重启完毕,Urch 就会每隔一分钟检查一次我们的登录用户名和密码,以及相关的远程控制配置是否正常啦。如果遇到配置不正常的情况,比如配置由于系统重启而被重置的情况,它就会自动的将问题纠正过来。

接下来,我们只需要使用你的支持 RDP 的远程控制软件,配置好你在上面配置的账号密码,并连接你的服务器的默认端口,就能愉快的开始远程控制啦。

使用 RDP 协议远程控制 Ubuntu

程序未来的设计规划

使用 AI 应用绘制的 Urch Logo

在文章的开头处,我们提到了,Ubuntu 默认的交互场景中,或许是出于安全考虑,默认其实会每次重启都将远程控制密码重置,以及提供了选择性允许连接的功能。

当前的版本中,我们已经能够确保远程控制功能是稳定可靠的。所以接下来的程序功能中,我或许会加上两个有意思的小功能,和官方一样,增强连接使用时的安全性:

  1. 通过接口或者规则文件,动态的开关服务器的远程控制功能。
  2. 以及提供动态登录密码,让每次都登录都变的更加安全。

好啦,聊完使用部分,本篇文章就讲完一半啦。

如果你对原理和踩坑部分感兴趣,可以继续阅读,如果你只是想解决问题,上面的文章内容,应该能够帮到你了。别忘记给软件“一键三连”~

聊聊原理

虽然,在上面的文章里,我们轻描淡写的就解决了问题。

但其实,软件想要稳当的运行,提供功能,需要解决不少细碎的问题。

实现自动更新系统配置的原理

软件提供的主要功能之一,是自动对系统远程控制相关功能进行配置,并保证配置内容是“稳定的”。

如果不使用程序,我们可以通过系统提供的 gsettings 命令,来得到上文中,我们使用“系统设置”设置的远程控制相关的配置。

比如,先使用 gsettings list-schemas|grep remote-desktop 可以得到 Ubuntu 原生的“远程桌面”相关的配置项。

# gsettings list-schemas|grep remote-desktop

org.gnome.desktop.remote-desktop
org.gnome.desktop.remote-desktop.rdp
org.gnome.desktop.remote-desktop.vnc

然后,使用 gsettings list-keys 可以得到具体的配置项中的子项名称:

# gsettings list-keys org.gnome.desktop.remote-desktop.rdp

enable
screen-share-mode
tls-cert
tls-key
view-only

接着,使用 gsettings get 可以获得具体设置子项中的数值:

# gsettings get 'org.gnome.desktop.remote-desktop.rdp' 'enable'

true

以及,我们可以通过使用 gsettings set 来完成配置项的数值调整。

gsettings set 'org.gnome.desktop.remote-desktop.rdp' 'enable' true

将上面的操作使用程序来实现,就完成了配置的基础自动化。

远程登录凭证(用户名和密码)的修改原理

虽然用于“远程控制”的用户名和密码也属于配置,但是配置的麻烦程度远超上面提到的系统配置。

Ubuntu 中的远程登录凭证保存在系统的 Keyring 中,想要使用程序的方式去操作它,我们需要先安装一个依赖工具 libsecret-tools

sudo apt-get install -y libsecret-tools

完成工具安装之后,我们就可以使用命令 secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials 来获取系统中保存的数据啦:

# secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials
{'username': <'soulteary'>, 'password': <'&@RhOxaBakTe'>}

日志输出中的 {'username': <'soulteary'>, 'password': <'&@RhOxaBakTe'>} 就是系统所使用的保存账号密码的格式啦,修改其中的内容,然后将内容回写到系统中,就能够完成登录凭证的调整了。

如果我们希望完成登录凭证的调整,可以通过执行 secret-tool store 命令,来完成系统中配置的更新:

secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials

不过,这种方式将会触发交互式的操作确认,比较不利于实现程序完成操作。

所以,我们可以借助下面的命令,通过管道的方式,自动完成交互式的输入。

printf "{'username': <'soulteary'>, 'password': <'soulteary'>}" | secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials

完成设置之后,就可以使用 secret-tool lookup 检查设置内容是否生效:

# secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials
{'username': <'soulteary'>, 'password': <'soulteary'>}

当然,上面这两条命令,如果是在“系统未开启自动登录”、“用户停留在锁屏界面”、“系统默认使用的加密 Keyring”、“使用后台程序启动的 Urch” 几类场景下,是都无法简单执行成功的。

所以,还需要解决上面提到的几个问题。

为什么要开启系统自动登录

尤其是 Desktop 版本的 Ubuntu 操作系统,如果我们不开启“用户自动登录”,则会遇到两个问题。

第一个问题是“原生的远程出桌面”功能不会伴随系统启动。Ubuntu Remote Desktop 功能,只有在用户首次登录解除屏幕锁定之后,才会真的启动,本质是调用 systemd --user ,然后启动相关进程任务:

/lib/systemd/systemd --user
...
/usr/libexec/gnome-remote-desktop-daemon

第二个问题是,在我们没有调整 Keyring 权限之前,是无法通过程序自动的更新用户登录凭据的。

举个例子,如果你直接使用 ssh 命令登录服务器,没有通过 GUI 的方式登录系统并解锁屏幕,那么当你执行类似下面的关键命令的时候,会遇到类似下面的错误:

# printf "{'username': <'soulteary'>, 'password': <'soulteary'>}" | secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials

secret-tool: Cannot create an item in a locked collection

想要解决上面这两个问题,我们只需要进入系统,在系统设置中选择我们的用户,然后设置用户为“自动登录”即可。

Ubuntu 桌面版和我们的手机系统一样,会自动开启桌面锁定。但是系统锁定后,也是会影响 Urch 保障系统配置为正常值的设置。

除了在系统设置界面中关闭界面锁定之外,我们还可以执行下面的命令,来解决这个问题。

gsettings set 'org.gnome.desktop.session' 'idle-delay' 0

当然,你不执行也无所谓,Urch 会检测这个配置,并自动关闭这个功能,避免运行环境不靠谱。

解决系统会弹出认证登录框的问题

当我们使用编程方式(调用 API)来设置系统登录凭证的时候,可能会遇到动作被“卡住”的情况。此时,系统会弹出一个“认证登录”的确认窗口,需要我们输入密码,点击确认按钮,然后才能完成操作。

系统弹出的强制认证对话框

但是如果程序是无人值守状态,即没有用户登录在系统上时,遇到了这个问题,那么程序就无法保障我们的配置都是正常的啦。

想要彻底解决这个问题,最简单的方案是登录系统,搜索 “keyring”,打开系统密钥管理应用。

打开系统的 Keyring 管理应用

接着,找到包含 Remote Desktop 相关的记录,然后在左侧的菜单上右键,选择“修改密码”,输入当前密码点击确认之后,系统会要求我们输入新密码以及对密码进行二次确认,这里我们不输入任何内容,会看到系统提示我们这样做将会“解密存储的密码”,点击确认即可。

取消对远程登录相关信息的加密存储

完成操作后,我们重启系统。

再次进入系统之后,我们再次执行刚刚的命令,会发现不会再出现“系统弹窗认证”的问题啦。

printf "{'username': <'soulteary'>, 'password': <'soulteary'>}" | secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials

无外接显示器登录原理

当我们没有给 Ubuntu Desktop 安装显示器的时候,如果我们想用 RDP 软件来连接系统,进行 GUI 登录,会得到类似 “The disconnection was initiated by an administrative tool on the server in another session”的错误。

当然,默认情况不论是 RDP 还是市面上的三方商业远程控制软件都是如此。

解决这个问题的最佳方案是安装“虚拟桌面”:

sudo apt-get install -y xserver-xorg-core xserver-xorg-video-dummy

完成依赖安装之后,我们对 xorg 进行配置(参考 俄罗斯小哥 dragolabs的总结):

Section "Device"
    Identifier  "Configured Video Device"
    Driver      "dummy"
EndSection

Section "Monitor"
    Identifier  "Configured Monitor"
    HorizSync 31.5-48.5
    VertRefresh 50-70
EndSection

Section "Screen"
    Identifier  "Default Screen"
    Monitor     "Configured Monitor"
    Device      "Configured Video Device"
    DefaultDepth 24
    SubSection "Display"
    Depth 24
    Modes "1920x1080"
    EndSubSection
EndSection

将上面内容保存在 /etc/X11/xorg.conf 路径下,完成配置后,需要重启生效。

最后

本篇文章目前提到了,如何让 Ubuntu 原生的远程控制稳定可靠,下一篇相关的内容里,我们来聊聊细粒度的控制,以及让这个远程管理会话安全可靠。

自从能够使用 AI 应用绘图之后,写起来源项目的负担更轻了,因为再也不用头疼如何解决 Logo 设计啦! :-D

–EOF