
ety001
## 背景
`hclient-cli` 是[懒猫微服的命令行工具](https://gitee.com/lazycatcloud/hclient-cli),如果使用的是 tun 模式启动,启动后会创建 TUN 网卡(如 `heiyu-0`)并拦截 IPv6 流量。在 Archlinux 系统上,如果使用 `systemd-networkd` 和 `systemd-resolved` 作为网络管理方案,需要正确配置 DNS 解析,确保 `*.heiyu.space` 等域名能够正确解析到 `fc03:1136:3800::/40` 网段的 IPv6 地址。
## 问题现象
配置完成后,可能出现以下问题:
1. **DNS 解析失败**
```bash
$ ping ecat.heiyu.space
ping: ecat.heiyu.space: No address associated with hostname
```
2. **路由表已配置但 DNS 未生效**
- TUN 网卡 `heiyu-0` 已创建并配置了 IPv6 地址
- 路由表显示 `fc03:1136:3800::/40` 网段已路由到 `heiyu-0`
- 但 DNS 查询仍然失败
## 问题诊断
### 1. 检查 TUN 网卡状态
```bash
# 查看 TUN 网卡
ip link show heiyu-0
ip addr show heiyu-0
# 查看 IPv6 路由表
ip -6 route show
```
正常情况下应该看到:
- TUN 网卡已创建并处于 UP 状态
- 配置了 `fc03:1136:3800::/40` 网段的 IPv6 地址
- 路由表中存在 `fc03:1136:3800::/40 dev heiyu-0` 路由
```bash
[root@worker ~]# ip link show heiyu-0
3: heiyu-0: mtu 1380 qdisc fq_codel state UNKNOWN mode DEFAULT group default qlen 500
link/none
[root@worker ~]# ip addr show heiyu-0
3: heiyu-0: mtu 1380 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet6 fc03:1136:388a:793f:59ea:b249:4347:0/40 scope global
valid_lft forever preferred_lft forever
inet6 fe80::6ea2:e5e1:fbf4:6064/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
[root@worker ~]# ip -6 route show
2001:4860:4860::8888 dev heiyu-0 metric 1024 pref medium
fc03:1136:3800::/40 dev heiyu-0 proto kernel metric 256 pref medium
fda2:972e:ea1d::/64 dev ens18 proto ra metric 1024 pref medium
unreachable fda2:972e:ea1d:4::/62 dev lo proto dhcp metric 1024 pref medium
fda2:972e:ea1d::/48 nhid 2082517828 via fe80::8cb:c6ff:fe00:736b dev ens18 proto ra metric 1024 expires 1666sec pref medium
fe80::/64 dev ens18 proto kernel metric 256 pref medium
fe80::/64 dev heiyu-0 proto kernel metric 256 pref medium
```
### 2. 检查 DNS 配置
```bash
# 查看 systemd-resolved 状态
systemd-resolve --status
# 或使用新命令
resolvectl status
```
执行结果如下:
```bash
[root@worker ~]# resolvectl status
Global
Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 8.8.8.8
DNS Servers: 8.8.8.8 114.114.114.114 223.5.5.5 fc03:1136:3800::1
Fallback DNS Servers: 9.9.9.9#dns.quad9.net 2620:fe::9#dns.quad9.net 1.1.1.1#cloudflare-dns.com
2606:4700:4700::1111#cloudflare-dns.com 8.8.8.8#dns.google 2001:4860:4860::8888#dns.google
Link 2 (ens18)
Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 114.114.114.114
DNS Servers: 114.114.114.114 fda2:972e:ea1d::1
Default Route: yes
Link 3 (heiyu-0)
Current Scopes: none
Protocols: -DefaultRoute +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
Default Route: no
Link 4 (docker0)
Current Scopes: none
Protocols: -DefaultRoute +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
Default Route: no
```
问题可能在于:
- `heiyu-0` 网卡的 DNS 服务器未配置
- `heiyu-0` 网卡未设置为默认路由
- DNS 域名搜索列表未配置
### 3. 检查路由可达性
```bash
# 测试 DNS 服务器地址的路由
[root@worker ~]# ip -6 route get fc03:1136:3800::1
fc03:1136:3800::1 from :: dev heiyu-0 proto kernel src fc03:1136:388a:793f:59ea:b249:4347:0 metric 256 pref medium
```
应该显示路由通过 `heiyu-0` 网卡。
## 解决方案
### 步骤 1:配置 systemd-resolved
使用 `resolvectl` 命令为 TUN 网卡配置 DNS:
```bash
# 配置 DNS 服务器
resolvectl dns heiyu-0 fc03:1136:3800::1
# 配置域名搜索列表(注意修改为自己的域名)
resolvectl domain heiyu-0 ecat.heiyu.space
# 启用默认路由(重要!)
resolvectl default-route heiyu-0 yes
```
**注意**:`default-route` 选项非常重要,它确保 DNS 查询会优先使用该网卡上的 DNS 服务器。
### 步骤 2:验证配置
```bash
# 查看配置是否生效
resolvectl status heiyu-0
```
应该看到类似输出:
```
Link 3 (heiyu-0)
Current Scopes: DNS
Protocols: +DefaultRoute +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
DNS Servers: fc03:1136:3800::1
DNS Domain: ecat.heiyu.space
Default Route: yes
```
### 步骤 3:测试 DNS 解析
```bash
# 使用 dog 或 dig 测试 DNS 解析
[root@worker ~]# dog AAAA ecat.heiyu.space
AAAA ecat.heiyu.space. 59s fc03:1136:3803:dc8d:781c:9f1f:854a:0
# 或使用 ping 测试
[root@worker ~]# ping ecat.heiyu.space
PING ecat.heiyu.space (fc03:1136:3803:dc8d:781c:9f1f:854a:0) 56 data bytes
64 bytes from fc03:1136:3803:dc8d:781c:9f1f:854a:0: icmp_seq=1 ttl=64 time=44.1 ms
64 bytes from fc03:1136:3803:dc8d:781c:9f1f:854a:0: icmp_seq=2 ttl=64 time=44.7 ms
```
如果配置正确,应该能够解析到 `fc03:1136:3803:dc8d:781c:9f1f:854a:0` 这样的 IPv6 地址。
## 持久化配置
上述 `resolvectl` 命令是临时性的,系统重启后会丢失。为了持久化配置,需要在 systemd service 文件中添加配置命令。由于我是自己写的 `hclient-cli` 的启动文件,因此我需要在 `hclient-cli` 启动后,执行上面的命令。
### 修改 hclient-cli.service
编辑 `/etc/systemd/system/hclient-cli.service`:
```ini
[Unit]
Description=LazyCat Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/hclient-cli -tun -api-addr 127.0.0.1:7777
# 在 TUN 网卡创建后配置 DNS
ExecStartPost=/usr/bin/sleep 2
ExecStartPost=/usr/bin/resolvectl dns heiyu-0 fc03:1136:3800::1
# 注意这里改为自己的域名
ExecStartPost=/usr/bin/resolvectl domain heiyu-0 ecat.heiyu.space
ExecStartPost=/usr/bin/resolvectl default-route heiyu-0 yes
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
### 更可靠的等待方式(可选)
如果 `sleep 2` 不够稳定,可以使用更可靠的方式等待接口就绪:
```ini
ExecStartPost=/bin/sh -c 'for i in 1 2 3 4 5; do ip link show heiyu-0 >/dev/null 2>&1 && break || sleep 1; done'
ExecStartPost=/usr/bin/resolvectl dns heiyu-0 fc03:1136:3800::1
ExecStartPost=/usr/bin/resolvectl domain heiyu-0 ecat.heiyu.space
ExecStartPost=/usr/bin/resolvectl default-route heiyu-0 yes
```
### 应用配置
```bash
# 重新加载 systemd 配置
systemctl daemon-reload
# 重启服务
systemctl restart hclient-cli
# 检查服务状态
systemctl status hclient-cli
# 验证 DNS 配置
resolvectl status heiyu-0
```
## 关键配置点总结
1. **DNS 服务器配置**:必须将 `fc03:1136:3800::1` 配置为 `heiyu-0` 网卡的 DNS 服务器
2. **域名搜索列表**:配置 `ecat.heiyu.space` 域名,确保相关域名能够正确解析
3. **默认路由**:**最关键**,必须设置 `default-route yes`,否则 systemd-resolved 不会优先使用该网卡的 DNS 服务器
4. **持久化**:在 systemd service 中使用 `ExecStartPost` 确保配置在每次服务启动时自动应用
## 参考命令速查
```bash
# 查看 TUN 网卡状态
ip link show heiyu-0
ip addr show heiyu-0
# 查看 IPv6 路由
ip -6 route show
# 查看 DNS 配置
resolvectl status heiyu-0
# 手动配置 DNS(临时)
resolvectl dns heiyu-0 fc03:1136:3800::1
resolvectl domain heiyu-0 ecat.heiyu.space
resolvectl default-route heiyu-0 yes
# 测试 DNS 解析
dog AAAA ecat.heiyu.space
ping6 ecat.heiyu.space
```
## 总结
在 Archlinux 上配置 hclient 的 TUN 网卡和 DNS 解析,关键在于正确配置 `systemd-resolved`。通过 `resolvectl` 命令设置 DNS 服务器、域名搜索列表和默认路由,并在 systemd service 中持久化这些配置,可以确保系统重启后 DNS 解析仍然正常工作。
评论
2再补充一个方案,更加优雅。 创建 `/etc/systemd/system/heiyu-dns-setup.service`,内容如下: ``` [Unit] Description=Configure DNS for heiyu-0 TUN device After=network-online.target # 需要前置服务启动 Requires=hclient-cli.service [Service] Type=oneshot ExecStart=/usr/bin/resolvectl dns heiyu-0 fc03:1136:3800::1 ExecStart=/usr/bin/resolvectl domain heiyu-0 "~heiyu.space" RemainAfterExit=yes [Install] WantedBy=multi-user.target ``` 创建 `DNS` 设置的服务,这样就可以不用在 `/etc/systemd/system/hclient-cli.service` 文件中设置 DNS 相关信息了。 创建完上面的文件后,执行下面的命令生效 ``` systemctl daemon-relaod && systemctl enable --now heiyu-dns-setup.service ```
向大神膜拜