定制 curl 支持 –dns-servers 也就是 c-ares 异步 DNS 解析

操作系统默认安装的 curl 是不支持指定自定义的 DNS 服务器的。我们在一台有域名过滤的服务器上, 需要跑 curl ,要绕过系统默认的 DNS 解析器,所以,需要在命令行下指定自己的 DNS 解析服务器,这个需要 c-ares 支持。

# ./configure --enable-ares --enable-https --with-nghttp2  --with-librtmp=/usr/lib/x86_64-linux-gnu --with-gssapi --with-zlib --with-libssh2
如果不想删除原先的 curl 包的话,运行一下:
# ln -s /usr/local/lib/libcurl.so.4.6.0 /usr/lib/x86_64-linux-gnu/libcurl.so.4

跑 configure 之前,当然要先安装相关的 dev 包:
libnghttp2-dev, libc-ares-dev, libssh2-1-dev, librtmp-dev

接下来我们就可以用 curl 来分析网页的 title 来大概知道某个域名是做什么的:

# /usr/local/bin/curl -sS --dns-servers "114.114.114.114" http://www.tuchong.com/|xmllint --html --nowarning --xpath '//title' - 2>/dev/null|tr -d 'a-z<>'

用 whoami.ds.akahelp.net 查看递归解析器

2018年5月 Akamai 在他们家博客上发布了这个新域名替代 whoami.akamai.net 的通知。

所有的计算机系统连接互联网的话,都需要一个 DNS 解析器,一般而言,在网络的边缘接入层,当在家庭或者企业用光猫或者路由器拨号或者其他方式接入运营商时,运营商会默认分配 DNS 。然后 DNS 污染就产生了,然后就有了国际求学的需求。

DNS 查询一般是需要一个递归解析器,帮我们的上网电脑作为客户端,把“正确”的 IP 地址返回给我们。运营商给我们的 DNS 服务器就是这样的递归解析器。譬如我们在 PPPoE 拨号路由上,设置自动获取运营商的 DNS ,就得到 116.228.111.118 和 180.168.255.18。

我们修改 Linux 主机上的 /etc/resolv.conf ,指定 nameserver 180.168.255.18 用 dig 命令多次查询 whoami , 就得到如下的结果:

我们可以修改 /etc/resolv.conf ,设置不同的 nameserver 到公共的 DNS 服务器,例如 1.1.1.1, 8.8.8.8,8.8.4.4, 233.5.5.5 等等,来用同样的 dig 命令来检查这些公共 DNS 服务器的递归服务器。

另外,如果要通过 DNS 查找自己的 IP 地址,我们可以用以下的三个 DNS 服务器里的任意一个来查找:

nslookup whoami.akamai.net. ns1-1.akamaitech.net.
nslookup -q=TXT o-o.myaddr.l.google.com. ns2.google.com.
nslookup myip.opendns.com. resolver1.opendns.com.

最后,我们必须提一下,用unbound 这个 DNS 解析软件,在企业局域网内部建设自己的 DNS 递归服务器。也就是说每次局域网内部的电脑请求 DNS 访问时,如果不在缓冲的话,都是向根服务器请求的,绕过了 ISP,也没有使用公共 DNS,这个在被污染的世界里,能保持出淤泥而不染,是绝对值得部署的。刚开始的时候,解析会慢,但是使用多了,就会很快。 配合广告,钓鱼域名的过滤规则,真正实现我命由我不由天!

我们的一台机器上跑了三个 DNS 服务,分别侦听在 53, 5300, 5350 上, 53 上的 dnsmasq 把 DNS Query 转发给 DNSCrypt-Proxy (5300),而 5350 上的 Unbound 是独立的,通过 unbound 查询递归服务器返回的 218.82 的地址,就是公司的公网地址。

再聊 DNS 加密以及广告去除以及黑名单

DNS 黑名单其实是一个很重要的话题,很多人往往忽略。曾经在北美某电子商务大厂(不是A)和内部信息安全部门有业务交往,我们被要求管理一个 DNS 黑名单,在公司内部遇到此类域名解析,一律定向到内部的一个域名,在上面有一个 Web 页面,当然是警告了。

如果企业内部的 DNS 都是自己解析,并且能维护一个黑名单的话,基本上 90% 的网络安全事件都是可控的。 甚至还可以做很多类似 GFW 在做的事情,把 Google.com 给你一个某度的地址。

所以说,你可以脑补一下,这个 DNS 是多么神奇的事情,可以把不想给你看的东西去掉,所以,广告以及有病毒的恶意网站域名都是第一批次就被过滤的。

说了那么多,技术上怎么实现呢? 企业内部有 IT 可以做自己的 DNS 服务器,个人家庭网络,要怎么做才能过滤广告,才能安心看片呢?

基本上,你需要一个能安装 Linux 的小盒子,放在光猫旁边,把光猫的 DHCP 功能去掉,把这个 Linux 小盒子通过无线或者有线连接到光猫上,然后 Linux 上启动 DHCP 和 DNS 服务功能。

那么这个 Linux 小盒子,有哪些不同的实现形式呢?最常见的就是能刷机的路由器,例如斐讯的K2 比较常见,华硕的很多也能刷机。这里列出一个能刷 OpenWrt Linux 操作系统的最新版本的一些无线路由器列表,最后两列为 Flash 和内存是购买时要主要考虑的。

我们知道,我们上网时,一般都是要走运营商的 DNS 来解析的,就算我们不使用运营商的,很多人会使用公共 DNS 服务器, 例如 114.114.114.114,但是他们并不能保证我们的 DNS 解析是安全的,而且类似 Google 的域名也是基本被“拐”的,就算有的人知道使用 Google 的 DNS 服务器 8.8.8.8/8.8.4.4 ,但是 DNS 解析本身是不安全的,也就是说,你看过的网站,运营商还是能知道你访问了哪些网站。

那怎么解呢?我们就需要在 Linux 小盒子上安装 Go 语言编写的 DNSCrypt-Proxy 这个免费软件。通过名称就可以知道,它是对 DNS 解析做加密的,能从网络上已知的 DNS 加密服务器上做解析,完全绕过了运营商,而且做了加密。

安装了这个软件,指定了黑名单以后,你就会感觉网页是清爽很多,没有什么狗皮膏药了。

譬如我们看 YouTube,按 F12, 就可以看到很多被屏蔽的域名。

譬如我们看新浪的一则新闻,屏蔽的内容就更多

指定黑名单其实不难, git clone 项目地址,里面有一个公共的黑名单清单, util 目录下还有一个 Python 脚本能自动生成这个黑名单。

企业和个人对这个方案有兴趣的可以关注我们公众号,并留言哦!

DNSCrypt 的黑名单机制,能有效的去除广告以及恶意网站。 不过,对于有些原生的广告图片嵌入, DSNcrypt 确实还是没有效果的,因为此类广告和页面内容的域名是同一个,你总不能因噎废食,把所有正常内容都过滤掉吧。 所以 DNSCrypt 是一个小盒子上的“硬件”解决方案,对于此类特殊的过滤,还是需要浏览器里的广告去除插件来进一步净化环境。

以 Sohu.com 首页下半部娱乐版块内嵌的广告为例,这是使用了 Adblock 以后什么广告都没有的情形:

这是没有使用 Adblock 插件时,小部分广告图片依然有展示。

Windows 客户端从 DHCP 服务器上自动取 DNS 域名搜索后缀

先给答案:不可能
标题里说的事情,在 DHCP 服务器上叫做 Option 119 DOmain Suffix Search

Linux 上的 DNS 服务器 dnsmasq ,有一个 dnsmasq –help dhcp 命令,能输出所有的选项:

具体来说就是在 dnsmasq 配置上添加如下:总体上三行是等效的,加了 force 是强制 push.

然后在查看到这篇文章:
https://serverfault.com/questions/37417/which-dhcp-client-os-support-dhcp-option-119-domain-suffix-search
里面提到的的微软的链接里,提到微软其实是不支持的。

用 dnsmasq + dnscrypt 实现企业级网络的 DNS 解析

DNS 无论在企业内部还是企业外部,都是无比重要的一个互联网工具。在云计算日益风行的今天,恐怕企业内外没有几个人会使用 IP 地址访问一项资源了。

然而各种的 DNS 解析方式和工具,不要说 Linux 就是在微软自己的体系里,也是各有千秋,从 NetBT 到 WINS 到 LMHOSTS 到 LLMNR 到微软自己的 DHCP/DNS 服务器。Sun Microsystem, 老早就发明了 NIS 来解析 Unix 世界里的名字, 苹果有 Apple Talk , 然后有 Bonjour ,这个技术在 Linux 里就是叫做 Avahi 的工具。

可以说微软的 NetBT, LLMNR 和 Linux 上的 Avahi 以及苹果的 Bonjour 是一个体系的,在局域网内没有 DNS服务器存在的时候,他们之间相互解析,就是采用 mDNS的广播技术(NetBT除外). DNS-SD 其实还是蛮有用处的, 不仅仅可以用来解析主机名(RR) 资源,还可以用来解析其他的服务,所以 SD=Service Discovery,就是可以用作微服务的服务发现的一种工具。

然而,如果我们在企业内部部署一套 dnsmasq 作为内网解析并作为转发服务器,在后端采用 dnscrypt-proxy ,把 DNS 数据包加密,就能有效的保护企业的隐私,并采用一定的 DNS Blacklist , 更能保护企业安全,防止用户访问一些有“毒”的网站。

CentOS 默认安装了 Network-Manager 作为本地解析的服务,采用 nmtui 命令或者 nmcli 命令可以管理网卡,然后会自动写入 /etc/resolv.conf ,本机的解析就会采用 Network-Manager 这个服务来实现,不会生成其他的 tcp/udp 端口。如果安装 avahi 软件包,并启用服务的话, 系统会打开 UDP 5353 端口,向外广播自己的地址,一般是 hostname.local 这样的格式。 记得停止 avahi-daemon 服务的是否,同时要停止 avahi-daemon.socket。
如果我们同时安装 systemd-resolved 软件包,那么系统启动 systemd-resolved 后,如果 /etc/systemd/resolved.conf 打开了 LLMNR 的话, 就会启用 tcp/udp 5355 端口,基本上在 CentOS 上,我们无需安装 systemd-resolved 软件包。

Ubuntu 上默认是没有 Network-Manager, 因此我们需要打开 systemd-resolved 服务, 但是在实际应用中,我们无需打开 mDNS 以及 LLMNR,因此,在 /etc/systemd/resolved.conf 中,我们只要配置到 DNS= 以及 Domains= 那两行即可,保持 LLMNR=no, MulticastDNS=no。可以看到会启动一个 127.0.0.53 上的 53 端口,作为本地解析。 /etc/resolv.conf 是一个 /run/systemd/resolve/stub-resolv.conf 的软连接。

Windows 上默认就是拿 DHCP 地址的,在其他软件栈上一般的用户无需做特殊的处理,我们就略过。Mac 笔记本回头再补充()。

基本上从本地 DNS 解析我们就可以说到这里,CentOS 就是 /etc/resolv.conf 直接写解析的 DNS 服务器地址,或者通过 nmtui 指定。 Ubuntu 上就是写 /etc/systemd/resolved.conf 文件,记得修改后 reload 服务。

接下来我们要介绍 dnsmasq 这把瑞士军刀,安装在企业局域网内,提供比传统的 BIND 还要牛逼的一些功能。

安装其实很简单,在 Ubuntu 1904 版本上,就是 apt install dnsmasq。
我的配置文件 /etc/dnsmasq.conf 如下:

domain-needed
bogus-priv
proxy-dnssec
filterwin2k
no-resolv
server=127.0.0.1#5300
local=/yj/
addn-hosts=/etc/pihole/hosts.static
addn-hosts=/etc/pihole/hosts-01.leases
addn-hosts=/etc/pihole/hosts-02.leases
dhcp-script=/sbin/dnsmasq_dhcp.sh
no-negcache
log-queries

附加的一个配置文件:

addn-hosts=/etc/pihole/gravity.list
addn-hosts=/etc/pihole/black.list
addn-hosts=/etc/pihole/local.list
localise-queries
cache-size=10000
log-facility=/var/log/pihole.log
local-ttl=2
dhcp-name-match=set:hostname-ignore,wpad
dhcp-name-match=set:hostname-ignore,localhost
dhcp-ignore-names=tag:hostname-ignore

DHCP 选项:

dhcp-authoritative
dhcp-range=192.168.7.61,192.168.7.90,24h
dhcp-option=option:router,192.168.7.1
dhcp-option=option:dns-server,192.168.7.11,192.168.7.12
dhcp-leasefile=/etc/pihole/dhcp-01.leases
domain=yj
local=/yj/
expand-hosts
dhcp-option=option6:dns-server,[::]
dhcp-range=::100,::1ff,constructor:ens8,ra-names,slaac,24h
ra-param=*,0,0
dhcp-option-force=option:domain-search,yj,yj777.cn

从配置我们可以知道, 提供了一个 61-90 的 DHCP 池,附加本地局域网后缀 .yj,DHCP 每次获取或者删除都会运行一个 /sbin/dnsmasq_dhcp.sh 的脚本。第一个配置文件里, 读取了 /etc/pihole 下三个附加的 hosts 文件, 从名字可以知道 hosts.static 就应该是一个静态解析的文件,企业网络内需要静态配置的地址,都直接修改这个文件即可, hosts-01.leases 和 hosts-02.leases 就是两台 DHCP 解析后,运行以上脚本,生成的“静态”文件。

为什么要这么做呢?

我们在环境里提供了两台 dnsmasq DHCP 服务,为了防止IP 冲突, 提供了两个不同的 DHCP Range,如果某台机器是在 01 服务器上取到的地址,那么通常的话, 通过 02 上的 dnsmasq 是无法解析该机器的,因此, 我们写了 /sbin/dnsmasq_dhcp.sh 脚本, 在两台机器上,分别生成自己的 hosts.leases 文件(一旦有自动 renew IP,两台 DHCP 的脚本都会响应), 而每次有修改后,自动 reload dnsmasq 服务,保证新的 DHCP 地址以“静态”的方式解析。至于静态的 hosts 文件,我们放在共享的 NFS 服务上, /etc/pihole 是一个 NFS 挂接点,每次有修改静态 IP 地址,当然需要 reload 两边的 dnsmasq 服务。

这样子, 通过 DHCP 和 静态 IP 的手工配置,(只需要配置一次),我们就实现了全网络的所有机器之间的 DNS 访问,而无需配置 avahi-daemon 或者打开 LLMNR 这样的端口,减少了机器上的网络堆栈可能引起的各种混乱。

dnscrypt-proxy 软件包的安装和配置也十分简单, apt install 后,systemctl –now enable dnscrypt-proxy 然后 status 命令看下服务状态即可。 配置文件是 /etc/dnscrypt-proxy/dnscrypt-proxy.toml,我们用 cloudflare 来解析。 端口配置为 5300,让 dnsmasq 转发到这个端口即可(参见以上 dnsmasq 配置的 server= 行)。

通过以上,我们设置两台 dns-01 和 dns-02 的服务器,各自运行 dnsmasq 和 dnscrypt-proxy , 共享一个 /etc/pihole 目录,存放相关的 hosts 配置,和动态生成的 hosts.leases 文件。

avahi-daemon & systemd-resolved & dnsmasq

写下这个标题的时候,就感觉这是一个庞大的课题,自己要做很多的研究和演练,才能把这几个不同的东西说清楚。

Avahi 的 org 官网非常干净,就一个简单的介绍,以及版本历史。简单的翻译一下, Avahi 就是一个类 Unix 上的通过 mDNS/DNS-SD 协议在局域网做服务发现的一个套件。

Arch Linux 有比较好的文档, 讲述了这些不同的组件,虽然 ArchLinux 不像红帽和 Ubuntu 那么流行,特别是版本管理采用了一个叫做 pacman 的工具。

Avahi 前面已经有介绍但是,ArchLinux 的文档特别的提到了 nsswitch.conf 文件相关的修改。

systemd-resolved :做本地 DNS 解析的一个服务,会侦听在 127.0.0.53 的 53 端口上做 mDNS 和 LLMNR 的解析,找不到就转发到后端/外部的 DNS 服务器。

DNS 里面另外需要了解的一个概念就是 NSS (Name Service Switch),Arch Linux 的文档也解释得比较细腻。文章最后的表格罗列了各种 DNS 软件的比较,也包含了 dnsmasq 。

dnsmasq 小巧但是功能强大, 包含了 DHCP/DNS/TFTP/PXE Boot/,特别是可以通过 OpenWRT 的 DNS Block,来过滤有害的域名,是局域网环境内不可多得的安全工具。

mDNS 在物联网的设备自动发现上会很有前途。这篇文章就介绍微软的一些计划苹果的一个文档介绍 mDNS
DNS-SD org 官网上有关于设置 Bonjour 名称服务器的一个文档

用 LLMNR协议实现 Windows 和 Linux 的统一访问

LLMNR 全称是 Link-local Multicast Name Resolution,微软 MSDN 上2010年的一篇文章有比较详细的解释。对于一个纯粹的 Windows 机器网络而言,IPv4 可以完全通过 NetBIOS over TCP/IP(NetBT) 实现,换言之, NetBT 是不支持 IPv6 的。

LLMNR有一个典型的应用是,在一个 802.11 无线临时网络里,在没有 DHCP 服务的情况下,相互之间能通过主机名访问。

LLMNR 采用和 RFC1035 规定的类似的DNS 消息通过 UDP 5355 端口通信。
RFC4795 规定了通过 TCP 5355 端口发送消息,但是 Windows(Vista) 不支持。

对于 IPv6 , LLMNR 通过 FF02::1:3 的多播地址,IPv4 是 224.0.0.252的多播地址。DNS解析启动时,主机会向网络广播自己的地址,如果没有冲突,就宣告自己为合法的主机名,如果有冲突,就会等15分钟继续广播查询。

非常幸运的是, Linux 的 systemd-resolved 也支持 LLMNR,但是不幸的是 CentOS7 还使用比较旧版本的 systemd (219),只有229版本以后才支持全功能。

具体而言就是配置文件 /etc/systemd/resolved.conf 只支持
DNS 和 LLMNR 以及 FallbackDNS 三个选项
这个可以通过运行 man resolved.conf 看到。而同样的,在 Ubuntu 1904 上,我们可以看到更多的配置选项, man 去看手册也有更多配置选项的介绍。

在 Ubuntu 上的配置是这样的:

我们内部有两台做加密 DNS 查询的安装有 dnsmasq + DNScrypt-Proxy 的虚拟机,Domains 是解析搜索的顺序,LLMNR 就是这里的主角,打开这个开关, systemd-resolved 服务就会启用 TCP/UDP 5355 端口。MulticastDNS 是多播,会和 avahi-daemon 冲突,由于我们计划使用 LLMNR,所以,多播包括 avahi-daemon 其实都是可以关闭的。

这样子,无论在 CentOS 7 上还是 Ubuntu 上,我们只要用 yum/apt install systemd-resolved 软件包后,根据自己需要修改好配置文件: /etc/systemd/resolved.conf ,然后 systemctl –now enable systemd-resolved 就可以实现 Linux 和 Windows 的无缝访问了。只要知道主机名就可以,无须理会 IP 地址,无须设置 DNS 服务器, avahi-daemon 的多播 DNS 也可以关闭(部分网关设备会开启 avahi-daemon 实现通过名字访问,苹果的机器也需要,所以可以根据情况决定是否关闭 Linux 上的 avahi-daemon)。

当然,事情绝对不会那么顺利,在 Ubuntu 上都能正常解析的主机名,在 CentOS 上都不能相互访问,原来是 /etc/nsswitch.conf 文件作怪。 Ubuntu 上的 这个文件, hosts 那一行非常简单:
hosts: files dns

但是在 CentOS 7 上,在安装有 avahi-daemon 后,这一行是:
hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname
在我们删除软件包 avahi-daemon 后,依然无解。正确的写法是:
hosts: files resolve [!UNAVAIL=return] dns

也就是说,CentOS 这里最大的坑就是 resolve 这个关键字! 没有这个关键字,系统是不会去走 LLMNR 解析的!!!

还有一个待解的问题,当操作系统是通过 dnsmasq DHCP 的 Linux ,通过 Windows 机器 ping 这些名字,都可以正常返回 IPv4 的地址,但是对于静态分配地址的机器,都只是返回 IPv6 的地址。

用一个简单的 Shell 脚本实现动态 DNS,自动更新办公室的 DNS 记录

几天前微信公众号上发了一篇《动态修改 AWS EC2 IP 并自动注册 GoDaddy DNS》,当时的意图是自动更新 EC2 的 IP 地址,自动注册 DNS。
然后想到,其实自己公司办公室也可以做成自动更新,假设我有一个 mydomain.com 的域名在 GoDaddy 上注册并管理的,那么,添加一条 office.mydomain.com 的记录, 任意指向一个地址,例如 1.2.3.4

然后,用这个 Github 上已经开源的动态更新 DNS的脚本,就可以实现 办公室内的机器,随时随地访问了。 当然, 需要你对路由器知识有一定的了解,要在办公室的路由器上把端口映射做好。
例如,把 2222 端口映射到内部一台机器 192.168.7.22 的 22 端口,那么 SSH 访问 $ ssh username@office.mydomain.com -p 2222 就是访问 192.168.7.22 的 SSH 服务了。

理论上来说,这个脚本也可以用到 阿里云,腾讯云的 DNS。请 fork/star 这个小脚本吧,star 到 5 -10 个,添加阿里云和腾讯云 DNS的自动注册。

这个方法,基本就不需要搭建复杂的 VPN 服务器,只是在公司内部的一台 Linux 服务器上,每 n 分钟跑一次这个脚本就可以,如果万一公司的 IP 地址修改了, 你还可以收到邮件提醒通知,然后你依然可以访问office.mydomain.com 。一个示例的每2分钟检查的 crontab 如下:
*/2 * * * * /root/bin/MyOffice.sh -d office.mydomain.com -t myemail@qq.com

端口映射做好以后,需要登录到外部网络,例如用 4G 上网,来测试端口映射,直接用内部 IP 访问 office.mydomain.com 是无法连接上做好端口映射的端口的。
一个通过外部的地址 nmap 办公室公网域名,得到的结果如下:(例子是上海电信某款光猫的结果,打开了三个端口 2222/3322/xxxx)

阿里云用 Go 语言写的命令行,配置 Profile