Cloudflare DNS Firewall で権威 DNS サーバー (BIND) を保護する

# Cloudflare DNS Firewall とは
DNS インフラを悪意ある攻撃から保護し、アップタイムを向上させ、高速なパフォーマンスを実現する DNS のための Firewall-as-a-Service (FWaaS) です。
例えば、オンプレにある権威DNSサーバー (BIND) 運用を維持したまま、ランダムサブドメイン攻撃や DDoS 攻撃などからオリジン権威 DNS サーバーを保護したい場合に有効なソリューションです。

:::note info
Enterprise のお客様を対象とした有償アドオン機能になります。
:::


- [DNS Firewall · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/)

>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/791dd36a-7530-c67e-f3aa-e04913025eff.png)

また、主な特徴は以下の通りです。

![dns_firewall_feature.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/d71db4e3-e5fd-4810-c82b-288b202d7387.png)


# 権威DNSサーバ (BIND) 準備

- [【BIND入門実践】BINDでDNSサーバーを構築してみよう](https://envader.plus/article/213)

# DNS Firewall セットアップ
ネームサーバーのIPをCloudflareに向けるだけです。

- [Set up DNS Firewall · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/setup/)

以下のステップで実装します。

- DNS Firewall クラスタ設定
- レジストラでグルーレコード変更
- ゾーンファイルでネームサーバーAレコード変更
- オリジンで Cloudflare IP を許可

```mermaid:
graph LR
Resolver --> |Cloudflare IP|Cloudflare["Cloudflare<br>DNS Firewall<br>--------------------------------------<br><br>- DDoS mitigation<br>- High availability<br>- Global distribution<br>- Enhanced performance<br>- Bandwidth savings<br>- Rate limiting per data center<br>- Cache DNS response<br>- DNS ANY query type block"] --> |Origin IP|NS[Origin<br>Authoritative<br>DNS Server]
```

## DNS Firewall クラスタ設定
権威DNSサーバー (BIND) のオリジン IP を入れて作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/e9b54a3e-9c46-dea5-b47e-eaffdc8d377b.png)

Cloudflare の IP が払い出されますので、次のステップ以降で使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/e28c6607-ad07-cf4e-2c52-58325aad8194.png)

## レジストラでグルーレコード変更

お名前.com では、以下の手順で変更できます。
グルーレコードを払い出された Cloudflare IP に設定します。

- [DNS関連機能の設定：ホスト設定｜お名前.com Navi ガイド｜ドメイン取るならお名前.com](https://www.onamae.com/guide/p/73)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/2fce2188-4acd-5edb-ffd1-861f6df4cd24.png)

## ゾーンファイルでネームサーバーAレコード変更
権威DNSサーバー (BIND) 側でも、ネームサーバーの A レコードを払い出された Cloudflare IP に設定します。

```conf:example.com
@       IN      NS      ns1.example.com.
@       IN      NS      ns2.example.com.
ns1     IN      A       172.x.x.x
ns2     IN      A       172.y.y.y
```

## オリジンで Cloudflare IP を許可
Cloudflare の公開 IP レンジを、オリジン側で `TCP / UDP port 53` が通るように許可してください。

- [IP Ranges | Cloudflare](https://www.cloudflare.com/ips/)

## 名前解決の確認
`dig +trace` により、払い出された Cloudflare IP `172.x.x.x` が権威 DNS として応答することを確認します。

```shell
% dig +trace +nodnssec example.com

; <<>> DiG 9.18.20 <<>> +trace +nodnssec example.com
;; global options: +cmd
.			511072	IN	NS	a.root-servers.net.
.			511072	IN	NS	b.root-servers.net.
.			511072	IN	NS	c.root-servers.net.
.			511072	IN	NS	d.root-servers.net.
.			511072	IN	NS	e.root-servers.net.
.			511072	IN	NS	f.root-servers.net.
.			511072	IN	NS	g.root-servers.net.
.			511072	IN	NS	h.root-servers.net.
.			511072	IN	NS	i.root-servers.net.
.			511072	IN	NS	j.root-servers.net.
.			511072	IN	NS	k.root-servers.net.
.			511072	IN	NS	l.root-servers.net.
.			511072	IN	NS	m.root-servers.net.
;; Received 239 bytes from 2606:4700:4700::1111#53(2606:4700:4700::1111) in 6 ms

site.			172800	IN	NS	b.z.net.
site.			172800	IN	NS	f.z.net.
site.			172800	IN	NS	a.z.net.
site.			172800	IN	NS	e.z.net.
;; Received 289 bytes from 202.12.27.33#53(m.root-servers.net) in 5 ms

example.com.		3600	IN	NS	ns1.example.com.
example.com.		3600	IN	NS	ns2.example.com.
;; Received 109 bytes from 2a04:2b00:13ff::61#53(f.z.net) in 62 ms

example.com.		86400	IN	A	34.z.z.z
example.com.		86400	IN	NS	ns1.example.com.
example.com.		86400	IN	NS	ns2.example.com.
;; Received 125 bytes from 172.x.x.x#53(ns1.example.com) in 17 ms
```

# 追加で API 設定できる項目 
こちらにある API パラメータ（ダッシュボードにないものが含まれる）を指定できます。

- [Update DNS Firewall Cluster - Cloudflare API Documentation](https://developers.cloudflare.com/api/operations/dns-firewall-update-dns-firewall-cluster)

```shell:getDnsClusterTag
export EMAIL='YOUR_EMAIL'
export APIKEY='YOUR_APIKEY'
export ACCOUNT_ID='YOUR_ACCOUNT_ID'

curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_firewall" \
 -H "X-Auth-Email: $EMAIL" \
 -H "X-Auth-Key: $APIKEY" | jq
```

## Rate Limit
API パラメータを使って、Rate Limit（データセンターあたり1秒あたりのクエリー数）を指定できます。

データセンターごとの1秒あたりのクエリ数の上限が、クラスタに設定されたオリジン権威 DNS サーバーに送信される DNS クエリに適用されます。

- [Additional options · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/setup/#additional-options)

```shell:
export CLUSTER_TAG='YOUR_CLUSTER_TAG'

curl -X PATCH "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_firewall/$CLUSTER_TAG" \
 -H "X-Auth-Email: $EMAIL" \
 -H "X-Auth-Key: $APIKEY" \
 -H "Content-Type: application/json" \
 --data '{
   "ratelimit":600
 }'
```

## ランダムサブドメイン攻撃（ランダムプレフィックス撃）保護

以下のようなランダムサブドメイン攻撃（ランダムプレフィックス撃）に対して、自動保護機構を有効化できます。

- [ランダムサブドメイン攻撃についてドメイン名登録者が出来ること](https://dnsops.jp/event/20230623/20230623-nagai.pdf)

>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/6da11911-e9fe-3580-030f-cbf1a9c0706f.png)
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a9ce2c13-e9fa-a244-9016-44da1115955b.png)

以下の API 操作により、有効化できます。

攻撃を検知すると、サブドメインやサブサブドメインなど、オリジン権威 DNS サーバーへの問い合わせを一時的に停止します。その後、Cloudflare はキャッシュされたレスポンスで応答します（TTLがまだ失効していない場合）。

> [FAQs — DNS Firewall · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/faq/)
> **DNSファイアウォールはどのくらい古いオブジェクトをキャッシュしますか?**
DNS Firewallは、割り当てられたメモリに応じてキャッシュの寿命を設定します。
>十分な割り当てメモリがある限り、Cloudflareは、TTLが失効しても、キャッシュからアイテムを強制的にクリアしません。この機能により、ネームサーバーがオフラインの場合、Cloudflareはキャッシュから古いオブジェクトを提供することができます。

また、`log_only` モードや `only_when_upstream_unhealthy` のオプションも設定できます。

- [Protect against random prefix attacks · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/random-prefix-attacks/setup/)

```shell:
export CLUSTER_TAG='YOUR_CLUSTER_TAG'

curl -X PATCH "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_firewall/$CLUSTER_TAG" \
 -H "X-Auth-Email: $EMAIL" \
 -H "X-Auth-Key: $APIKEY" \
 -H "Content-Type: application/json" \
 --data '{"attack_mitigation":{
   "enabled":true,
   "log_only":true,
   "only_when_upstream_unhealthy":false
   }
 }'
```

## 【参考】ランダムサブドメイン問い合わせ
例えば、自らテストしたい場合には以下のツールを使って ChatGPT に教えてもらったランダムなサブドメインに DNS クエリを投げることができます。

- [askmediagroup/dnsbench: Simple DNS server benchmarking tool](https://github.com/askmediagroup/dnsbench)

```shell:
dnsbench run --nameserver=8.8.4.4 --count=3000 --names "domains_to_lookup.txt"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a0e4042b-19c1-48d1-7524-31682bb87ee7.png)

# 統計データ・ログ
## Analytics
以下の API から統計データを取得できます。

- [Analytics · Cloudflare DNS docs](https://developers.cloudflare.com/dns/dns-firewall/analytics/)

```shell:
export CLUSTER_TAG='YOUR_CLUSTER_TAG'

% curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/dns_firewall/$CLUSTER_TAG/dns_analytics/report" \
 -H "X-Auth-Email: $EMAIL" \
 -H "X-Auth-Key: $APIKEY" | jq
{
  "result": {
    "rows": 1,
    "data": [
      {
        "metrics": [
          112
        ]
      }
    ],
    "data_lag": 0,
    "min": {},
    "max": {},
    "totals": {
      "queryCount": 112
    },
    "query": {
      "dimensions": [],
      "metrics": [
        "queryCount"
      ],
      "since": "2023-12-12T23:36:00Z",
      "until": "2023-12-13T05:36:00Z",
      "limit": 100000
    }
  },
  "success": true,
  "errors": [],
  "messages": []
}
```

## Logpugh

個々の詳細ログを確認するには、Logpush を構成する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/7da0b30b-68bb-980c-940c-bb64ac6335f0.png)

ログを見ていると、ランダムに大文字を含む問い合わせや存在しないサブドメインへの問い合わせがあることがわかります。

- [DNS Firewall Logs · Cloudflare Logs docs](https://developers.cloudflare.com/logs/reference/log-fields/account/dns_firewall_logs/)

```json:dns_firewall_logs.json
{
  "ClientResponseCode": 3, // NXDOMAIN
  "ClusterID": "xxx",
  "ColoCode": "NRT",
  "EDNSSubnet": "",
  "EDNSSubnetLength": 0,
  "QueryDO": true,
  "QueryName": "gaLActic-EXPlOrATIon.ExAMPLe.CoM",
  "QueryRD": false,
  "QuerySize": 62,
  "QueryTCP": false,
  "QueryType": 1,
  "ResponseCached": false,
  "ResponseCachedStale": false,
  "SourceIP": "173.194.168.132",
  "Timestamp": "2023-12-13T15:33:38Z",
  "UpstreamIP": "x.x.x.x",
  "UpstreamResponseCode": 3,
  "UpstreamResponseTimeMs": 9
}
```

# まとめ

Cloudflare DNS Firewall を使って権威 DNS サーバー (BIND) を保護する構成が取れることが確認できました。

統計データやログなどに関わる部分でも十分に透明性が期待できます。

オンプレなどに権威 DNS サーバー (BIND) をお持ちの方は、参考にしてみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/80bb7bdb-83c7-fd48-ac28-fe8a77ef74de.png)