前言

目前,DNS服务的主要安全问题之一是DNS查询时加密性较弱。即使你浏览的网站启用了HTTPS保护,黑客还是可以窃取你和DNS服务器之间的数据包,获取你正在访问的内容。在本文中,我将向您展示如何通过HTTPS解析器将CloudFlare用作于DNS保护,以及如何使用libModSecurity过滤掉网络钓鱼站点。

当DNS服务不安全时,攻击者可以轻松地更改DNS的请求回复并将用户导向钓鱼站点,我们可以使用DNSSEC解决中间人攻击的问题,不幸的是只有一小部分网站使用了DNSSEC服务。

DNS over HTTPS

DNS over HTTPS(DoH)是一种通过HTTPS 执行远程DNS解析的协议。该方法的目标是通过防止中间人攻击窃听和操纵DNS数据来提高用户隐私和安全性。DNS over HTTPS 基于IETF(译者注:互联网工程任务小组)下的RFC 8484标准而制定。它使用HTTP/2和HTTPS协议,并支持“Wire Format(线型格式)”DNS响应数据,如果是UDP协议,响应包里面将会有MIME type(译者注:互联网媒体类型)为application/dns-message的HTTPS有效负载。

DoH 允许让用户将未加密的DNS查询发送到他的本地主机(例如127.0.0.1:53/udp),主机中有类似于DNS缓存服务器的东西,它可以接受查询并且通过HTTPS协议将其转发给CloudFlare DNS 1.1.1.1 。在这种情况下,可以防止未加密的DNS查询被监听。为了实施滤过操作,黑名单政策,保护用户隐私,其实使用HTTP协议更加便捷。这里,我们已经将通常的DNS查询转化为加密的HTTPS请求,为什么不顺带在上面加上一些过滤策略?开源的WAF ModSecurity可用于制定用户可以查询和不能查询的内容的规则!

当然,我们还可以添加一个“Pi-Hole” 黑名单策略,以阻止用户被导向某些恶意主机。其实我们还可以做更多!众所周知,许多网络钓鱼网站通常会选择一个狡猾的主机名来欺骗用户,例如login.google.com.access.pure-evil-phishing.xyz,那么我们可以使用来自letsencrypt(证书颁发机构)有效ssl证书来提醒用户。

让我们来测试一下,看看我是否能够发生一个DoH 查询给Nginx服务器,该服务器上的ModSecurity已经写好了一份规则:“如果用户DNS查询中包含google.com,并且google不是二级域名,com不是顶级域,那么将会阻止访问! ”。

示意图:

CloudFlare HTTPS解析机制

通过HTTPS向CloudFlare 1.1.1.1查询域名的最简单方法只需使用两个参数。我们向https://cloudflare-dns.com发送简单的GET请求,其中name为要解析的域名,type为所需的记录类型。这里,我们还需要将Accept头指定为application/dns-json

$ http 'https://cloudflare-dns.com/dns-query?name=google.com&type=A' 'accept:application/dns-json'
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
CF-RAY: 4a6750253a36be52-MXP
Connection: keep-alive
Content-Length: 203
Content-Type: application/dns-json
Date: Sat, 09 Feb 2019 15:19:13 GMT
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
Vary: Accept-Encoding
cache-control: max-age=36

{
    "AD": false,
    "Answer": [
        {
            "TTL": 36,
            "data": "216.58.205.78",
            "name": "google.com.",
            "type": 1
        }
    ],
    "CD": false,
    "Question": [
        {
            "name": "google.com.",
            "type": 1
        }
    ],
    "RA": true,
    "RD": true,
    "Status": 0,
    "TC": false
}

还有一种稍微复杂的方法,它需要你深入了解DNS协议。使用DNS Wire Format(它可以方便帮助我们创建ModSecurity规则)。

echo -n 'q80BAAABAAAAAAAAA3d3dwZnb29nbGUDY29tAAABAAE=' | base64 -d | \
curl -s -H 'content-type: application/dns-message' \
    --data-binary @- https://cloudflare-dns.com/dns-query | \
    hexdump -C

00000000  ab cd 81 80 00 01 00 01  00 00 00 01 03 77 77 77  |.............www|
00000010  06 67 6f 6f 67 6c 65 03  63 6f 6d 00 00 01 00 01  |.google.com.....|
00000020  c0 0c 00 01 00 01 00 00  00 ab 00 04 d8 3a cd 64  |.............:.d|
00000030  00 00 29 05 ac 00 00 00  00 00 00                 |..)........|
0000003b

无论如何,和你了解的那样,DNS查询中的域名可以分解为一系列标签,标签由一个长度的八位组加上一些八位组字节组成。让我们来分析www.google.com:查询时的解析过程:

\x03www\x06google\x03com代表www.google.com,隔一位,后面两个字节代表记录类型(例如A \x00\x01NS \x00\x02等),最后两个字节用于类(IN \x00\x01)。域名后面通常有一个root标签的零长度的八位组字节。

利用这些,我们可以轻松地在bash 中创建序列:

echo -ne '\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00'\
    '\x03www\x06google\x03com\x00'\
    '\x00\x01\x00\x01' | \
    hexdump -C

00000000  ab cd 01 00 00 01 00 00  00 00 00 00 03 77 77 77  |.............www|
00000010  06 67 6f 6f 67 6c 65 03  63 6f 6d 00 00 01 00 01  |.google.com.....|
00000020

我不想过多地讨论DNS协议,这里我只告诉你上面代码第一行的含义,\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00它是用来声明一些有用信息的标题,比如IDflag:“我是一个查询”等等...

这次我们用POST形式发送使用curl组合构造的请求。如下图所示:

echo -ne '\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01' | \
    curl -s -H 'content-type: application/dns-message' \
    --data-binary @- \
    https://cloudflare-dns.com/dns-query | \
    hexdump -C

00000000  ab cd 81 80 00 01 00 01  00 00 00 01 03 77 77 77  |.............www|
00000010  06 67 6f 6f 67 6c 65 03  63 6f 6d 00 00 01 00 01  |.google.com.....|
00000020  c0 0c 00 01 00 01 00 00  00 34 00 04 d8 3a cd 44  |.........4...:.D|
00000030  00 00 29 05 ac 00 00 00  00 00 00                 |..)........|
0000003b

CloudFlare的回应显示www.google.comA记录的长度为4个字节的0x04,其IP为0xd83acd44

CloudFlare DoH 客户端

CloudFlare已经公开了的DoH客户端源码,在https://developers.cloudflare.com/argo-tunnel/downloads/ 下载,安全完成后,我们使用sudo cloudflared proxy-dns运行:

我们有一个正在使用HTTPS和HTTP/2协议的Nginx服务器,并且安装了libModSecurity(这里有安装教程https://www.nginx.com/blog/compiling-and-installed-modsecurity-for-open-source-nginx/) 。首先,告诉cloudflared将所有请求转发到我们的网站。

# ./cloudflared proxy-dns --address 127.0.0.1 --upstream https://doh.rev3rse.it/dns-query
INFO[0000] Adding DNS upstream                           url="https://doh.rev3rse.it/dns-query"
INFO[0000] Starting DNS over HTTPS proxy server          addr="dns://127.0.0.1:53"
INFO[0000] Starting metrics server                       addr="127.0.0.1:44992"

现在我们只需简单处理来自cloudflared的所有请求并将它们转发到https://cloudflare-dns.com。使用Nginx可以轻松做到:

location ~* /dns-query {
    modsecurity on;
    modsecurity_rules_file conf/modsecurity.conf;

    proxy_redirect off;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host "cloudflare-dns.com";

    proxy_pass https://cloudflare-dns.com:443;
}

重新加载Nginx配置:

Nginx上的libModSecurity会以JSON 格式记录每个请求,Logstash(译者注:开源的服务器端数据处理管道)收集这些日志并发送到Elasticsearch(译者注:一个分布式、支持多租户的全文搜索引擎)。DoH的可以做到的最酷的事情之一是我可以使用Kibana(译者注:提供交互式可视化图形)查看请求

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖