上次收集整理[[170822 获取Local DNS 地址信息]]) 的时候看到akamai 的whoami.akamai.net
,想起之前看到agentzh 基于OpenResty实现了一个权威DNS 服务器,感觉可以用openresty 简单快速的实现。
找到agentzh 当时的 gist,第一次学习OpenResty ,决定照猫画虎。看起来要在OpenResty 里面接受dns 数据包,并且返回,需要用到stream-lua-nginx-module这个模块,这里要注意的时候,截至目前(2017-08-30) master 分支还不支持 ngx.req.udp_socket
,agentzh 当时hack 的代码都在 bloody-dns-server 分支下面。
编译OpenResty
说来惭愧,编译OpenResty费了好大一番工夫。先是没有看清stream-lua-nginx-modele 的分支,直接用master 分支的编译,测试代码的时候直接返回 ngx.req.udp_socket
是空。
然后用bloody-dns-server 分支编译,又遇到 mmdb 库的问题。Mac OS 下需要在编译的时候指定maxminddb 的库:
./configure \
--with-cc-opt="-I/usr/local/opt/openssl/include/ -I/usr/local/opt/pcre/include/" \
--with-ld-opt="-L/usr/local/opt/openssl/lib/ -L/usr/local/opt/pcre/lib/ -L/opt/mmdb/lib -lmaxminddb" \
--with-stream \
--with-stream_ssl_module \
--add-module=./bundle/stream-lua-nginx-module
不然会出现一堆:
undefined reference to `MMDB_open'
undefined reference to `MMDB_strerror'
undefined reference to `MMDB_lookup_sockaddr'
ndefined reference to `MMDB_strerror'
...
我看了一下 stream-lua-nginx-module 的build.sh
是显式指定了-L/opt/mmdb/lib -lmaxminddb
,但是nginx 编译的时候没指定,就会报错。
相关问题:ld: symbols not found for architecture x86_64, clang: linker command failed。
遇到错误:
nginx: [alert] cannot open file /opt/mmdb/database/GeoLite2-Country.mmdb for reading: Error opening the specified MaxMind DB file in
去Maxmind 官网下一个,丢到对应的目录即可。
另外编译的时候要注意选择版本,我选择的是OpenResty-1.11.2.5,其中的Nginx 的版本是1.11.2
,太新的Nginx 可能没测试过。
实现whoami.akamai.net
编译成功之后,就是开始动手了。
首先是DNS 报文格式,参考这2篇文章:
以及自己用wireshark 抓包分析。
对着文档一个一个bit 校对,对任何DNS 查询报文,都拿出它的IP,然后返回一条A记录就好了,效果如下:
上线
我在个人的VPS 上部署了一个,再添加一条NS 记录,注意需要是域名,不能添加IP:
再 dig whoami.example.com
或者 ping whoami.example.com
即可。
代码
实现代码: whoami.lua