安装并配置 TPClash Link to heading

本来是想用 Clash.Meta 作透明代理的,奈何第一步就不知道为啥卡住了:Clash.Meta 运行指定的配置文件之后,无法科学,webui 也无法连接。

后面发现了 tpclash,它可以自动安装 Clash Premium/Meta, 并自动配置基于 Tun 的透明代理。这里为了方便起见,后续操作都是在 root 用户下执行的。

执行 cd && wget https://github.com/mritd/tpclash/releases/download/v0.1.17/tpclash-meta-linux-arm64,然后执行 chmod 755 tpclash-meta-linux-arm64 && mv tpclash-meta-linux-arm64 /usr/local/bin/tpclash

这样就相当于安装了 tpclash,然后执行 tpclash -c /etc/clash.yaml,其中 /etc/clash.yaml 是我根据 release 中的 example.yaml 手搓的,由于使用 Clash.Meta 内核, 配置文件中需要关闭 iptables 配置,如下:

iptables:
  enable: false

要十分注意的是,这种方案使用 N1 作旁路由时,其他被代理的设备,例如手机,笔记本,设置静态 IP 时,DNS 服务器的地址不能设置为 N1 的 IP!原因参见 tpclash README

手搓 clash 配置文件 Link to heading

我们需要用到 mihomo 内核的两大特性:proxy-providerrule-provider

具体使用方法参见 mihomo 的 官方 Wiki

配置文件的具体内容,见 Clash 配置文件

mosdns 的安装与配置 Link to heading

DNS 服务默认使用 UDP 端口 53 来发送查询请求。

我的 mosdns 配置文件整体写的比较简单,只有根据域名列表分流的功能,即可以直连的域名,利用 mosdns 的 froward_cn 中设置的 DNS 进行解析;对其他域名,则将 DNS 请求转发给 tpclash。

对于可以直连的域名,如果不是 cdn 或者 ddns 域名,那么就先查询缓存,如果缓存命中,则直接从缓存中拿到结果,结束查询,否则再转发给 forward_cn 进行查询。

旧方案 Link to heading

该方案下,局域网内所有设备都会科学上网的情况。

采用 docker-compose 部署 mosdns,docker-compose.yml 内容如下:

version: '3'
services:
  mosdns:
    container_name: mosdns
    image: irinesistiana/mosdns:latest
    network_mode: "host"
    volumes:
      - /home/zwyyy/mosdns:/etc/mosdns
    restart: always

由于 docker-compose.yml 是将 /home/zwyyy/mosdns 目录映射到容器的 /etc/mosdns 目录,因此,我们将 mosdns 的配置文件 config.yaml 和域名列表等 txt 文件都存放在 /home/zwyyy/mosdns 目录下,mosdns 的配置文件内容如下:

log:
  level: info

plugins:
  # 缓存
  - tag: "cache"
    type: "cache"
    args:
      size: 10240
      lazy_cache_ttl: 86400

  # 转发给国内 DNS,并发查询
  - tag: "forward_cn"
    type: "forward"
    args:
      concurrent: 3
      upstreams:
        - { tag: alidns, addr: "tls://dns.alidns.com", dial_addr: "223.5.5.5", enable_pipeline: true }
        - { tag: dndpod, addr: "tls://1.12.12.12", enable_pipeline: true }
        - { tag: cfdns, addr: "tls://1.1.1.1", enable_pipeline: true }

  - tag: "forward_fake"
    type: "forward"
    args:
      upstreams:
        - { tag: fakedns, addr: "192.168.6.206:1053" }

 # 可以直连的国内域名列表
  - tag: "direct_domain"
    type: "domain_set"
    args:
      files: ["./apple-cn.txt", "./china-list.txt", "./direct-list.txt", "./tracker-domain.txt", "./direct-domain.txt"]

  - tag: "reject_domain"
    type: "domain_set"
    args:
      files: ["./reject-list.txt"]

  - tag: "cdn-ddns-domain"
    type: "domain_set"
    args:
      files: ["./cdn-ddns.txt"]

  - tag: "cn_seq"
    type: "sequence"
    args:
      - { matches: "!qname $cdn-ddns-domain", exec: $cache } # 如果非 cdn 或者 ddns 域名,则查询缓存
      - { matches: [has_resp], exec: accept } # 查找缓存,如果缓存命中,结束
      - { exec: $forward_cn } # 缓存不命中,通过设置的 dot 查询
      - { exec: query_summary }
      - { exec: accept } # 国内 DNS 查询完成,不再通过 Fake DNS 查询

  - tag: "proxy_seq"
    type: "sequence"
    args:
      - { exec: $forward_fake }
      - { exec: query_summary }

  - tag: "main_seq"
    type: "sequence"
    args:
      - { matches: qname $reject_domain, exec: reject 3 }
      - { matches: qname $direct_domain, exec: goto cn_seq } # 匹配到直连域名,则跳转到 cn_sequence
      - { exec: goto proxy_seq } # 没有匹配到直连域名,跳转 proxy_sequence

  - type: "udp_server"
    args: { entry: main_seq, listen: ":5533" }

  - type: "tcp_server"
    args: { entry: main_seq, listen: ":5533" }

新方案 Link to heading

该方案允许只让指定的设备具有科学上网能力。

采用 docker-compose 部署 mosdns,docker-compose.yml 内容如下:

version: '3'
services:
  mosdns:
    container_name: mosdns
    image: irinesistiana/mosdns:latest
    network_mode: "host"
    volumes:
      - /home/zwyyy/mosdns:/etc/mosdns
    restart: always

由于 docker-compose.yml 是将 /home/zwyyy/mosdns 目录映射到容器的 /etc/mosdns 目录,因此,我们将 mosdns 的配置文件 config.yaml 和域名列表等 txt 文件都存放在 /home/zwyyy/mosdns 目录下,mosdns 的配置文件内容如下:

log:
  level: info

plugins:
  # 缓存
  - tag: "cache"
    type: "cache"
    args:
      size: 10240
      lazy_cache_ttl: 86400

  # 转发给国内 DNS,并发查询
  - tag: "forward_cn"
    type: "forward"
    args:
      concurrent: 3
      upstreams:
        - { tag: alidns, addr: "tls://dns.alidns.com", dial_addr: "223.5.5.5", enable_pipeline: true }
        - { tag: dndpod, addr: "tls://1.12.12.12", enable_pipeline: true }
        - { tag: cfdns, addr: "tls://1.1.1.1", enable_pipeline: true }

  - tag: "forward_fake"
    type: "forward"
    args:
      upstreams:
        - { tag: fakedns, addr: "192.168.6.206:1053" }

 # 可以直连的国内域名列表
  - tag: "direct_domain"
    type: "domain_set"
    args:
      files: ["./apple-cn.txt", "./china-list.txt", "./direct-list.txt", "./tracker-domain.txt", "./direct-domain.txt"]

  - tag: "reject_domain"
    type: "domain_set"
    args:
      files: ["./reject-list.txt"]

  - tag: "cdn-ddns-domain"
    type: "domain_set"
    args:
      files: ["./cdn-ddns.txt"]

  - tag: "cn_seq"
    type: "sequence"
    args:
      - { matches: "!qname $cdn-ddns-domain", exec: $cache } # 如果非 cdn 或者 ddns 域名,则查询缓存
      - { matches: [has_resp], exec: accept } # 查找缓存,如果缓存命中,结束
      - { exec: $forward_cn } # 缓存不命中,通过设置的 dot 查询
      - { exec: query_summary }
      - { exec: accept } # 国内 DNS 查询完成,不再通过 Fake DNS 查询

  - tag: "proxy_seq"
    type: "sequence"
    args:
      - { exec: $forward_fake }
      - { exec: query_summary }

  - tag: "main_seq"
    type: "sequence"
    args:
      - { matches: qname $reject_domain, exec: reject 3 }
      - { matches: qname $direct_domain, exec: goto cn_seq } # 匹配到直连域名,则跳转到 cn_sequence
      - { exec: goto proxy_seq } # 没有匹配到直连域名,跳转 proxy_sequence

  - type: "udp_server"
    args: { entry: main_seq, listen: ":53" }

  - type: "tcp_server"
    args: { entry: main_seq, listen: ":53" }

实际上就是将 Mosdns 的监听端口修改为 DNS 服务默认使用的 53 端口。

配置 mosdns 时踩过的坑 Link to heading

  1. 设置 udp_servertcp_server 时,设置的 ip 和端口不能是 127.0.0.1:5533,尽管官方 wiki 上是这么写的,但是 127.0.0.1 仅能用于本机的程序进行通讯,其他客户端的 DNS 请求转发到 192.168.6.206:5533 时,mosdns 监听的 127.0.0.1:5533 是不会有反应的。

  2. main_seq 中,要跳转到另外一条 sequence 上时,应该使用 exec: goto cn_seq 这样的形式,而不能直接用 exec: $cn_seqexec: $plugin 仅适用于 plugin 为非 sequence 的情况。

主路由 的设置 Link to heading

旧方案 Link to heading

  1. 将所有的 DNS 请求转发给 mosdns:

    • OpenWrt 下,点击 网络 -> DHCP/DNS,在 DNS 转发那一栏添加 192.168.6.206#5533,ip 与端口根据自己的实际情况而定。如下图所示:

    • L18k6ANvWfcmlh3

    • Pandavan 下,点击

  2. 关闭接口 wan 的高级设置中的 自动获取 DNS 服务器选项!

    • OpenWrt 下,点击 网络 -> 接口,点击 WAN 右侧的编辑,在 高级设置 中取消勾选 自动获取 DNS 服务器,如下图所示:

    • eUq436J5p8EhFkf

    • Pandavan 下,点击 外网设置,取消 自动获取 DNS。如下图所示

    • DNS 和 WINS 服务器设置留空

  3. 添加静态路由,如下图所示:

  • awfIcR8PvUMjdzr

WAN 口的 自动获取 DNS 服务器选项如果不关闭,那么会导致域名解析时,DNS 请求没有被转发给 mosdns,而是被路由器从 WAN 口获取的 DNS 服务器解析了,从而客户端没有获取到 FakeIP,而是获取了可能被污染 RealIP。

目前只有 telegram 可能会通过 IP 直接连接,因此静态路由中要添加 telegram 的设置。

新方案 Link to heading

这里只演示 OpenWrt 主路由的设置。

LAN 口中,DHCP 服务器 -> IPv6 设置,取消勾选 本地 IPv6 DNS 服务器,如下图所示:

6DlKHEPmk3tcjIe

添加静态路由的步骤与旧方案相同。

/etc/dnsmasq/conf 中追加如下内容:

## 为指定 IP 段的设备分配 gfw 标签
dhcp-range=set:gfw,192.168.6.152,192.168.6.182,255.255.255.0,24h

## 对具有 gfw 标签的设备,将其 dns 设置为 192.168.6.206
dhcp-option=tag:gfw,option:dns-server,192.168.6.206

## 设置路由器下设备的 dns 为 223.5.5.5,不会覆盖前面的设置
dhcp-option=option:dns-server,223.5.5.5

DHCP/DNS -> 静态地址分配 中,为你需要科学上网的设备分配 192.168.6.152192.168.6.182 之间的 IP,然后执行 service restart dnsmasq 即可。

mosdns 与 tpclash 的配置文件更新流程 Link to heading

通过 crontab 定时执行 /home/zwyyy/mosdns/update.sh 来更新 mosdns 配置文件所需的域名列表 txt 文件。

N1 的 /home/zwyyy/mosdns/update.sh 的文件内容如下:

#!/bin/zsh

# 设置 GitHub 仓库的所有者和仓库名
GITHUB_OWNER="Loyalsoldier"  # 替换为仓库所有者的用户名
GITHUB_REPO="v2ray-rules-dat"    # 替换为仓库名称

# 要下载的文件列表
FILES=("apple-cn.txt" "china-list.txt" "direct-list.txt" "direct-tld-list.txt")

# 构建 API 请求 URL
API_URL="https://api.github.com/repos/$GITHUB_OWNER/$GITHUB_REPO/releases/latest"

# 获取最新 release 的所有资产信息
ASSETS=$(curl -s $API_URL | jq -r '.assets[] | {name, browser_download_url}')

# 下载每个文件
for FILE_NAME in "${FILES[@]}"; do
    DOWNLOAD_URL=$(echo "$ASSETS" | jq -r --arg FILE_NAME "$FILE_NAME" 'select(.name == $FILE_NAME).browser_download_url')

    # 检查下载链接是否为空
    if [ -z "$DOWNLOAD_URL" ]; then
        echo "未找到文件 $FILE_NAME"
        continue
    fi

    # 下载文件
    echo "正在下载 $FILE_NAME..."
    curl -L $DOWNLOAD_URL -o $FILE_NAME
done

curl -L "https://raw.githubusercontent.com/zwyyy456/dotfile/main/myproxy-rule/mosdns/domain-set/proxy-domain.txt" -o proxy-domain.txt
curl -L "https://raw.githubusercontent.com/zwyyy456/dotfile/main/myproxy-rule/mosdns/domain-set/direct-domain.txt" -o direct-domain.txt
curl -L "https://raw.githubusercontent.com/zwyyy456/dotfile/main/myproxy-rule/mosdns/domain-set/cdn-ddns.txt" -o cdn-ddns.txt
curl -L "https://raw.githubusercontent.com/zwyyy456/dotfile/main/myproxy-rule/mosdns/config.yaml" -o config.yaml

echo "所有文件下载完成。"

docker restart mosdns

arm-tao.yaml 本身是通过 gist 来管理的。

而在 arm-tao.yaml 中,rule-provider 的自定义 rule-set 中的源文件是直接存在 github 的公开 repo 中,链接即 repo 中的源文件的直链。

定时更新 tpclash 的配置文件的脚本如下所示:

cd /data/clash
rm arm-tao.yaml
wget "https://gist.githubusercontent.com/zwyyy456/<token>/raw/arm-yuan.yaml" -O myconfig.yaml
systemctl restart tpclash
systemctl status tpclash

解决 google play 可以搜索,但是无法下载的问题 Link to heading

关键在于 services.googleapis.cn 这个网址,被 RULE-SET,direct,DIRECT 匹配到了,因此走了直连。解决方案很简单,在 mproxy.yaml 中追加 - DOMAIN-SUFFIX,services.googleapis.cn,使得该域名走代理,追加后内容如下:

同时 mosdns 所用的 proxy-domain.txt 追加 services.googleapis.cn,防止 services.google.cn 直接被 mosdns 设置的本地 DNS 解析,而不是被 Fake DNS 解析,追加之后内容如下:

bing.com
services.googleapis.cn
google.cn

关于 New Bing Link to heading

很奇怪,尽管已经保证 bing.com 以及它的子域名一定会走代理,但是还是需要登录之后才能使用 New Bing,否则提问时会提示无法连接。此外,建议 Windows 与 Mac 都关闭 edge 的获取定位权限,同时 Microsoft 帐号将位置设置于美国。

题外话 Link to heading

浏览器的缓存会导致通过直链下载配置文件时,尽管 gist 或者 github 的 repo 中已经修改了,但是下载下来的文件还是没有变化。

参考 Link to heading

mosdns wiki