在无桌面 Archlinux 上配置 hclient-cli TUN 网卡和 IPv6 DNS 解析

ety001

发布于159天前
远程工作,Steem开发者,Steem见证人
## 背景

`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
ety001133天前

再补充一个方案,更加优雅。 创建 `/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 ```

我是小E154天前

向大神膜拜

说点什么呢~
收藏
1
2
0