Aug 29

ECS (edns-client-subnet)的支持上,国内 DNS派,国外 Google 支持最好,而 Overture 支持上发 EDNS 信息,基于这几个特点,可以在 VPS (无论在国内还是国外)建立一个 CDN 友好的 DNS 服务器。

国外 VPS 配置范例:

{
"BindAddress": ":5353",
"DebugHTTPAddress": "127.0.0.1:5555",
"PrimaryDNS": [
{
"Name": "DNSPaiS",
"Address": "218.30.118.6:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 6,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
},
{
"Name": "DNSPaiM",
"Address": "101.226.4.6:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 6,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
}
],
"AlternativeDNS": [
{
"Name": "GoogleM",
"Address": "8.8.8.8:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 3,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
},
{
"Name": "GoogleS",
"Address": "8.8.4.4:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 3,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
}
],
"OnlyPrimaryDNS": false,
"IPv6UseAlternativeDNS": false,
"WhenPrimaryDNSAnswerNoneUse": "PrimaryDNS",
"IPNetworkFile": {
"Primary": "./cn.zone",
"Alternative": "./ip_network_alternative_sample"
},
"DomainFile": {
"Primary": "./domain_primary_sample",
"Alternative": "./domain_alternative_sample",
"Matcher": "regex-list"
},
"HostsFile": "./hosts_sample",
"MinimumTTL": 0,
"DomainTTLFile" : "./domain_ttl_sample",
"CacheSize" : 10000,
"RejectQType": [255]
}

国内/路由器等配置范例:(注意与国外的主要差别,使用了 Google 的 DNS-Over-TLS,否则会被污染)

{
"BindAddress": "0.0.0.0:5554",
"DebugHTTPAddress": "0.0.0.0:8081",
"PrimaryDNS": [
{
"Name": "DNSPaiS",
"Address": "123.125.81.6:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 3,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
},
{
"Name": "DNSPaiM",
"Address": "101.226.4.6:53",
"Protocol": "udp",
"SOCKS5Address": "",
"Timeout": 3,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
}
],
"AlternativeDNS": [
{
"Name": "GoogleM",
"Address": "dns.google:853@8.8.8.8",
"Protocol": "tcp-tls",
"SOCKS5Address": "",
"Timeout": 6,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
},
{
"Name": "GoogleS",
"Address": "dns.google:853@8.8.4.4",
"Protocol": "tcp-tls",
"SOCKS5Address": "",
"Timeout": 6,
"EDNSClientSubnet": {
"Policy": "auto",
"ExternalIP": "223.73.56.110",
"NoCookie": true
}
}
],
"OnlyPrimaryDNS": false,
"IPv6UseAlternativeDNS": false,
"WhenPrimaryDNSAnswerNoneUse": "AlternativeDNS",
"IPNetworkFile": {
"Primary": "/opt/etc/cn.zone",
"Alternative": "/opt/etc/empty"
},
"DomainFile": {
"Primary": "/opt/etc/empty",
"Alternative": "/opt/etc/empty"
},
"HostsFile": "",
"MinimumTTL": 300,
"DomainTTLFile" : "/opt/etc/domain_ttl.txt",
"CacheSize" : 8192,
"RejectQtype": [255]
}

:cool: :cool: :cool:


Dec 03

项目地址:
https://github.com/aarond10/https_dns_proxy

特色功能:
自从 Google 发布 DNS-Over-HTTPS 服务以来,其实有很多基于此服务写的程序,但是目前看起来这个项目实现的比较好:
C++ 实现,执行文件很小 (30kiB,静态编译的版本约为 900k),比大多数用 Go 写的小得多
基于 Curl HTTP/2 API , 解析延迟极小
单线程无阻塞式查询,适用于嵌入式系统如路由器等
最好作为 DNSMASQ 这样带缓存的 DNS 服务器上游.
由于 Google 这个服务支持 EDNS SUBNET 的查询,所以理论上通过这个服务器查询的结果不会有 CDN 的问题,当然实际还需时间来证明。

Usage: https_dns_proxy [-a ] [-p ]
[-e ] [-d] [-u ] [-g ] [-b ]
[-l ]
-a listen_addr 监听地址. (127.0.0.1)
-p listen_port 监听端口. (5053)
-e subnet_addr edns-client-subnet edns 子网 “203.31.0.0/16”. 建议通过路由器外网地址来计算()
-d 后台运行.
-u user 用户名. (nobody)
-g group 用户组. (nobody)
-b dns_servers 用来解析 dns.google.com 的域名服务器. (8.8.8.8,8.8.4.4)
-t proxy_server 代理服务器,例如: socks5://127.0.0.1:1080,http://127.0.0.1:8080 (注意上面 dns.google.com 的解析不通过此代理!)
-l logfile 日志文件. (-)
-v 开启调试信息. (INFO)

上面的 subnet_addr 可以通过一些命令行获取,例如:

$(nvram get wan_ipaddr | cut -d "." -f 1-2).0.0/16

如果是内网,则应该用:

curl -sS ifconfig.co | cut -d "." -f 1-2
或者
wget http://ipecho.net/plain -O - -q | cut -d "." -f 1-2

这个在 Tomatoware 上静态编译稍微有点麻烦:

1. 首先要编译 curl (及其库)支持 http2,这样用到 nghttp2:

git clone https://github.com/tatsuhiro-t/nghttp2.git
cd nghttp2
autoreconf -i
automake
autoconf
./configure --prefix=/mmc
make
make install

2. 编译 curl :

#!/bin/sh

[ ! -e ./curl.pem ] && wget -qO curl.pem https://curl.haxx.se/ca/cacert.pem

[ -n "$1" ] && ssVersion=$1 || ssVersion="git"

mkdir -p done/${ssVersion}/OpenSSL-opt

echo "Compiling OpenSSL Version..."
make clean
[ ! -e  /opt/sbin/curl.pem ] && cp ./curl.pem /opt/sbin/
./configure --prefix=/mmc --with-ca-bundle=/opt/sbin/curl.pem --with-nghttp2 
--disable-ldap
make -j2 LDFLAGS="-all-static -s" LIBS="-ldl"
[ $? -eq 0 ] || { echo "Compiling OpenSSL failed."; exit 1; }
make install
mv -f src/curl done/${ssVersion}/OpenSSL-opt/

echo -e "Compile Result:n"

file done/${ssVersion}/OpenSSL-opt/curl

echo ""

done/${ssVersion}/OpenSSL-opt/curl -V

3. 静态编译 https_dns_proxy,修改过的 CMakeList.txt:

project(HttpsDnsProxy)
cmake_minimum_required(VERSION 2.8)

#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_BUILD_TYPE "Release")

# set(CMAKE_C_FLAGS "-Wall --pedantic -Wno-strict-aliasing")

set(NXJSON_DIR lib/nxjson/)
set(NXJSON_SRC ${NXJSON_DIR}/nxjson.c)

find_path(LIBCARES_INCLUDE_DIR ares.h)
find_path(LIBCURL_INCLUDE_DIR curl/curl.h)
find_path(LIBEV_INCLUDE_DIR ev.h)
include_directories(
${LIBCARES_INCLUDE_DIR} ${LIBCURL_INCLUDE_DIR}
${LIBEV_INCLUDE_DIR} ${NXJSON_DIR} src)

# The main binary
set(TARGET_NAME "https_dns_proxy")
aux_source_directory(src SRC_LIST)
set(SRC_LIST ${SRC_LIST} ${NXJSON_SRC})
add_executable(${TARGET_NAME} ${SRC_LIST})
#set(LIBS ${LIBS} cares curl ev resolv ssl crypto dl z m)
set(LIBS ${LIBS} cares curl ev resolv ssh2 ssl psl crypto dl z m nghttp2)
target_link_libraries(${TARGET_NAME} ${LIBS})

# Link to static libraries if needed
IF(STATIC_LIB)
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s -static")
ENDIF(STATIC_LIB)

install(CODE "MESSAGE(\"Please install manually for now.\")")

然后:

mkdir b
cd b
cmake -DSTATIC_LIB=ON ..
make

file ./https_dns_proxy
./https_dns_proxy: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped