在 systemd
中,可以使用 BindPaths
或 BindReadOnlyPaths
来重定向应用访问的目录。这些选项可以在 .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 | [Unit] |
在这个示例中,/path/to/original
是应用程序预期访问的目录,/path/to/redirected
是你希望应用程序实际访问的目录。
修改单元文件后,重新加载 systemd
配置以使更改生效,在 example-binary
中访问 /path/to/original
目录的内容时,此时均会重定向至 /path/to/redirected
目录。
1 | # 重新加载 systemd 配置 |
其他配置
除了 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
- 设置挂载点的标志。通常用来隔离服务的挂载命名空间。
备注
部分环境中设置后并不能生效,报错内容如下:
你需要升级systemd和内核。
systemd在 233 版本之后对这一特性添加了支持。见systemd-man-BindPaths。
内核版本不确定,笔者在4.19的内核上测试失败但在6.1.32的内核验证成功。