我想欺骗一个程序来使用一个特殊的/etc/resolv.conf
文件,这反过来又会迫使它使用一个非标准的名称服务器。
显而易见的解决方案是重新创建除一个文件之外的整个文件系统并使用 chroot。但也许有一个更简单的方法可以做到这一点。
如何仅为特定进程更改文件的内容?提供了在许多情况下有效的解决方案,但不适用于/etc/resolv.conf
:LD_PRELOAD
当 libc 内的解析器打开时不会捕获/etc/resolv.conf
,并且绑定安装无法覆盖符号链接(如果链接目标丢失或之后链接发生更改) )。
编辑:一个相关的问题是如何在损坏的符号链接上安装文件?并且没有找到通用的解决方案
答案1
一个可以用overlayfs
以避免重复。如果是临时的,一切都可以使用 来完成/tmp
。与挂载命名空间相结合,这可以影响单个应用程序。从 root 开始准备(它确实可以与 user+mount 命名空间一起使用,其中普通用户被映射为 root,但如果没有特权帮助和/或最新的 pid 转换内核,用户映射将无助于做一些有用的事情)。
- 创建一个新的挂载命名空间
overlayfs
在此挂载命名空间中创建一个- 绑定重新安装这个overlayfs
/etc
- 更改内容(例如删除
/etc/resolv.conf
符号链接,然后创建具有自定义内容的常规文件/etc/resolv.conf
) - 仍然从此挂载命名空间运行应用程序
例子:
mkdir /tmp/upper /tmp/work /tmp/fake_etc
unshare -m
接下来的命令在新的挂载命名空间中运行:
mount -t overlay -olowerdir=/etc,upperdir=/tmp/upper,workdir=/tmp/work overlay_etc /tmp/fake_etc
然后/etc
用用来伪造其内容的那个覆盖:
mount --bind /tmp/fake_etc /etc
并进行更改(仅影响挂载命名空间中的overlayfs):
rm /etc/resolv.conf
echo nameserver 192.0.2.2 > /etc/resolv.conf
AFAIK 无法安装山命名空间来保留引用。如果需要,可以使用挂载命名空间中的 PID 引用来代替:
# echo $$
325304
在同一个 shell 中或在单独的(根)shell 中运行以下命令:
nsenter -t 325304 --mount
然后按照前面的示例(名称服务器 192.0.2.2 无法访问):
# su - -c 'ping stackexchange.com' someuser
ping: stackexchange.com: Name or service not known
而其他地方ping
将照常工作。
答案2
您可以使用bubblewrap
创建挂载命名空间。它包含在大多数发行版中,因为 Flatpak 需要它。
bwrap \
--bind / / \
--bind /home/user/resolv.conf /etc/resolv.conf \
binary parameter1 parameter2d