diff --git a/apps/smartdns/README.md b/apps/smartdns/README.md new file mode 100644 index 00000000..eeeb851f --- /dev/null +++ b/apps/smartdns/README.md @@ -0,0 +1,149 @@ +# SmartDNS + +**[English](https://github.com/pymumu/smartdns/blob/master/ReadMe_en.md)** + +![SmartDNS](doc/smartdns-banner.png) +SmartDNS 是一个运行在本地的 DNS 服务器,它接受来自本地客户端的 DNS 查询请求,然后从多个上游 DNS 服务器获取 DNS 查询结果,并将访问速度最快的结果返回给客户端,以此提高网络访问速度。 +SmartDNS 同时支持指定特定域名 IP 地址,并高性匹配,可达到过滤广告的效果; 支持DOT(DNS over TLS)和DOH(DNS over HTTPS),更好的保护隐私。 + +与 DNSmasq 的 all-servers 不同,SmartDNS 返回的是访问速度最快的解析结果。 + +支持树莓派、OpenWrt、华硕路由器原生固件和 Windows 系统等。 + +## 使用指导 + +SmartDNS官网:[https://pymumu.github.io/smartdns](https://pymumu.github.io/smartdns) + +## 软件效果展示 + +**阿里 DNS** +使用阿里 DNS 查询百度IP,并检测结果。 + +```shell +$ nslookup www.baidu.com 223.5.5.5 +Server: 223.5.5.5 +Address: 223.5.5.5#53 + +Non-authoritative answer: +www.baidu.com canonical name = www.a.shifen.com. +Name: www.a.shifen.com +Address: 180.97.33.108 +Name: www.a.shifen.com +Address: 180.97.33.107 + +$ ping 180.97.33.107 -c 2 +PING 180.97.33.107 (180.97.33.107) 56(84) bytes of data. +64 bytes from 180.97.33.107: icmp_seq=1 ttl=55 time=24.3 ms +64 bytes from 180.97.33.107: icmp_seq=2 ttl=55 time=24.2 ms + +--- 180.97.33.107 ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 24.275/24.327/24.380/0.164 ms +pi@raspberrypi:~/code/smartdns_build $ ping 180.97.33.108 -c 2 +PING 180.97.33.108 (180.97.33.108) 56(84) bytes of data. +64 bytes from 180.97.33.108: icmp_seq=1 ttl=55 time=31.1 ms +64 bytes from 180.97.33.108: icmp_seq=2 ttl=55 time=31.0 ms + +--- 180.97.33.108 ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 31.014/31.094/31.175/0.193 ms +``` + +**SmartDNS** +使用 SmartDNS 查询百度 IP,并检测结果。 + +```shell +$ nslookup www.baidu.com +Server: 192.168.1.1 +Address: 192.168.1.1#53 + +Non-authoritative answer: +www.baidu.com canonical name = www.a.shifen.com. +Name: www.a.shifen.com +Address: 14.215.177.39 + +$ ping 14.215.177.39 -c 2 +PING 14.215.177.39 (14.215.177.39) 56(84) bytes of data. +64 bytes from 14.215.177.39: icmp_seq=1 ttl=56 time=6.31 ms +64 bytes from 14.215.177.39: icmp_seq=2 ttl=56 time=5.95 ms + +--- 14.215.177.39 ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms +``` + +从对比看出,SmartDNS 找到了访问 www.baidu.com 最快的 IP 地址,比阿里 DNS 速度快了 5 倍。 + +## 特性 + +1. **多 DNS 上游服务器** + 支持配置多个上游 DNS 服务器,并同时进行查询,即使其中有 DNS 服务器异常,也不会影响查询。 + +1. **返回最快 IP 地址** + 支持从域名所属 IP 地址列表中查找到访问速度最快的 IP 地址,并返回给客户端,提高网络访问速度。 + +1. **支持多种查询协议** + 支持 UDP、TCP、DOT 和 DOH 查询及服务,以及非 53 端口查询;支持通过socks5,HTTP代理查询; + +1. **特定域名 IP 地址指定** + 支持指定域名的 IP 地址,达到广告过滤效果、避免恶意网站的效果。 + +1. **域名高性能后缀匹配** + 支持域名后缀匹配模式,简化过滤配置,过滤 20 万条记录时间 < 1ms。 + +1. **域名分流** + 支持域名分流,不同类型的域名向不同的 DNS 服务器查询,支持iptable和nftable更好的分流;支持测速失败的情况下设置域名结果到对应ipset和nftset集合。 + +1. **Windows / Linux 多平台支持** + 支持标准 Linux 系统(树莓派)、OpenWrt 系统各种固件和华硕路由器原生固件。同时还支持 WSL(Windows Subsystem for Linux,适用于 Linux 的 Windows 子系统)。 + +1. **支持 IPv4、IPv6 双栈** + 支持 IPv4 和 IPV 6网络,支持查询 A 和 AAAA 记录,支持双栈 IP 速度优化,并支持完全禁用 IPv6 AAAA 解析。 + +1. **支持DNS64** + 支持DNS64转换。 + +1. **高性能、占用资源少** + 多线程异步 IO 模式,cache 缓存查询结果。 + +1. **主流系统官方支持** + 主流路由系统官方软件源安装smartdns。 + +## 架构 + +![Architecture](https://github.com/pymumu/test/releases/download/blob/architecture.png) + +1. SmartDNS 接收本地网络设备的DNS 查询请求,如 PC、手机的查询请求; +1. 然后将查询请求发送到多个上游 DNS 服务器,可支持 UDP 标准端口或非标准端口查询,以及 TCP 查询; +1. 上游 DNS 服务器返回域名对应的服务器 IP 地址列表,SmartDNS 则会检测从本地网络访问速度最快的服务器 IP; +1. 最后将访问速度最快的服务器 IP 返回给本地客户端。 + +## 编译 + +- 代码编译: + + SmartDNS 提供了编译软件包的脚本(`package/build-pkg.sh`),支持编译 LuCI、Debian、OpenWrt 和 Optware 安装包。 + +- 文档编译: + + 文档分支为`doc`,安装`mkdocs`工具后,执行`mkdocs build`编译。 + +## 捐赠 + +如果你觉得此项目对你有帮助,请捐助我们,使项目能持续发展和更加完善。 + +### PayPal 贝宝 + +[![Support via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://paypal.me/PengNick/) + +### AliPay 支付宝 + +![alipay](doc/alipay_donate.jpg) + +### WeChat Pay 微信支付 + +![wechat](doc/wechat_donate.jpg) + +## 开源声明 + +SmartDNS 基于 GPL V3 协议开源。 \ No newline at end of file diff --git a/apps/smartdns/data.yml b/apps/smartdns/data.yml new file mode 100644 index 00000000..6c70ef04 --- /dev/null +++ b/apps/smartdns/data.yml @@ -0,0 +1,20 @@ +name: SmartDNS +tags: + - 工具 +title: 一个运行在本地的 DNS 服务器 +type: 工具 +description: 一个运行在本地的 DNS 服务器 +additionalProperties: + key: smartdns + name: SmartDNS + tags: + - Tool + shortDescZh: 一个运行在本地的 DNS 服务器 + shortDescEn: A local DNS server + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://pymumu.github.io/smartdns + github: https://github.com/pymumu/smartdns + document: https://pymumu.github.io/smartdns diff --git a/apps/smartdns/latest/.env.sample b/apps/smartdns/latest/.env.sample new file mode 100644 index 00000000..ce53b96c --- /dev/null +++ b/apps/smartdns/latest/.env.sample @@ -0,0 +1,2 @@ +CONTAINER_NAME="smartdns" +PANEL_APP_PORT_HTTP="40175" diff --git a/apps/smartdns/latest/data.yml b/apps/smartdns/latest/data.yml new file mode 100644 index 00000000..1838a00a --- /dev/null +++ b/apps/smartdns/latest/data.yml @@ -0,0 +1,10 @@ +additionalProperties: + formFields: + - default: 40175 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number diff --git a/apps/smartdns/latest/data/smartdns.conf b/apps/smartdns/latest/data/smartdns.conf new file mode 100644 index 00000000..5aa5f6d5 --- /dev/null +++ b/apps/smartdns/latest/data/smartdns.conf @@ -0,0 +1,368 @@ +# 监听53端口 +bind [::]:53 +# 配置上游服务器 +#server 119.29.29.29 +#server 223.5.5.5 +#server 180.184.1.1 +server-tls 1.1.1.1 +server-https https://doh.pub/dns-query +server-https https://dns.alidns.com/dns-query +server-https https://cloudflare-dns.com/dns-query + +force-qtype-SOA 65 +log-level info + +########################################### +# dns server name, default is host name +# server-name, +# example: +# server-name smartdns +# + +# whether resolv local hostname to ip address +# resolv-hostname yes + +# dns server run user +# user [username] +# example: run as nobody +# user nobody +# + +# Include another configuration options +# conf-file [file] +# conf-file blacklist-ip.conf + +# dns server bind ip and port, default dns server port is 53, support binding multi ip and port +# bind udp server +# bind [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection] +# bind tcp server +# bind-tcp [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection] +# bind tls server +# bind-tls [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection] +# bind-cert-key-file [path to file] +# tls private key file +# bind-cert-file [path to file] +# tls cert file +# bind-cert-key-pass [password] +# tls private key password +# bind-https server +# bind-https [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection] +# option: +# -group: set domain request to use the appropriate server group. +# -no-rule-addr: skip address rule. +# -no-rule-nameserver: skip nameserver rule. +# -no-rule-ipset: skip ipset rule or nftset rule. +# -no-speed-check: do not check speed. +# -no-cache: skip cache. +# -no-rule-soa: Skip address SOA(#) rules. +# -no-dualstack-selection: Disable dualstack ip selection. +# -no-ip-alias: ignore ip alias. +# -force-aaaa-soa: force AAAA query return SOA. +# -ipset ipsetname: use ipset rule. +# -nftset nftsetname: use nftset rule. +# example: +# IPV4: +# bind :53 +# bind :53@eth0 +# bind :6053 -group office -no-speed-check +# IPV6: +# bind [::]:53 +# bind [::]:53@eth0 +# bind-tcp [::]:53 +#bind [::]:53 + +# tcp connection idle timeout +# tcp-idle-time [second] + +# dns cache size +# cache-size [number] +# 0: for no cache +# -1: auto set cache size +# cache-size 32768 + +# enable persist cache when restart +# cache-persist no + +# cache persist file +# cache-file /tmp/smartdns.cache + +# cache persist time +# cache-checkpoint-time [second] +# cache-checkpoint-time 86400 + +# prefetch domain +# prefetch-domain [yes|no] +# prefetch-domain yes + +# cache serve expired +# serve-expired [yes|no] +# serve-expired yes + +# cache serve expired TTL +# serve-expired-ttl [num] +# serve-expired-ttl 0 + +# reply TTL value to use when replying with expired data +# serve-expired-reply-ttl [num] +# serve-expired-reply-ttl 30 + +# List of hosts that supply bogus NX domain results +# bogus-nxdomain [ip/subnet] + +# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter +# blacklist-ip [ip/subnet] + +# List of IPs that will be accepted when nameserver is configured -whitelist-ip parameter +# whitelist-ip [ip/subnet] + +# List of IPs that will be ignored +# ignore-ip [ip/subnet] + +# alias of IPs +# ip-alias [ip/subnet] [ip1[,ip2]...] +# ip-alias 192.168.0.1/24 10.9.0.1,10.9.0.2 + +# speed check mode +# speed-check-mode [ping|tcp:port|none|,] +# example: +# speed-check-mode ping,tcp:80,tcp:443 +# speed-check-mode tcp:443,ping +# speed-check-mode none + +# force AAAA query return SOA +# force-AAAA-SOA [yes|no] + +# force specific qtype return soa +# force-qtype-SOA [qtypeid |...] +# force-qtype-SOA [qtypeid|start_id-end_id|,...] +# force-qtype-SOA 65 28 +# force-qtype-SOA 65,28 +#force-qtype-SOA 65 + +# Enable IPV4, IPV6 dual stack IP optimization selection strategy +# dualstack-ip-selection-threshold [num] (0~1000) +# dualstack-ip-allow-force-AAAA [yes|no] +# dualstack-ip-selection [yes|no] +# dualstack-ip-selection no + +# edns client subnet +# edns-client-subnet [ip/subnet] +# edns-client-subnet 192.168.1.1/24 +# edns-client-subnet 8::8/56 + +# ttl for all resource record +# rr-ttl: ttl for all record +# rr-ttl-min: minimum ttl for resource record +# rr-ttl-max: maximum ttl for resource record +# rr-ttl-reply-max: maximum reply ttl for resource record +# example: +# rr-ttl 300 +# rr-ttl-min 60 +# rr-ttl-max 86400 +# rr-ttl-reply-max 60 + +# Maximum number of IPs returned to the client|8|number of IPs, 1~16 +# example: +# max-reply-ip-num 1 + +# response mode +# Experimental feature +# response-mode [first-ping|fastest-ip|fastest-response] + +# set log level +# log-level: [level], level=off, fatal, error, warn, notice, info, debug +# log-file: file path of log file. +# log-console [yes|no]: output log to console. +# log-size: size of each log file, support k,m,g +# log-num: number of logs, 0 means disable log +#log-level info + +# log-file /var/log/smartdns/smartdns.log +# log-size 128k +# log-num 2 +# log-file-mode [mode]: file mode of log file. + +# dns audit +# audit-enable [yes|no]: enable or disable audit. +# audit-enable yes +# audit-SOA [yes|no]: enable or disable log soa result. +# audit-size size of each audit file, support k,m,g +# audit-file /var/log/smartdns-audit.log +# audit-console [yes|no]: output audit log to console. +# audit-file-mode [mode]: file mode of audit file. +# audit-size 128k +# audit-num 2 + +# Support reading dnsmasq dhcp file to resolve local hostname +# dnsmasq-lease-file /var/lib/misc/dnsmasq.leases + +# certificate file +# ca-file [file] +# ca-file /etc/ssl/certs/ca-certificates.crt + +# certificate path +# ca-path [path] +# ca-path /etc/ss/certs + +# remote udp dns server list +# server [IP]:[PORT]|URL [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group] +# default port is 53 +# -blacklist-ip: filter result with blacklist ip +# -whitelist-ip: filter result with whitelist ip, result in whitelist-ip will be accepted. +# -check-edns: result must exist edns RR, or discard result. +# g|-group [group]: set server to group, use with nameserver /domain/group. +# e|-exclude-default-group: exclude this server from default group. +# p|-proxy [proxy-name]: use proxy to connect to server. +# -bootstrap-dns: set as bootstrap dns server. +# -set-mark: set mark on packets. +# -subnet [ip/subnet]: set edns client subnet. +# -host-ip [ip]: set dns server host ip. +# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2 +# server tls://dns.google:853 +# server https://dns.google/dns-query + +# remote tcp dns server list +# server-tcp [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-group [group] ...] [-exclude-default-group] +# default port is 53 +# server-tcp 8.8.8.8 + +# remote tls dns server list +# server-tls [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group] +# -spki-pin: TLS spki pin to verify. +# -tls-host-verify: cert hostname to verify. +# -host-name: TLS sni hostname. +# k|-no-check-certificate: no check certificate. +# p|-proxy [proxy-name]: use proxy to connect to server. +# -bootstrap-dns: set as bootstrap dns server. +# Get SPKI with this command: +# echo | openssl s_client -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 +# default port is 853 +# server-tls 8.8.8.8 +# server-tls 1.0.0.1 + +# remote https dns server list +# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group] +# -spki-pin: TLS spki pin to verify. +# -tls-host-verify: cert hostname to verify. +# -host-name: TLS sni hostname. +# -http-host: http host. +# k|-no-check-certificate: no check certificate. +# p|-proxy [proxy-name]: use proxy to connect to server. +# -bootstrap-dns: set as bootstrap dns server. +# default port is 443 +# server-https https://cloudflare-dns.com/dns-query + +# socks5 and http proxy list +# proxy-server URL -name [proxy name] +# URL: socks5://[username:password@]host:port +# http://[username:password@]host:port +# -name: proxy name, use with server -proxy [proxy-name] +# example: +# proxy-server socks5://user:pass@1.2.3.4:1080 -name proxy +# proxy-server http://user:pass@1.2.3.4:3128 -name proxy + +# specific nameserver to domain +# nameserver /domain/[group|-] +# nameserver /www.example.com/office, Set the domain name to use the appropriate server group. +# nameserver /www.example.com/-, ignore this domain + +# expand ptr record from address record +# expand-ptr-from-address yes + +# specific address to domain +# address /domain/[ip1,ip2|-|-4|-6|#|#4|#6] +# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client +# address /www.example.com/1.2.3.4,5.6.7.8, return multiple ip addresses +# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all +# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all + +# specific cname to domain +# cname /domain/target + +# enalbe DNS64 feature +# dns64 [ip/subnet] +# dns64 64:ff9b::/96 + +# enable ipset timeout by ttl feature +# ipset-timeout [yes] + +# specific ipset to domain +# ipset /domain/[ipset|-] +# ipset /www.example.com/block, set ipset with ipset name of block +# ipset /www.example.com/-, ignore this domain + +# add to ipset when ping is unreachable +# ipset-no-speed ipsetname +# ipset-no-speed pass + +# enable nftset timeout by ttl feature +# nftset-timeout [yes|no] +# nftset-timeout yes + +# add to nftset when ping is unreachable +# nftset-no-speed [#4:ip#table#set,#6:ipv6#table#setv6] +# nftset-no-speed #4:ip#table#set + +# enable nftset debug, check nftset setting result, output log when error. +# nftset-debug [yes|no] +# nftset-debug yes + +# specific nftset to domain +# nftset /domain/[#4:ip#table#set,#6:ipv6#table#setv6] +# nftset /www.example.com/ip#table#set, equivalent to 'nft add element ip table set { ... }' +# nftset /www.example.com/-, ignore this domain +# nftset /www.example.com/#6:-, ignore ipv6 + +# set ddns domain +# ddns-domain domain + +# set domain rules +# domain-rules /domain/ [-speed-check-mode [...]] +# rules: +# [-c] -speed-check-mode [mode]: speed check mode +# speed-check-mode [ping|tcp:port|none|,] +# [-a] -address [address|-]: same as address option +# [-n] -nameserver [group|-]: same as nameserver option +# [-p] -ipset [ipset|-]: same as ipset option +# [-t] -nftset [nftset|-]: same as nftset option +# [-d] -dualstack-ip-selection [yes|no]: same as dualstack-ip-selection option +# -no-serve-expired: ignore expired domain +# -delete: delete domain rule +# -no-ip-alias: ignore ip alias +# -no-cache: ignore cache + +# collection of domains +# the domain-set can be used with /domain/ for address, nameserver, ipset, etc. +# domain-set -name [set-name] -type list -file [/path/to/file] +# [-n] -name [set name]: domain set name +# [-t] -type [list]: domain set type, list only now +# [-f] -file [path/to/set]: file path of domain set +# +# example: +# domain-set -name domain-list -type list -file /etc/smartdns/domain-list.conf +# address /domain-set:domain-list/1.2.3.4 +# nameserver /domain-set:domain-list/server-group +# ipset /domain-set:domain-list/ipset +# domain-rules /domain-set:domain-list/ -speed-check-mode ping + +# set ip rules +# ip-rules ip-cidrs [-ip-alias [...]] +# rules: +# [-c] -ip-alias [ip1,ip2]: same as ip-alias option +# [-a] -whitelist-ip: same as whitelist-ip option +# [-n] -blacklist-ip: same as blacklist-ip option +# [-p] -bogus-nxdomain: same as bogus-nxdomain option +# [-t] -ignore-ip: same as ignore-ip option + +# collection of IPs +# the ip-set can be used with /ip-cidr/ for ip-alias, ignore-ip, etc. +# ip-set -name [set-name] -type list -file [/path/to/file] +# [-n] -name [set name]: ip set name +# [-t] -type [list]: ip set type, list only now +# [-f] -file [path/to/set]: file path of ip set +# +# example: +# ip-set -name ip-list -file /etc/smartdns/ip-list.conf +# bogus-nxdomain ip-set:ip-list +# ip-alias ip-set:ip-list 1.2.3.4 +# ip-alias ip-set:ip-list ip-set:ip-map-list \ No newline at end of file diff --git a/apps/smartdns/latest/docker-compose.yml b/apps/smartdns/latest/docker-compose.yml new file mode 100644 index 00000000..02f6e569 --- /dev/null +++ b/apps/smartdns/latest/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3' +services: + smartdns: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:53/udp" + volumes: + - "./data:/etc/smartdns" + image: pymumu/smartdns:latest + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/smartdns/logo.png b/apps/smartdns/logo.png new file mode 100644 index 00000000..896eb4f5 Binary files /dev/null and b/apps/smartdns/logo.png differ