常规软路由方案拓扑

下图为常规软路由拓扑,网上的旁路由方案基本上都是采用“网关互指”的方式,这种方案看似简单,但因为所有流量都经过旁路由,所以问题很多

  • 性能差

  • 不稳定

  • 精确配置很难

  • 影响智能家居组网

  • BT被出海浪费流量等等

家庭高性能组网方案(装修/家庭网络优化拓扑参考) - 知乎

理想方案🍚

正常流量应直接走主路由,而不经过旁路由,只有特定流量,才走旁路由。

本文的目标是不改变网络结构的前提下,以最小的代价让网络高效透明,对主网络以最小影响。

因为众所周知的原因,本文只讲核心原理,具体操作点到为止。

实现步骤

旁路由

安装基础插件

opkg update
opkg install wget sed coreutils-base64

工具选择

第一步当然是在旁路OpenWrt上安装科学工具,这个在网上有大把的文章,这里面就不展开了,具体是什么样的工具,这个不重要,本方案对此也没有什么要求,总之你喜欢就好,能用就行。

开启功能

  1. 工具支持并开启全局代理,即旁路OpenWrt上的所有流量都走工具过滤分流;(一定得开启全局)

  2. 工具支持并开启域名嗅探;

按上述要求配置并保证在OpenWrt上能正常上外网就行,可以用以下命令在OpenWrt命令行里验证:

curl https://www.外网.com/

有正常内容响应即可

指定DNS服务器

由于目前我们的OpenWrt是通过DHCP客户端的方式上网的,所以上游DNS是通过主路由的DHCP分配的,后面我们会修改主路由的DHCP DNS参数,所以这里我们需要将OpenWrt的上游DNS固定下来,这里面我们将上游DNS改为主路由的地址。

dnsmasq配置

OpenWrt默认安装了dnsmasq,dnsmasq承担了dhcp和dns解析的工具,这里我们需要对dnsmasq配置稍做改动,让其支持额外的配置文件,在命令行中执行以下命令即可:

mkdir /etc/dnsmasq.d
uci set dhcp.@dnsmasq[0].confdir='/etc/dnsmasq.d'
uci commit
service dnsmasq restart

完成上述操作后,dnsmasq则会将/etc/dnsmasq.d/目录下所有文件当作额外配置加载,在这里面我们可以对特定域名指定特定的dns服务器,也可以对特定域名做特定解析,做特定解析可以实现内网域名,或者做dns污染。

比如我们在/etc/dnsmasq.d/新增加域名test.conf,输入以下内容并执行命令重启dnsmasq(service dnsmasq restart),就可以实现将内网域名http://xxx.myhome.com指向OpenWrt软路由了。

address=/.my.com/192.168.200.1

污染dns

到这一步,大佬都知道是啥思路了,这边就不解释了,总结的时候再解释

我这边准备了使用deepseek写的脚本,完成这功能,其中自定义域名数组就是可以自定义的规则,开箱即用

#!/bin/bash

#--------------- 用户配置区 ---------------
DNS_IP="3.3.3.3"                     # 目标解析IP
TARGET_DIR="/etc/dnsmasq.d"          # 配置目录
CONF_FILE="${TARGET_DIR}/dnsmasq_gfw.conf"  # 最终配置文件

# 自定义域名数组 (直接在此处添加)
CUSTOM_DOMAINS=(
    "docker.io"
)
#-----------------------------------------

# 强制root权限
[[ $(id -u) -ne 0 ]] && echo -e "\033[31m错误:必须使用root权限运行!\033[0m" >&2 && exit 1

# 创建临时文件
tmpfile=$(mktemp /tmp/gfwlist.XXXXXX) || exit 1

# 下载生成工具
if ! wget -qO /tmp/gfwlist2dnsmasq.sh \
    https://raw.githubusercontent.com/cokebar/gfwlist2dnsmasq/master/gfwlist2dnsmasq.sh; then
    echo -e "\033[31m错误:脚本下载失败\033[0m" >&2
    rm -f "$tmpfile"
    exit 1
fi
chmod +x /tmp/gfwlist2dnsmasq.sh

# 生成基础规则
if ! /tmp/gfwlist2dnsmasq.sh -l -o "$tmpfile"; then
    echo -e "\033[31m错误:规则生成失败\033[0m" >&2
    rm -f "$tmpfile"
    exit 1
fi

# 格式转换
sed -i 's/^/address=\/./; s/$/\/'"$DNS_IP"'/' "$tmpfile"

# 添加自定义域名
echo -e "\n# 自定义域名规则" >> "$tmpfile"
for domain in "${CUSTOM_DOMAINS[@]}"; do
    # 防御性处理:移除所有逗号和空格
    domain=${domain//[ ,]/}
    # 跳过空项和注释项
    [[ -z "$domain" || "$domain" == "#"* ]] && continue
    echo "address=/.${domain}/$DNS_IP" >> "$tmpfile"
done

# 确保目录存在
mkdir -p "$TARGET_DIR" || {
    echo -e "\033[31m错误:无法创建目录 $TARGET_DIR\033[0m" >&2
    exit 1
}

# 原子化部署
if mv -f "$tmpfile" "$CONF_FILE"; then
    echo -e "\033[32m配置部署成功\033[0m"
else
    echo -e "\033[31m错误:配置文件移动失败\033[0m" >&2
    exit 1
fi

# 重载服务
if service dnsmasq restart; then
    echo -e "服务状态:\033[36m$(service dnsmasq status)\033[0m"
    echo -e "总规则数:\033[33m$(wc -l < "$CONF_FILE")\033[0m"
else
    echo -e "\033[31m错误:dnsmasq重启失败\033[0m" >&2
    exit 1
fi

创建完,赋予权限执行即可

到这里旁路OpenWrt的配置就完成了,上述操作可以制作成脚本定时执行以更新列表。

如果一切顺利,在OpenWrt上ping任何外网域名都会解析成3.3.3.3(可以改为其他任意外网ip),此时可以再次验证下OpenWrt上上网是否正常,如果不正常,则是科学工具不支持或者没有开启域名嗅探:

另外可在局域网任意机器上执行以下命令验证dns配置是否成功

主路由

配置静态路由

核心要将自定义解析出来的IP能过旁路由一遍

DHCP

将DNS设置为旁路由地址,网关依旧为主路由

总结

通过维护一些需要学习的顶级域名,通过脚本自动转换解析为dnsmaq能识别的格式,并且将DNS设置为旁路由,这样的话所有域名都会经过旁路由去解析,如果需要学习的域名呢就会返回3.3.3.3,访问时主路由有这个静态路由就会走旁路由,即可学习,否则其他就正常走主路由出去了,少了一层。

缺点

  • 只能维护域名,IP只能在主路由添加静态路由

踩坑

  • 学习工具一定要全局模式!