BIG-IPで簡易DNS応答VSを作成する

F5社負荷分散装置BIG-IPにて簡易DNS応答用Virtual Server(VS)を作成した際のメモです。

DNSサーバーはLinuxのBINDを用いて構築することが多いと思いますが、
利用できるLinuxがない場合にBIG-IPを用いて簡易DNSサーバーを構築した例を紹介します。


:::note warn
DNS_REQUESTイベントを利用するためにはDNS Servicesオプションが必要です。
DNSサーバーの高度な機能を用いる場合はAddon licneseが必要です。
:::

# 設定方法

簡易DNS応答用Virtual Serverの主要パラメータは下記です。

| 項目 | 入力内容 |
|--|----------|
| Virtual ServerのType | Standard |
| Service Port | 53 |
| protocol | udp |
| DNS Profile | dns(default) | 
| Pool | なし | 
| irule | DNS応答用iRule | 

※ DNS応答用iRuleを紐づけるためには、Type=Standard および DNS Profielの選択が必須


# DNS応答用iRule

F5 DevCentralで紹介されているiRule例を参考に修正する

DNSへの問い合わせ時のHost名は大文字/小文字が混ざることがあるため、string tolowerコマンドを利用し、小文字へ一括返還した文字列を条件文で照合

```console: if文を用いたirule例
when DNS_REQUEST {
    set type [DNS::question type]
    if {$type equals "A" } {
        set host [string tolower [DNS::question name]]
        if {$host contains "www.test.local" } {
            DNS::answer insert "[DNS::question name]. 120 [DNS::question class] [DNS::question type] 10.0.0.1"
            DNS::return
            # log local0. "return dns www.test.local to 10.0.0.1"
        } elseif {$host contains "www.test2.local" } {
            DNS::answer insert "[DNS::question name]. 120 [DNS::question class] [DNS::question type] 10.0.0.2"
            DNS::return
            # log local0. "return dns www.test2.local to 10.0.0.2"
        }
    }
}
```

```console: 応答結果
# dig www.test.local @10.0.0.100

; <<>> DiG 9.11.22 <<>> www.test.local @10.0.0.100
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63479
;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.test.local.                        IN      A

;; ANSWER SECTION:
www.test.local.         120     IN      A       10.0.0.1

;; Query time: 1 msec
;; SERVER: 10.0.0.100#53(10.0.0.100)
;; WHEN: Tue Apr 18 16:17:34 JST 2023
;; MSG SIZE  rcvd: 59
```


簡易DNS用VSにGoogle DNS(8.8.4.4)を含めたPoolを紐づけて
iRuleで回答できない宛先(下記例ではwww.yahoo.co.jp)のDNS問い合わせを行った場合

```console: 応答結果
# dig www.yahoo.co.jp @10.0.0.100

; <<>> DiG 9.11.22 <<>> www.yahoo.co.jp @10.0.0.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37086
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.yahoo.co.jp.               IN      A

;; ANSWER SECTION:
www.yahoo.co.jp.        297     IN      CNAME   edge12.g.yimg.jp.
edge12.g.yimg.jp.       34      IN      A       182.22.25.124

;; Query time: 27 msec
;; SERVER: 10.0.0.100#53(10.0.0.100)
;; WHEN: Tue Apr 18 16:35:11 JST 2023
;; MSG SIZE  rcvd: 88
```

## その他 

登録したいDNS宛先が多い場合には、Data Groupを利用する

```console: Data Groupを用いたirule例
when DNS_REQUEST {
    set type [DNS::question type]
    if {$type equals "A" } {
        set host [string tolower [DNS::question name]]
        if { [class match $host equals dns_List_DG ] } {
            DNS::answer insert "[DNS::question name]. 120 [DNS::question class] [DNS::question type] [class match -value $host equals dns_List_DG ]"
            DNS::return
        }
    }
}
```

```console: 応答結果(nslookup)
PS C:\Users\test> nslookup www.test3.local 10.0.0.100
サーバー:  UnKnown
Address:  10.0.0.100

権限のない回答:
名前:    www.test3.local
Address:  10.0.0.3
```




Data Groupの設定例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329464/b2302be0-d56c-457d-0825-78cf7e39a269.png)



# 参考

Simple iRule For DNS Intercept on Big IP DNS
https://community.f5.com/t5/technical-forum/simple-irule-for-dns-intercept-on-big-ip-dns/td-p/268221