NgDNS: https://github.com/selboo/ngdns-server
FROM: https://mp.weixin.qq.com/s/oZ2ftMgPtaDCygrgOUD3QA
最新 Nginx 已经支持 4层服务 ngx_stream_core_module, 有了 4层 支持我们可以做更多服务,
本篇我们用 OpenResty 配合 lua-resty-dns-server 做一个高性能 权威DNS 服务
先来看下压力测试, QPS 10W/s 左右
# cat /tmp/q.txt lb.sinacloud.com # queryperf -s 127.0.0.1 -d /tmp/q.txt -l 30 DNS Query Performance Testing Tool Version: $Id: queryperf.c,v 1.12 2007/09/05 07:36:04 marka Exp $ [Status] Processing input data [Status] Sending queries (beginning with 10.23.2.241) [Status] Testing complete Statistics: Parse input file: multiple times Run time limit: 30 seconds Ran through file: 3212709 times Queries sent: 3212710 queries Queries completed: 3212710 queries Queries lost: 0 queries Queries delayed(?): 0 queries RTT max: 0.000836 sec RTT min: 0.000069 sec RTT average: 0.000153 sec RTT std deviation: 0.000030 sec RTT out of range: 0 queries Percentage completed: 100.00% Percentage lost: 0.00% Started at: Wed Jun 19 17:05:33 2019 Finished at: Wed Jun 19 17:06:03 2019 Ran for: 30.000171 seconds Queries per second: 107089.722922 qps
OpenResty 安装
参考: http://openresty.org/en/installation.html
lua-resty-dns-server 安装
opm install vislee/lua-resty-dns-server
常见DNS类型, 都以支持
nginx.conf 配置
stream { server { listen 53 udp ; content_by_lua_file conf/53.lua; } }
53.lua 代码
local server = require 'resty.dns.server' local sock, err = ngx.req.socket() if not sock then ngx.log(ngx.ERR, "failed to get the request socket: ", err) return ngx.exit(ngx.ERROR) end local req, err = sock:receive() if not req then ngx.log(ngx.ERR, "failed to receive: ", err) return ngx.exit(ngx.ERROR) end local dns = server:new() local request, err = dns:decode_request(req) if not request then ngx.log(ngx.ERR, "failed to decode request: ", err) local resp = dns:encode_response() local ok, err = sock:send(resp) if not ok then ngx.log(ngx.ERR, "failed to send: ", err) ngx.exit(ngx.ERROR) end return end local query = request.questions[1] ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype) local cname = "sinacloud.com" if query.qtype == server.TYPE_A then local err = dns:create_a_answer(query.qname, 600, "192.168.1.1") local err = dns:create_a_answer(query.qname, 600, "192.168.2.2") if err then ngx.log(ngx.ERR, "failed to create cname answer: ", err) return end end local resp = dns:encode_response() local ok, err = sock:send(resp) if not ok then ngx.log(ngx.ERR, "failed to send: ", err) return end
dig 测试
# dig @127.0.0.1 lb.sinacloud.com ; <<>> DiG 9.9.4-RedHat-9.9.4-74.el7_6.1 <<>> @127.0.0.1 lb.sinacloud.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45924 ;; flags: qr rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;lb.sinacloud.com. IN A ;; ANSWER SECTION: lb.sinacloud.com. 600 IN A 192.168.1.1 lb.sinacloud.com. 600 IN A 192.168.2.2 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#(127.0.0.1) ;; WHEN: Wed Jun 19 17:27:17 CST 2019 ;; MSG SIZE rcvd: 98
后续
目前只是实现了一个很简单的例子, 如果做成一个可持续的服务, 还需要很多工作, 比如:
- DNS记录可以放到, Redis, MySQL 或这本地文件
- 封装 API接口, 可以动态修改 DNS记录
- 从 ngx.var.remote_addr 获取客户端IP, 支持智能解析
- tld 顶级域 QPS限制
- 记录请求日志
- 支持递归查询, 做 LocalDNS 服务
- 等等…
NgDNS: https://github.com/selboo/ngdns-server
转载请注明:爱开源 » 基于 OpenResty 权威DNS 服务