让局域网内所有设备用上Tailscale+MagicDNS: ShellClash+Tailscale+AdGuardHome

前言:最近在闲鱼80收了台JD AX1800 Pro玩,512MB RAM+64G EMMC,刷了QWRT,感觉只跑科学上网有点浪费了,于是整了一个让局域网每台设备都能同时用上Tailscale特别是MagicDNS,在此记录一下流程。

大致流程:用户请求 → iptables重定向(53→5353) → AdGuardHome过滤/分流 → 域名匹配/ts.net/ → Tailscale DNS(100.100.100.100),其他 → Clash DNS(127.0.0.1:1053)

场景需求

在跨境网络环境中实现:

  1. 国内直连/国外代理智能分流(Clash)
  2. Tailscale组网设备的无缝访问
  3. 全网广告过滤(AdGuardHome)
  4. MagicDNS短域名支持

核心组件

组件 监听地址 功能说明
Clash 127.0.0.1:1053 DNS智能分流
Tailscale 100.100.100.100:53 MagicDNS解析
AdGuardHome 0.0.0.0:5353 DNS过滤+请求路由

详细配置步骤

一、Tailscale配置

# 安装Tailscale
opkg install tailscale

# 启动服务并配置路由
tailscale up \
  --advertise-routes=192.168.77.0/24 \ # 换成你的IP
  --accept-dns=true \
  --advertise-exit-node

二、Clash配置

参见:全网最详细的解锁 SSH ShellCrash 搭载 mihomo 内核搭配 AdGuard Home 安装和配置教程 | mihomo 和 sing-box 教程合集

据此配置后,Clash的DNS监听1053端口。

三、AdGuardHome配置

同样参见上面的教程,先配置好AGH。

上游DNS设置:

[/ts.net/]100.100.100.100
127.0.0.1:1053

启动脚本 /root/AdGuardHome/start_agh.sh

#!/bin/sh
sleep 10  # 等待网络初始化

# 启动AdGuardHome
/root/AdGuardHome/AdGuardHome -s start

# IPv4规则
iptables -t nat -A PREROUTING -p tcp -d 100.100.100.100 --dport 53 -j RETURN
iptables -t nat -A PREROUTING -p udp -d 100.100.100.100 --dport 53 -j RETURN
iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 5353
iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5353

# IPv6规则
ip6tables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 5353
ip6tables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5353

把这个启动脚本放在ShellClash的自动任务 / OpenWRT的启动项即可。

四、Tailscale MagicDNS解决方案

按照上述方案配置,客户端可以获得完整的Tailscale域名(xxx.yyy.ts.net)DNS结果,但MagicDNS依然无法使用(xxx)。

接下来我们可以使用如下脚本,通过AGH提供的API添加一些DNS Rewrite规则,将xxx.lan映射到xxx.yyy.ts.net,即可确保在所有客户端上都能与MagicDNS等效了。
通过定时任务维护CNAME记录:

#!/bin/sh

set -euo pipefail

# Configuration
AGH_URL="http://localhost:3000/control"
AGH_USER="<your-agh-username>"
AGH_PASS="<your-agh-password>"
DOMAIN_SUFFIX="<your-tailscale-domain-suffix>.ts.net"

# Check Tailscale availability
if ! tailscale status >/dev/null 2>&1; then
    echo "Error: Tailscale is not running. Exiting."
    exit 1
fi

# Get current Tailscale hosts
hosts=$(tailscale status | awk '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $1, $2}')
if [ -z "$hosts" ]; then
    echo "Error: No Tailscale hosts found. Exiting."
    exit 1
fi

# Get current AdGuard Home rewrite rules
current_rules_json=$(curl -s -u "$AGH_USER:$AGH_PASS" "$AGH_URL/rewrite/list")
if ! echo "$current_rules_json" | jq -e . >/dev/null 2>&1; then
    echo "Error: Failed to fetch valid rewrite rules from AdGuard Home. Exiting."
    exit 1
fi

# Rule processing function
process_rule() {
    local domain="$1"
    local answer="$2"

    local current_entry=$(echo "$current_rules_json" | jq --arg d "$domain" '.[] | select(.domain == $d)')

    if [ -z "$current_entry" ]; then
        echo "Adding rule: $domain → $answer"
        if ! curl --fail -sS -u "$AGH_USER:$AGH_PASS" -X POST \
            -H "Content-Type: application/json" \
            -d "{\"domain\":\"$domain\", \"answer\":\"$answer\"}" \
            "$AGH_URL/rewrite/add"; then
            echo "Error: Failed to add rule $domain"
            exit 1
        fi
    else
        local current_answer=$(echo "$current_entry" | jq -r '.answer')
        if [ "$current_answer" != "$answer" ]; then
            echo "Updating rule: $domain from $current_answer → $answer"
            if ! curl --fail -sS -u "$AGH_USER:$AGH_PASS" -X PUT \
                -H "Content-Type: application/json" \
                -d "{\"target\": {\"domain\": \"$domain\", \"answer\": \"$current_answer\"}, \"update\": {\"domain\": \"$domain\", \"answer\": \"$answer\"}}" \
                "$AGH_URL/rewrite/update"; then
                echo "Error: Failed to update rule $domain"
                exit 1
            fi
        fi
    fi
}

# Process each Tailscale host
echo "$hosts" | while read -r ip hostname; do
    echo "Processing host: $hostname ($ip)"

    # Create FQDN rule
    process_rule "$hostname.lan" "${hostname}.${DOMAIN_SUFFIX}"

done

echo "All rules processed successfully."

到这里就折腾完了,所有设备都可以享受到Tailscale+MagicDNS,也可以自由使用Clash。

8 个赞

感谢分享

感谢大佬教程

正打算在闲置的K2P上试试tailscale,这就有渔了。谢谢哈