技术分享 | 基于 OpenResty 权威 DNS 服务

Posted 新浪云计算

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术分享 | 基于 OpenResty 权威 DNS 服务相关的知识,希望对你有一定的参考价值。

最新的 nginx 已经支持 4 层服务 ngx_stream_core_module, 有了 4 层支持我们可以做更多服务,本篇我们用 OpenResty 配合 lua-resty-dns-server 做一个高性能权威 DNS 服务。

查看更多信息请参考:

http://nginx.org/en/docs/stream/ngx_stream_core_module.html

http://openresty.org/cn

https://github.com/vislee/lua-resty-dns-server


先来看下压力测试,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类型, 都已支持 

  • TYPE_A 

  • TYPE_NS 

  • TYPE_CNAME 

  • TYPE_SOA 

  • TYPE_MX 

  • TYPE_TXT 

  • TYPE_AAAA  

  • TYPE_SRV  

  • TYPE_ANY 

查看更多信息请参考:

https://github.com/vislee/lua-resty-dns-server


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 服务等等...



以上是关于技术分享 | 基于 OpenResty 权威 DNS 服务的主要内容,如果未能解决你的问题,请参考以下文章

又拍云邵海杨:基于 OpenResty 的动态服务路由方案

速致云技术分享:云时代的多面手,OpenResty在云计算领域的开源应用

HelloTalk 基于 OpenResty 的全球化探索之路

个推PPT | 基于OpenResty和Node.js的微服务架构实践

Nginx+lua+openresty系列 | 第一篇:openresty介绍

2019 OpenResty 北京大会征集议题