本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2023年04月11日 统计字数: 9488字 阅读时间: 19分钟阅读 本文链接: https://soulteary.com/2023/04/11/make-ubuntu-native-remote-control-reliable-with-urch.html ----- # 使用 Urch 让 Ubuntu 原生远程控制功能稳定可靠 有些时候,使用远程控制能够简化不少运维和操作的事情。 本篇文章分享如何通过开源工具 “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 开源仓库](https://attachment.soulteary.com/2023/04/11/urch-repo.jpg) 项目完整代码开源在[soulteary/ubuntu-remote-control-helper](https://github.com/soulteary/ubuntu-remote-control-helper),欢迎自取、提交反馈和 PR,以及 “一键三连”。 关于项目的使用和介绍,下文中会聊到。 ### 系统安装和前置准备 关于 Ubuntu 系统的安装,你可以参考这篇文章[《在笔记本上搭建高性价比的 Linux 学习环境:基础篇》](https://soulteary.com/2022/06/21/building-a-cost-effective-linux-learning-environment-on-a-laptop-the-basics.html)。本文中测试了 Ubuntu 22.04 和 Ubuntu 22.10 两个 Desktop 版本。 不过,默认的桌面环境不支持我们使用 `ssh` 连接设备,我们需要先在机器上执行命令,安装 `openssh-server`: ```python sudo apt install -y openssh-server ``` 在完成 SSH 服务器软件的安装后,我们就能够使用自己的顺手的设备,通过 `ssh` 来连接这台设备/服务器啦。 关于服务器的其他配置,你也可以参考上面文章中“[进行系统基础配置](https://soulteary.com/2022/06/21/building-a-cost-effective-linux-learning-environment-on-a-laptop-the-basics.html#%E8%BF%9B%E8%A1%8C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE)”部分来搞定,就不过多赘述了。 ### 首次登录系统后的相关设置 首次登录系统后,我们需要打开“系统设置”,找到“桌面共享”,点击一次打开共享桌面,让系统自动配置和生成一次“登录凭证”。 ![初始化“远程控制”功能](https://attachment.soulteary.com/2023/04/11/initial-desktop-share.jpg) 为了避免一些预期之外的事情,我们在“系统设置”中选择当前用户,打开“自动登录”。 另外,为了避免在使用软件过程中,尤其是软件自动化职守的过程中,系统会弹出“认证登录框”影响程序运行。我们需要阅读本文中的 “聊聊原理:解决系统会弹出认证登录框的问题”,更新系统设置,解决这个问题。 好了,接下来我们来使用开源软件 “Urch(Ubuntu Remote Control Helper)” 完成剩余的操作。 ## 快速配置稳定的 Ubuntu 远程控制 想要快速的让 Ubuntu 的远程控制功能稳定可靠,最快的方式是使用下面的两行命令,完成 Urch 安装脚本的下载和快速配置。 ```bash # 下载安装程序,并使用 bash 执行安装程序 wget https://github.com/soulteary/ubuntu-remote-control-helper/raw/main/example/installer.sh bash installer.sh ``` 如果你遇到了网络问题,那么可以在命令前添加 `https_proxy` 变量来解决问题,比如这样: ```bash 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` 命令,完成必要的远程控制相关的配置更新。** 命令执行完毕,不错意外,你将看到类似下面的日志输出: ```bash # 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`: ```bash # 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`: ```bash # 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 能够持续运行,能够确保我们远程控制账号始终正确的设置为我们想要的内容。 默认的配置如下: ```bash [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`,让我们的新配置内容生效: ```bash sudo service supervisor restart ``` 等待程序重启完毕,Urch 就会每隔一分钟检查一次我们的登录用户名和密码,以及相关的远程控制配置是否正常啦。如果遇到配置不正常的情况,比如配置由于系统重启而被重置的情况,它就会自动的将问题纠正过来。 接下来,我们只需要使用你的支持 RDP 的远程控制软件,配置好你在上面配置的账号密码,并连接你的服务器的默认端口,就能愉快的开始远程控制啦。 ![使用 RDP 协议远程控制 Ubuntu](https://attachment.soulteary.com/2023/04/11/ubuntu-with-rdp.jpg) ## 程序未来的设计规划 ![使用 AI 应用绘制的 Urch Logo](https://attachment.soulteary.com/2023/04/11/logo-urch.jpg) 在文章的开头处,我们提到了,Ubuntu 默认的交互场景中,或许是出于安全考虑,默认其实会每次重启都将远程控制密码重置,以及提供了选择性允许连接的功能。 当前的版本中,我们已经能够确保远程控制功能是稳定可靠的。所以接下来的程序功能中,我或许会加上两个有意思的小功能,和官方一样,增强连接使用时的安全性: 1. 通过接口或者规则文件,动态的开关服务器的远程控制功能。 2. 以及提供动态登录密码,让每次都登录都变的更加安全。 好啦,聊完使用部分,本篇文章就讲完一半啦。 如果你对原理和踩坑部分感兴趣,可以继续阅读,如果你只是想解决问题,上面的文章内容,应该能够帮到你了。别忘记给软件“一键三连”~ ## 聊聊原理 虽然,在上面的文章里,我们轻描淡写的就解决了问题。 但其实,软件想要稳当的运行,提供功能,需要解决不少细碎的问题。 ### 实现自动更新系统配置的原理 软件提供的主要功能之一,是自动对系统远程控制相关功能进行配置,并保证配置内容是“稳定的”。 如果不使用程序,我们可以通过系统提供的 `gsettings` 命令,来得到上文中,我们使用“系统设置”设置的远程控制相关的配置。 比如,先使用 `gsettings list-schemas|grep remote-desktop` 可以得到 Ubuntu 原生的“远程桌面”相关的配置项。 ```python # 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` 可以得到具体的配置项中的子项名称: ```python # gsettings list-keys org.gnome.desktop.remote-desktop.rdp enable screen-share-mode tls-cert tls-key view-only ``` 接着,使用 `gsettings get` 可以获得具体设置子项中的数值: ```python # gsettings get 'org.gnome.desktop.remote-desktop.rdp' 'enable' true ``` 以及,我们可以通过使用 `gsettings set` 来完成配置项的数值调整。 ```python gsettings set 'org.gnome.desktop.remote-desktop.rdp' 'enable' true ``` 将上面的操作使用程序来实现,就完成了配置的基础自动化。 ### 远程登录凭证(用户名和密码)的修改原理 虽然用于“远程控制”的用户名和密码也属于配置,但是配置的麻烦程度远超上面提到的系统配置。 Ubuntu 中的远程登录凭证保存在系统的 Keyring 中,想要使用程序的方式去操作它,我们需要先安装一个依赖工具 `libsecret-tools`: ```bash sudo apt-get install -y libsecret-tools ``` 完成工具安装之后,我们就可以使用命令 `secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials` 来获取系统中保存的数据啦: ```bash # secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials {'username': <'soulteary'>, 'password': <'&@RhOxaBakTe'>} ``` 日志输出中的 `{'username': <'soulteary'>, 'password': <'&@RhOxaBakTe'>}` 就是系统所使用的保存账号密码的格式啦,修改其中的内容,然后将内容回写到系统中,就能够完成登录凭证的调整了。 如果我们希望完成登录凭证的调整,可以通过执行 `secret-tool store` 命令,来完成系统中配置的更新: ```bash secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials ``` **不过,这种方式将会触发交互式的操作确认,比较不利于实现程序完成操作。** 所以,我们可以借助下面的命令,通过管道的方式,自动完成交互式的输入。 ```bash printf "{'username': <'soulteary'>, 'password': <'soulteary'>}" | secret-tool store -l 'GNOME Remote Desktop RDP credentials' xdg:schema org.gnome.RemoteDesktop.RdpCredentials ``` 完成设置之后,就可以使用 `secret-tool lookup` 检查设置内容是否生效: ```bash # secret-tool lookup xdg:schema org.gnome.RemoteDesktop.RdpCredentials {'username': <'soulteary'>, 'password': <'soulteary'>} ``` **当然,上面这两条命令,如果是在“系统未开启自动登录”、“用户停留在锁屏界面”、“系统默认使用的加密 Keyring”、“使用后台程序启动的 Urch” 几类场景下,是都无法简单执行成功的。** 所以,还需要解决上面提到的几个问题。 ### 为什么要开启系统自动登录 尤其是 Desktop 版本的 Ubuntu 操作系统,如果我们不开启“用户自动登录”,则会遇到两个问题。 第一个问题是“原生的远程出桌面”功能不会伴随系统启动。Ubuntu Remote Desktop 功能,只有在用户首次登录解除屏幕锁定之后,才会真的启动,本质是调用 `systemd --user` ,然后启动相关进程任务: ```bash /lib/systemd/systemd --user ... /usr/libexec/gnome-remote-desktop-daemon ``` 第二个问题是,在我们没有调整 Keyring 权限之前,是无法通过程序自动的更新用户登录凭据的。 举个例子,如果你直接使用 `ssh` 命令登录服务器,没有通过 GUI 的方式登录系统并解锁屏幕,那么当你执行类似下面的关键命令的时候,会遇到类似下面的错误: ```bash # 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 保障系统配置为正常值的设置。 除了在系统设置界面中关闭界面锁定之外,我们还可以执行下面的命令,来解决这个问题。 ```bash gsettings set 'org.gnome.desktop.session' 'idle-delay' 0 ``` 当然,你不执行也无所谓,Urch 会检测这个配置,并自动关闭这个功能,避免运行环境不靠谱。 ### 解决系统会弹出认证登录框的问题 当我们使用编程方式(调用 API)来设置系统登录凭证的时候,可能会遇到动作被“卡住”的情况。此时,系统会弹出一个“认证登录”的确认窗口,需要我们输入密码,点击确认按钮,然后才能完成操作。 ![系统弹出的强制认证对话框](https://attachment.soulteary.com/2023/04/11/require-auth.jpg) **但是如果程序是无人值守状态,即没有用户登录在系统上时,遇到了这个问题,那么程序就无法保障我们的配置都是正常的啦。** 想要彻底解决这个问题,最简单的方案是登录系统,搜索 “keyring”,打开系统密钥管理应用。 ![打开系统的 Keyring 管理应用](https://attachment.soulteary.com/2023/04/11/keyring-app.jpg) 接着,找到包含 Remote Desktop 相关的记录,然后在左侧的菜单上右键,选择“修改密码”,输入当前密码点击确认之后,系统会要求我们输入新密码以及对密码进行二次确认,这里我们不输入任何内容,会看到系统提示我们这样做将会“解密存储的密码”,点击确认即可。 ![取消对远程登录相关信息的加密存储](https://attachment.soulteary.com/2023/04/11/encrypted.jpg) 完成操作后,我们重启系统。 再次进入系统之后,我们再次执行刚刚的命令,会发现不会再出现“系统弹窗认证”的问题啦。 ```bash 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 还是市面上的三方商业远程控制软件都是如此。** 解决这个问题的最佳方案是安装“虚拟桌面”: ```bash sudo apt-get install -y xserver-xorg-core xserver-xorg-video-dummy ``` 完成依赖安装之后,我们对 `xorg` 进行配置(参考 [俄罗斯小哥 dragolabs](https://gist.github.com/dragolabs/8e559113567faed32327ef24fdce775b)的总结): ```bash 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