-
Notifications
You must be signed in to change notification settings - Fork 435
DNS方案
zfl9 edited this page Sep 11, 2024
·
21 revisions
分享一些 DNS 玩法,比如给内置 DNS 方案套上 DoH/DoT,以及自定义 DNS 方案的例子。
欢迎大家在 Discussions 页面分享自己的 DNS 方案,我会不定时的将它们整理到 wiki 页面。
更新:
ss-tproxy v4.8+
+chinadns-ng 2024.04.27+
已支持 DoT。
以 https://github.com/AdguardTeam/dnsproxy 为例,给 direct 和 remote DNS 套上 DoH:
dns_direct='127.0.0.1#65001' # 指向 dnsproxy
dns_direct_white='223.5.5.5 223.6.6.6' # 加入白名单
dns_remote='127.0.0.1#65002' # 指向 dnsproxy
dns_remote_black='8.8.8.8 8.8.4.4' # 加入黑名单
# 如果给 remote DNS 套了 DoH/DoT,则不必启用 dns2tcp
dns2tcp_enable='false'
pre_start() {
# 设置所属 group、setgid 权限位 (只需执行一次)
set_dns_group dnsproxy
# 启动 dnsproxy 进程,用于 direct DNS
(dnsproxy -l 127.0.0.1 -p 65001 \
-b 223.5.5.5:53 \
-u https://dns.alidns.com/dns-query \
</dev/null &>>/var/log/dnsproxy.log &)
# 启动 dnsproxy 进程,用于 remote DNS
(dnsproxy -l 127.0.0.1 -p 65002 \
-b 223.5.5.5:53 \
-u https://dns.google/dns-query \
</dev/null &>>/var/log/dnsproxy.log &)
}
post_stop() {
# 关闭 dnsproxy
kill_by_name dnsproxy
}
extra_status() {
_status "doh/direct" udp_port_is_exists 65001
_status "doh/remote" udp_port_is_exists 65002
}
来自:https://github.com/zfl9/ss-tproxy/discussions/218
使用 AdGuardHome 可以方便的查看 dns 日志、block 不想要的域名、以及广告过滤。
AdGuardHome 的配置和用法就不介绍了,这里只说下如何接入 ss-tproxy,挂到 chinadns-ng 前面:
# 让 AdGuardHome 监听 53 端口
dns_mainport='53'
# chinadns 作为 AdGuardHome 的上游,监听非 53 端口
chinadns_bind_port='54'
pre_start() {
# 设置所属 group、setgid 权限位 (只需执行一次)
set_dns_group /path/to/AdGuardHome
# 启动 AdGuardHome,以 systemd 为例
systemctl start AdGuardHome
}
post_stop() {
# 停止 AdGuardHome,以 systemd 为例
systemctl stop AdGuardHome
}
chinadns-ng 2024.04.27+ 已支持 缓存、hosts、DoT 等功能,不再需要 coredns。
如果你想实现自己的 DNS 方案,可以参考这里的配置,因为核心思路还是一样的。
来自:https://github.com/zfl9/ss-tproxy/discussions/218#discussioncomment-5977470
- coredns 监听 53,接收所有 DNS 请求,转发给 chinadns-ng
- chinadns-ng 实现 global/gfwlist/chnroute 域名分流,与 ipset 联动
- coredns 监听 127.0.0.1#65001,作为 chinadns-ng 的国内上游,配置 DoT
- coredns 监听 127.0.0.1#65002,作为 chinadns-ng 的可信上游,配置 DoT
coredns 配置文件 /etc/ss-tproxy/Corefile:
# 有效时间单位: "ns", "us" (or "µs"), "ms", "s", "m", "h"
# (xyz) { ... } 是定义一个配置片段, 通过 import xyz 来引用
# import 也可以导入外部配置文件,具体见 import 插件的 README
# DNS 缓存相关
(enable_cache) {
# 缓存在到达数量上限之后,才会被随机删除。
# 默认缓存数量 256 * 39 = 9984
cache {
# 30 分钟之内查询过2次,当 ttl 剩余 10% 就会自动预查询
prefetch 2 30m 10%
# 立刻发送过期缓存, 同时后台刷新缓存, 提高效率
serve_stale 24h immediate
# 不要缓存 SERVFAIL
servfail 0
# 不要缓存 NXDOMAIN
disable denial
# 不要缓存这些域名 比如你的 ddns 域名
# disable success ddns.example.com
}
}
# /etc/hosts 相关
(enable_hosts) {
hosts {
# 默认会加载 /etc/hosts 以及下面自定义的 hosts
#
# 自定义 hosts 格式为
# ip 域名 别名 别名 别名 ....
# 1.2.3.4 example.com us1
#
# 如果 hosts 没有匹配, 就继续查询
fallthrough
}
}
(server_common) {
# EDNS0 请求的缓冲区大小
bufsize 1232
# 记录错误日志 (stdout)
errors
}
(forward_common) {
# 禁用健康检查
max_fails 0
}
# 监听 53,接收所有 DNS 请求
.:53 {
import server_common
import enable_cache
import enable_hosts
# 转发给 chinadns-ng,进行分流
forward . 127.0.0.1:65353 {
import forward_common
# 因为 chinadns-ng 目前只支持 UDP (新版本已支持 UDP/TCP)
prefer_udp
}
}
# 作为 chinadns-ng 的国内上游
.:65001 {
import server_common
bind 127.0.0.1
# 转发给 223.5.5.5 (DoT)
forward . tls://223.5.5.5 {
import forward_common
tls_servername dns.alidns.com
}
}
# 作为 chinadns-ng 的可信上游
.:65002 {
import server_common
bind 127.0.0.1
# 转发给 8.8.8.8 (DoT)
forward . tls://8.8.8.8 {
import forward_common
tls_servername dns.google
}
}
配置 /etc/ss-tproxy/ss-tproxy.conf:
dns_custom='true'
# 初始化,脚本加载时调用
custom_dns_init() {
set_dns_group coredns
set_dns_group chinadns-ng
}
# 要加入白名单的ip,启动dns之前调用
custom_dns_whiteip() {
# 格式同 ignlist.ext,一行一个
echo "-223.5.5.5"
}
# 要加入黑名单的ip,启动dns之前调用
custom_dns_blackip() {
# 格式同 gfwlist.ext,一行一个
echo "-8.8.8.8"
}
# 启动dns进程,请务必以dns_procgroup身份运行
custom_dns_start() {
pid_coredns=$(coredns </dev/null &>/var/log/coredns.log & echo $!)
# 请使用最新版 chinadns-ng (version >= 2023.06.01)
local chinadns_arg="-c 127.0.0.1#65001 -t 127.0.0.1#65002"
if is_global_mode; then # 白名单 (ignlist)
pid_chinadns=$(
trap "" CHLD # 避免僵尸进程
chinadns-ng $chinadns_arg \
-m <(list_ext_domain ignlist.ext) \
-d gfw \
-a sstp_white,sstp_white6 \
</dev/null &>/var/log/chinadns.log &
echo $!
)
elif is_gfwlist_mode; then # 黑名单 (gfwlist)
pid_chinadns=$(
trap "" CHLD # 避免僵尸进程
chinadns-ng $chinadns_arg \
-g gfwlist.txt,<(list_ext_domain gfwlist.ext) \
-d chn \
-A sstp_black,sstp_black6 \
</dev/null &>/var/log/chinadns.log &
echo $!
)
elif is_chnroute_mode; then # 白名单 (ignlist,chnlist,chnroute) + 黑名单 (gfwlist)
pid_chinadns=$(
trap "" CHLD # 避免僵尸进程
chinadns-ng $chinadns_arg \
-m chnlist.txt,<(list_ext_domain ignlist.ext) \
-g gfwlist.txt,<(list_ext_domain gfwlist.ext) \
-a sstp_white,sstp_white6 \
-A sstp_black,sstp_black6 \
-4 sstp_white -6 sstp_white6 \
</dev/null &>/var/log/chinadns.log &
echo $!
)
fi
}
# 关闭dns进程,stop时调用
custom_dns_stop() {
kill_by_pid $pid_coredns
kill_by_pid $pid_chinadns
}
# 打印运行状态,status时调用
custom_dns_status() {
_status "coredns" process_is_running $pid_coredns
_status "chinadns" process_is_running $pid_chinadns
}
# 清空dns缓存,flush-dnscache时调用
custom_dns_flush() {
! ss_tproxy_is_started && return
# 重启 coredns 进程
kill_by_pid $pid_coredns
pid_coredns=$(coredns </dev/null &>/var/log/coredns.log & echo $!)
# 更新 pid 文件
save_pidfile
}
# 此函数在start的最后一步执行,获取运行时状态,同extra_pid
custom_dns_pid() {
# 格式同shell变量赋值,注意变量命名,防止冲突/覆盖
# pid文件是一个shell脚本,下次执行时会source加载它
echo "pid_coredns=$pid_coredns"
echo "pid_chinadns=$pid_chinadns"
}