解释

解释

我的设置:

  • /etc/ns-shared-resolv.conf定期写入nameserver x.x.x.x,并通过脚本进行更新
  • /etc/netns/ag2/resolv.conf是上述内容的符号链接(以及ag3, ag4).. 用于根网络中的中央 DNS 设置o
  • ag2在netns中运行的长期服务(通过ip netns exec ag2 ...,从服务启动systemd

会发生什么:

一切正常……持续了几个小时。之后,DNS 请求失败。使用时tcpdump我可以看到 DNS 请求发往“错误的地方”……root 中的 DNS 服务器/etc/resolv.conf,而不是 netns 服务器。

同时,当它不起作用时,ip netns exec ag2 cat /etc/resolv.conf它会显示正确的设置。

如果我启动一个新ip netns exec ag2 bashshell,它会获得“正确的” resolv.conf(符号链接到的/run/systemd/resolve/stub-resolv.conf,它会使用的内容“实时”更新ns-shared-resolv.conf

所以就像过了一会儿,长时间运行的进程就获得了根源resolv.conf

问题:

  1. 为什么会发生这种情况/我如何诊断它在这段随机时间之后为什么使用“错误的”resolv.conf/DNS 服务器?

  2. 我能否以某种方式让 ubuntu 默认 DNSsystemd-resolv服务器在 netns-es 中运行,这样我就不需要做这种疯狂的事情了?

编辑:喜欢这个人!-->https://www.reddit.com/r/linuxquestions/comments/dnh8wq/comment/fo1tbty/?utm_source=share&utm_medium=web2x&context=3

答案1

解释

当您将文件放入时/etc/netns/.../resolv.conf,它将导致在设置命名空间时ip netns exec对其进行绑定挂载。/etc/resolv.conf

这通常有效,但当发生原子替换时/etc/resolv.conf,绑定挂载所在的 inode 会发生变化。我还没有确认这是为什么,但我大胆猜测,绑定挂载在文件上实际上附加到 inode 而不仅仅是文件名,而不是覆盖在恰好存在的任何文件之上。

当您使用 NetworkManager 或 resolvconf 之类的工具来管理您的 时/etc/resolv.conf,当这些工具替换文件以进行原子更新时,这将导致绑定挂载神秘消失。

resolv.conf这很可能是您的被覆盖的原因。

解决方法

有几种方法可以解决这个问题:

  1. 您可以禁用任何更新 /etc/resolv.conf 的功能,并选择自行管理。(其他答案这里指出了如何使用 NetworkManager 禁用它。)

  2. 您可以(可能应该)强制将端口 53 上的传出 UDP 和 TCP 连接发送到您选择的 DNS 服务器。这将有效地覆盖/etc/resolv.conf。使用 iptables 执行此操作非常容易,请执行以下操作:

    ip netns exec "${NAMESPACE}" iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to "${NAMESERVER}"
    ip netns exec "${NAMESPACE}" iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to "${NAMESERVER}"
    

    ${NAMESPACE}命名空间在哪里以及${NAMESERVER}您希望强制使用的 DNS 服务器在哪里。请注意,这会破坏故障转移。)

    (请随意更新这个答案,了解如何使用其他防火墙工具(如 nftables)执行此操作的信息。我个人不知道,所以我宁愿不这样做。)

    尽管这种方法在重启后不是持久的,至少对于 iptables 来说是这样,但它是网络命名空间本身状态的一部分,因此在使用多个ip netns exec命令进入 netns 时它是持久的。

故障排除

您应该确保它确实正常工作,因为还有其他几种方式会导致 DNS 泄漏ip netns exec。要彻底清除 DNS 泄漏,您需要确保 DNS 解析始终在 netns 内部进行。

systemd-已解决

如果你正在使用 systemd-resolved,可能需要确保它在命名空间内被阻止或禁用。glibc 选择使用 systemd solved 可能会受到以下因素的影响:1. /etc/resolve.conf,其中 systemd-resolved 可能会使用类似以下方式将自己设置为解析器nameserver 127.0.0.1:53(将被覆盖,而ip exec netns无需执行任何操作);2. /etc/nsswitch.conf,glibc 读取文件以确定哪个国家安全战略解析名称时要使用的模块。通常,如果该hosts:行包含resolve,则表示正在使用 systemd-resolved。如果它仅包含其他条目,则很可能未使用。使用 处的名称服务器的传统 DNS 解析/etc/resolv.conf通过模块进行dns

一个可能的解决方法是添加一个文件,/etc/netns/${NAMESPACE}/nsswitch.conf内容如下:

...
hosts: dns
...

(其中的各个...部分都是您的原始/etc/nsswitch.conf设置。)

与 不同/etc/resolv.conf,此文件不会定期写入,因此此绑定挂载不会失效。

神经胶质细胞

如果您不使用 systemd-resolved,glibc 可能还会通过另一种方式忽略您的/etc/resolv.conf设置/etc/nsswitch.conf。这是在 nscd 运行时。glibc 将在/var/run/nscd/socket开始加载 NSS 模块之前尝试访问 nscd。在 NixOS 中,这用于避免需要将 NSS 模块的全局状态配置污染到每个进程的直接运行时环境中;它依赖于 nscd 加载所有 NSS 模块和其他通过 nscd 解析的进程。在某些其他系统中,nscd 可用于提供解析缓存。

有几种解决方法:

  1. 您可以取消共享文件系统命名空间并绑定挂载某些东西,例如/var/empty通过。这将仅对一个进程/var/run/nscd禁用。请注意,这必须与 netns 配置分开完成;它不会仅通过调用来持久化。nscdip netns exec

  2. 你可以使用 firejail利用 seccomp-bpf 的强大功能来禁止访问/var/run/nscd/socket。这可能看起来像这样:

    firejail --noprofile --blacklist=/var/run/nscd/socket --netns=${NAMESPACE} --dns=${NAMESERVER} [command]
    
    
  3. 在许多情况下,您可以全局禁用 nscd,因为它通常不需要。这在 NixOS 上通常不推荐,但在大多数基于 Linux 的操作系统上是合理的。

答案2

就我而言,这是由 NetworkManager 引起的,禁用 nm 的 resolv.conf 处理即可解决该问题。

创建文件 /etc/NetworkManager/conf.d/90-dns-none.conf :

[main]
dns=none

并重新启动 NetworkManager。

相关内容