问题现象

在我的局域网中跑了一台DebianNAS192.168.0.102以及一台OpenWrt192.168.0.101旁路由,其中NAS网络接口配置如下:

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet static
    address 192.168.0.102/24
    gateway 192.168.0.101
    dns-nameservers 192.168.0.101

可以看到网关和DNS服务器地址均指向192.168.0.101(软路由地址),然而在我尝试Ping Google.com时却出现以下问题:

何为ICMP Redirect

可以从图中清晰看到 Redirect Host(New nexthop: 192.168.0.1) ,ICMP Redirect 可以理解成路由器发给主机的一种“路线纠正通知”。

DebianNAS  ->  OpenWrt  ->  Router 
    <————————————|发现捷径 回报网关IP

我们可以这样理解:手工配置的上级网关在进行下一跳转发时发现了可达的捷径,于是乎通过ICMP协议向请求主机返回这一推荐网关。

普通网络场景下的ICMP Redirect是合理的

ICMP Redirect作为一种路由优化机制,在特定场景下可以削减路由转发次数进而提升网络转发效率。但在本文实践当中极有可能会使NAS中的网络请求绕过旁路由网关,我们本意是想让OpenWrt旁路由代理NAS流量,由于ICMP Redirect的出现使得NAS中的数据报绕过预先设定好的转发路线直接到达最终网关,最终导致Clash代理服务失效。

解决方案(2选1)

代理主机(NAS)侧

cat > /etc/sysctl.d/99-no-icmp-redirect.conf <<'EOF' 
net.ipv4.conf.all.accept_redirects=0 
net.ipv4.conf.default.accept_redirects=0 
net.ipv4.conf.ens18.accept_redirects=0 
net.ipv4.conf.all.secure_redirects=0 
net.ipv4.conf.default.secure_redirects=0 
net.ipv4.conf.ens18.secure_redirects=0 
EOF 
sysctl --system

其中ens18为网卡名称,可以通过ip a进行查看。

旁路由侧(推荐)

cat > /etc/sysctl.d/99-no-send-redirect.conf <<'EOF' 
net.ipv4.conf.all.send_redirects=0 
net.ipv4.conf.default.send_redirects=0 
net.ipv4.conf.br-lan.send_redirects=0 
EOF 
sysctl --system

其中br-lan为网卡名称,可以通过ip a进行查看。

最终效果

fake-ip 模式下,域名会被解析到一个虚拟 IP,Clash 主要接管 TCP/UDP 连接;而 ping 使用 ICMP,所以 ping google.com 超时不能说明 HTTPS 不通。

这不能直接证明代理已经完全生效,但可以说明 NAS 的 DNS 解析已经进入了旁路由Clash 的 fake-ip 处理链路。

接下来需要更加严谨的测试:

curl https://www.google.com

响应如下:

<!doctype html>
<html itemscope="" itemtype="http://schema.org/WebPage" lang="ko">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<title>Google</title>