前言

挺早之前就已经把主力机迁移到了一台 LG Gram 上,原来的厚砖游戏本已经变成了旁路由 + 编译服务器。Gram 虽然优雅,但是,某些开发任务在它上面完成还是有些吃力的,比如跑 Android Studio ,跑是能跑,但是当单文件代码行数达到 1500+ 的时候,自动补全就已经卡的不行了。

所以,有没有什么解决方案能够实现类似 Windows 的远程桌面,连接到 Linux 桌面环境下呢?
嗯,KDE 自带了一个 Krfb ,可以将当前会话以 VNC 的形式共享出去。但是,这东西糊就算了,静置不动的时候网速都能跑到 20Mbps+ 实在是让人无法接受。

于是,我看上了一个叫做 Xrdp 的东西,那就配配看吧。

先说说我的环境:ArchLinux + KDE Plasma 5 (X11)。

跑起来

其实,光是成功的连上并进入桌面就花费了一番力气。这个东西的文档并不算很齐全,而且 journalctl 打出来的日志也并不能很好的点明问题所在,实在是有些头疼。

首先,安装核心软件包:

yay -S xrdp

然后,安装 Xorg 后端:
(三选一即可)

yay -S xorgxrdp-glamor (英特尔与 AMD 核显)
yay -S xorgxrdp (不使用显卡渲染,CPU 占用率会比较高)
yay -S xorgxrdp-nvidia (英伟达独显,没有测试过,可能需要根据安装时的提示修改配置文件)

接下来,在 /etc/X11/Xwrapper.config 中加入一行 allowed_users=anybody (如果没有这个文件则手动创建一个)。
(不知道为什么,这个步骤没有出现在英文版的 arch wiki 中,但没有它远程桌面是起不来的)

再接下来,创建 ~/.xinitrc ,并写入 /usr/lib/plasma-dbus-run-session-if-needed startplasma-x11
(正常步骤应该是修改原有的 .xinitrc ,但是,再次,我压根就没有这个东西,于是手动创建一个)

启用服务,再重启一下系统:

sudo systemctl enable xrdp.service
sudo systemctl enable xrdp-sesman.service
sudo reboot

好,可以连接了:

输入用户名,密码,Session 就选 Xorg ,登进去应该就能够看到桌面了...

花里胡哨的问题

Xrdp 的使用感受确实要比 VNC 好多了,但是小问题还是不少的。

无法弹出授权提示框

授权提示框是指这个东西:

在 Xrdp 下,这个框框不会弹出,对应的操作也会被直接拒绝。

解决方案一:

此类授权是由 polkit 负责的,我们可以修改 polkit 的配置文件,干脆直接允许所有的授权请求,虽然这不干净而且有点危险,但也算是能用:

/etc/polkit-1/rules.d/49-nopasswd_global.rules

/* Allow members of the wheel group to execute any actions
 * without password authentication, similar to "sudo NOPASSWD:"
 */
polkit.addRule(function(action, subject) {
    if (subject.isInGroup("wheel")) {
        return polkit.Result.YES;
    }
});

解决方案二:

这种解决方案出现在了 arch wiki 上,我们需要编辑 /etc/pam.d/system-auth 并注释掉所有包含 systemd_home 的行。

类似于这样:

#%PAM-1.0

auth       required                    pam_faillock.so      preauth
# Optionally use requisite above if you do not want to prompt for the password
# on locked accounts.
#-auth      [success=2 default=ignore]  pam_systemd_home.so
auth       [success=1 default=bad]     pam_unix.so          try_first_pass nullok
auth       [default=die]               pam_faillock.so      authfail
auth       optional                    pam_permit.so
auth       required                    pam_env.so
auth       required                    pam_faillock.so      authsucc
# If you drop the above call to pam_faillock.so the lock will be done also
# on non-consecutive authentication failures.

#-account   [success=1 default=ignore]  pam_systemd_home.so
account    required                    pam_unix.so
account    optional                    pam_permit.so
account    required                    pam_time.so

#-password  [success=1 default=ignore]  pam_systemd_home.so
password   required                    pam_unix.so          try_first_pass nullok shadow sha512
password   optional                    pam_permit.so

#-session   optional                    pam_systemd_home.so
session    required                    pam_limits.so
session    required                    pam_unix.so
session    optional                    pam_permit.so

在这之后授权框能够正常弹出了,但是这种注释想必会破坏一些东西,具体可以在该 issue 中了解详情。

(发现这种方案结合下面的自动登录会导致远程会话黑屏)

外接设备权限问题

这个问题其实和 xrdp 没有直接的关系。
在物理机未登录时,无论是登录 xrdp 还是 ssh ,都无法使用一些外接设备,比如:

$ adb shell
adb: insufficient permissions for device
See [http://developer.android.com/tools/device.html] for more information

对于 adb 来说,解决方法很简单,以 root 身份重启 adb server 即可:

$ adb kill-server
$ sudo adb start-server

但是,像 Dolphin 里的 MTP 就没这么容易解决了,因为 Dolphin 不被允许使用 root 身份运行。

造成这个问题的原因在于 systemd-logind 提供了用于多人一机的功能 “seat” 。 seat 基于 udev 规则工作,可以将不同的设备分配给不同的 session 。
但遗憾的是,像 ssh,xrdp 这样的远程会话,并不能被绑定到默认的 seat0 ,于是在没有物理的会话登录时,xrdp 和 ssh 会话都没法直接正常使用这些设备。

可以使用 loginctl 命令来查看当前会话及其绑定的 seat :

$ loginctl
SESSION  UID USER   SEAT  TTY
      1 1000 libxzr seat0

我也尝试过在 xorg 的启动参数中指定 -seat seat0 来强行绑定,但很遗憾并没有效果,于是最终想出了一个肮脏的绕过方法:

首先配置 SDDM 的自动登录:

然后配置在登录时自动运行锁屏脚本:

这样,既可以保证物理机上一定有一个 seat0 的会话正在运行,维持这些外接设备的可访问性,又不至于让开机密码消失。虽然手段有些肮脏,但结果算是好的。

在 stackexchange 上也有关于为 ssh 会话绑定 seat 的问题,可是截止目前为止还没有有效的回复:
https://unix.stackexchange.com/questions/709837/how-to-attach-virtual-ssh-session-to-systemd-seat0

baloo_file_extr 高 CPU 占用

具体原因不太清楚,但确实是开始使用 xrdp 之后出现的。
症状为 baloo_file_extr 持续占用 CPU (+ PID 暴增,因为它好像在不断重启) ,同时伴有 systemd-coredump 的 CPU 占用以及 journalctl 中的 crashdump 刷屏。
初步判断为文件索引系统出现了奇怪的状况,解决方法为关闭文件索引并重启:

$ balooctl disable
$ sudo reboot

参考资料

https://alvin.red/2021/11/06/archlinux-xrdp/
https://wiki.archlinux.org/title/xrdp
https://wiki.archlinuxcn.org/zh-hans/Xrdp
https://wiki.archlinux.org/title/Polkit
https://wiki.archlinux.org/title/xorg_multiseat