【问题记录】ddns-go与IPv6网络配置

在完成 Rustdesk 自建服务器 的搭建后,我又想到:由于实验室服务器的公网 IPv6 地址 并非永久不变,直接使用 IP 进行远程连接(如 SSH 或 Rustdesk)并不现实,如何确保远程访问的稳定性和便利性呢。为了解决这一痛点,我决定利用 动态域名解析(DDNS) 技术,配合 ddns-go阿里云 DNS 服务,将服务器的动态 IP 地址实时绑定到一个易于记忆的域名上。

本文将记录我在配置过程中遇到的四个主要问题及其解决方案。


问题 1:IPv6 临时地址导致域名解析不稳定

在启用 ddns-go 服务后,我发现尽管程序运行正常,但我的域名解析记录却频繁失效。经过排查,我意识到罪魁祸首是 IPv6 临时地址(Temporary Address)。这是一种为了增强用户隐私而设计的特性,系统会定期生成新的、临时的 IPv6 地址用于出站连接。当服务器的地址发生变化时,DDNS 服务来不及同步更新,就会导致域名无法解析到正确的 IP 地址。

解决方案:禁用 IPv6 临时地址

要解决这个问题,最直接的方法就是从系统层面禁用 IPv6 临时地址功能,强制使用稳定的、非临时的地址。

  1. 编辑 sysctl 配置文件: 使用 vim 或其他编辑器打开 sysctl.conf 文件,该文件用于在系统启动时配置内核参数。
1
sudo vim /etc/sysctl.conf
  1. 添加配置项: 在文件末尾添加以下两行,分别用于全局禁用默认禁用所有网络接口的 IPv6 临时地址功能。
1
2
3
# 禁用 IPv6 临时地址
net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.enp4s0.use_tempaddr = 0

注意:如果只想针对特定网卡(例如 enp4s0)进行配置,可以添加 net.ipv6.conf.enp4s0.use_tempaddr = 0。你可以通过 ip a 命令查看你机器的网卡名称。

  1. 应用配置: 执行以下命令,使新配置即时生效。
1
sudo sysctl -p
  1. 验证配置是否生效: 最后,可以通过查看特定参数的值来验证修改是否成功。如果返回 0,则表示临时地址已成功禁用。
1
2
cat /proc/sys/net/ipv6/conf/enp4s0/use_tempaddr
# 预期输出: 0

问题 2:ddns-go 无法通过 systemd 启动

利用 systemctl status ddns-go 查看 ddns-go 运行状态时,看到:

1
2
Unable to locate executable '/usr/local/bin/ddns-go': Permission denied
Failed at step EXEC spawning /usr/local/bin/ddns-go: Permission denied

但是对应的文件的权限我都给了,问了问 AI 后说可能造成的原因之一为SELinux 阻止执行(在 Fedora 上默认开启)。输入:

1
sudo ausearch -m avc -ts recent | grep ddns-go

看到有拒绝记录,说明是 SELinux 问题。

临时解决方案

1
sudo setenforce 0

永久解决方案

为该二进制打上正确的 SELinux 标签

1
sudo restorecon -v /usr/local/bin/ddns-go

之后再重启 ddns-go 服务,就 OK 了。

📝 为什么会有 SELinux 相关问题?

Linux 传统权限模型(用户/组/other + rwx)是 自主访问控制(DAC):用户对自己文件有完全控制权;程序继承用户权限 → 一旦用户被攻破,攻击者可为所欲为

SELinux 的目标是:即使程序或用户被攻破,也要限制它能做的事

我是把 ddns-go 的可执行文件放在/usr/local/bin/下(复制过去的)

而 SELinux 有预定义的“文件上下文”:

  • /usr/bin/*bin_t(可执行程序)
  • /usr/local/bin/* → 默认可能不是 bin_t,尤其是手动复制进去的文件

所以即使文件有 chmod +x,SELinux 仍可能阻止执行

问题 3:ddns-go 无法正确更新 IPv6 地址记录

解决了 IPv6 地址变化的问题后,我发现 ddns-go 服务依然无法正常工作,并抛出大量 DNS 相关的超时错误,例如:

1
2
3
2025/08/29 10:01:37 查询域名信息发生异常! 
Get "[https://alidns.aliyuncs.com/?AccessKeyId=xxxxxx](https://alidns.aliyuncs.com/?AccessKeyId=xxxxxx)": 
dial tcp: lookup alidns.aliyuncs.com on x.x.x.x:53: read udp x.x.x.x:59439->x.x.x.x:53: i/o timeout

通过分析日志,我发现服务在尝试向外部 DNS 服务器(如 8.8.8.8114.114.114.114)发起 DNS 请求时失败了。这通常是由于校园网或实验室网络的防火墙策略,限制了对外部公共 DNS 服务器的访问,强制所有 DNS 请求都通过内部服务器。

解决方案:指定 ddns-go 使用可访问的 DNS 服务器

由于 ddns-go 默认使用系统 DNS,而系统 DNS 可能被强制转发到内部服务器,因此我们需要在启动命令中显式指定可访问的公共 DNS 服务器。

  1. 编辑 ddns-go 服务文件:

    打开 /etc/systemd/system/ddns-go.service 文件。

1
sudo vim /etc/systemd/system/ddns-go.service
  1. 修改 ExecStart 参数:

    在 ExecStart 行的末尾,添加 -dns 参数,指定一个或多个在国内访问稳定的公共 DNS,如阿里云的 223.5.5.5 和腾讯云的 119.29.29.29。

1
2
3
4
5
6
7
[Service]
StartLimitInterval=5
StartLimitBurst=10
ExecStart=/usr/local/bin/ddns-go "-l" ":9876" "-f" "300" "-cacheTimes" "5" "-c" "/root/.ddns_go_config.yaml" "-dns" "223.5.5.5" "-dns" "119.29.29.29"

[Install]
...
  1. 重新加载并重启服务:

    保存文件后,重新加载 systemd 配置并重启 ddns-go 服务,使新参数生效。

1
2
sudo systemctl daemon-reload
sudo systemctl restart ddns-go

问题 4:电脑睡眠后网络中断,无法远程连接

解决了域名解析问题后,我又发现一个新情况:如果服务器闲置一段时间,SSH 连接就会断开。当物理唤醒电脑后,网络连接需要一段时间才能恢复。这是因为 系统默认的电源管理策略 会在电脑进入睡眠状态后,挂起或断开部分硬件(如网卡)以节省电量。

解决方案:禁用系统休眠与闲置操作

1
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

为了确保服务器 24/7 在线,我们需要修改电源管理配置,禁用自动休眠。

  1. 编辑 systemd-logind 配置文件:

    打开 /etc/systemd/logind.conf 文件,该文件用于配置用户登录和电源管理行为。

1
sudo vim /etc/systemd/logind.conf
  1. 修改配置参数:

    取消以下几行的注释(如果被注释),并将它们的值修改为 ignore 或 never。

1
2
3
4
5
6
[Login]
# 禁用闲置自动操作
IdleAction=ignore
IdleActionSec=never
# 禁用合盖自动操作
HandleLidSwitch=ignore
  1. 重启服务:

    修改完成后,重启 systemd-logind 服务使配置生效。

1
sudo systemctl restart systemd-logind

解决完上述问题后,无论是在校内还是校外,我都可以通过一个固定的域名来使用服务器了。

使用 Hugo 构建
主题 StackJimmy 设计