浅析如何保护DNS

2019-04-04 约 2677 字 预计阅读 6 分钟

声明:本文 【浅析如何保护DNS】 由作者 Hulk 于 2019-02-28 07:47:00 首发 先知社区 曾经 浏览数 570 次

感谢 Hulk 的辛苦付出!

前言

目前,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(译者注:提供交互式可视化图形)查看请求

关键词:[‘安全技术’, ‘技术讨论’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now