systemd 目录重定向
ssk-wh Lv4

systemd 中,可以使用 BindPathsBindReadOnlyPaths 来重定向应用访问的目录。这些选项可以在 .service 单元文件中设置,用于将特定的目录绑定到不同的位置,从而实现目录的重定向。systemd 的这种机制,可以让我们更好的控制应用的行为,增强系统的安全性。

BindPaths 是通过使用 Linux 内核的挂载命名空间(mount namespaces)和绑定挂载(bind mounts)来实现的。这些功能允许在特定进程的命名空间中修改文件系统的视图,而不会影响到其他进程或系统的全局视图。

挂载命名空间(mount namespaces)允许在特定进程的视图中隔离和重新配置挂载点。创建一个新的挂载命名空间后,进程可以在不影响其他进程的情况下修改其挂载点。
绑定挂载(bind mounts)是 Linux 文件系统功能的一部分,允许将一个目录或文件挂载到另一个目录。这使得同一目录或文件可以在多个位置同时出现。

以下是一个示例,展示如何配置一个 systemd 服务单元文件以重定向目录访问:

服务单元

假设你有一个名为 example.service 的服务单元文件,路径可能在 /etc/systemd/system/example.service/lib/systemd/system/example.service

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=Example Service

[Service]
ExecStart=/usr/bin/example-binary
BindPaths=/path/to/redirected:/path/to/original
# 或者使用只读绑定
# BindReadOnlyPaths=/path/to/redirected:/path/to/original

[Install]
WantedBy=multi-user.target

在这个示例中,/path/to/original 是应用程序预期访问的目录,/path/to/redirected 是你希望应用程序实际访问的目录。

修改单元文件后,重新加载 systemd 配置以使更改生效,在 example-binary 中访问 /path/to/original 目录的内容时,此时均会重定向至 /path/to/redirected 目录。

1
2
3
4
5
# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启动或重启服务
sudo systemctl restart example.service

其他配置

除了 BindPaths ,systemd还提供了其他的选项,使用者可以根据自己的需求选择合适的配置。

BindPaths

  • BindPaths=/target:/source
  • /source 目录绑定到 /target 目录。服务访问 /source 目录时实际上会访问 /target 目录。

BindReadOnlyPaths

  • BindReadOnlyPaths=/target:/source
  • BindPaths 类似,但绑定的目录为只读模式。服务只能读取 /target 目录,无法进行写操作。

ReadWritePaths

  • ReadWritePaths=/path/to/dir
  • 指定服务可以读写访问的目录。这些目录将被临时挂载为读写,即使根文件系统是只读的。

ReadOnlyPaths

  • ReadOnlyPaths=/path/to/dir
  • 指定服务可以只读访问的目录。这些目录将被临时挂载为只读。

InaccessiblePaths

  • InaccessiblePaths=/path/to/dir
  • 指定服务无法访问的目录。访问这些目录将导致权限错误。

TemporaryFileSystem

  • TemporaryFileSystem=/path/to/dir:mode=755,size=10M
  • 将指定目录挂载为临时文件系统(tmpfs),类似于 mount -t tmpfs。可以用来提供服务的临时存储空间。

PrivateTmp

  • PrivateTmp=yes
  • 启用服务的私有 /tmp 和 /var/tmp 目录,防止不同服务之间的临时文件相互影响。

ProtectSystem

  • ProtectSystem=full
  • 限制服务对系统文件和目录的写入访问。
    • ProtectSystem=yes:将 /usr 和其他系统目录设置为只读。
    • ProtectSystem=full:将 /etc 也设置为只读。
    • ProtectSystem=strict:将整个系统设置为只读,除了通过 ReadWritePaths 显式允许的目录。

ProtectHome

  • ProtectHome=yes
  • 限制服务对用户主目录的访问。
    • ProtectHome=yes:将用户主目录挂载为不可访问。
    • ProtectHome=read-only:将用户主目录挂载为只读。
    • ProtectHome=no:不限制用户主目录的访问。

MountFlags

  • MountFlags=slave
  • 设置挂载点的标志。通常用来隔离服务的挂载命名空间。

备注

部分环境中设置后并不能生效,报错内容如下:
image
你需要升级systemd和内核。

systemd在 233 版本之后对这一特性添加了支持。见systemd-man-BindPaths
内核版本不确定,笔者在4.19的内核上测试失败但在6.1.32的内核验证成功。

 Comments
Comment plugin failed to load
Loading comment plugin