# 【Linux】Dns 動態解析

若想實現同一個 DNS Server 根據不同來源 IP 返回不同的結果，這在 DNS 中稱為**視圖（View）或基於來源的策略解析**，以下是詳細實現方式。

---

### 使用 Bind 實現（最佳選擇）

Bind 支持基於來源 IP 的視圖配置，可以為不同來源的請求返回不同的 DNS 記錄。

#### 配置步驟

1. **安裝 Bind** 安裝 Bind DNS Server：
    
    ```
    sudo apt install <span class="hljs-built_in">bind</span>9
    
    ```
2. **配置視圖（View）** 編輯 Bind 的主配置文件 `/etc/bind/named.conf`，添加基於來源 IP 的視圖。
    
    範例配置：
    
    ```
    acl <span class="hljs-string">"internal-network"</span> {
        <span class="hljs-number">192.168</span>.<span class="hljs-number">1.0</span>/<span class="hljs-number">24</span><span class="hljs-comment">;</span>
    }<span class="hljs-comment">;</span>
    
    acl <span class="hljs-string">"external-network"</span> {
        any<span class="hljs-comment">;</span>
    }<span class="hljs-comment">;</span>
    
    view <span class="hljs-string">"internal"</span> {
        match-clients { <span class="hljs-string">"internal-network"</span><span class="hljs-comment">; };</span>
        zone <span class="hljs-string">"example.com"</span> {
            type master<span class="hljs-comment">;</span>
            file <span class="hljs-string">"/etc/bind/db.internal.example.com"</span><span class="hljs-comment">;</span>
        }<span class="hljs-comment">;</span>
    }<span class="hljs-comment">;</span>
    
    view <span class="hljs-string">"external"</span> {
        match-clients { <span class="hljs-string">"external-network"</span><span class="hljs-comment">; };</span>
        zone <span class="hljs-string">"example.com"</span> {
            type master<span class="hljs-comment">;</span>
            file <span class="hljs-string">"/etc/bind/db.external.example.com"</span><span class="hljs-comment">;</span>
        }<span class="hljs-comment">;</span>
    }<span class="hljs-comment">;</span>
    
    ```
3. **創建區域文件** 根據來源 IP 創建不同的區域文件。例如：
    
    
    - **內部網絡的區域文件 `/etc/bind/db.internal.example.com`**：
        
        ```
        <span class="hljs-meta">$TTL</span> <span class="hljs-number">604800</span>
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">SOA</span> example.com. admin.example.com. (
                <span class="hljs-number">1</span>   <span class="hljs-comment">; Serial</span>
                <span class="hljs-number">604800</span> <span class="hljs-comment">; Refresh</span>
                <span class="hljs-number">86400</span> <span class="hljs-comment">; Retry</span>
                <span class="hljs-number">2419200</span> <span class="hljs-comment">; Expire</span>
                <span class="hljs-number">604800</span> ) <span class="hljs-comment">; Negative Cache TTL</span>
        <span class="hljs-comment">;</span>
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">NS</span>  ns.example.com.
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">A</span>   <span class="hljs-number">192.168.1.1</span>
        
        ```
    - **外部網絡的區域文件 `/etc/bind/db.external.example.com`**：
        
        ```
        <span class="hljs-meta">$TTL</span> <span class="hljs-number">604800</span>
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">SOA</span> example.com. admin.example.com. (
                <span class="hljs-number">1</span>   <span class="hljs-comment">; Serial</span>
                <span class="hljs-number">604800</span> <span class="hljs-comment">; Refresh</span>
                <span class="hljs-number">86400</span> <span class="hljs-comment">; Retry</span>
                <span class="hljs-number">2419200</span> <span class="hljs-comment">; Expire</span>
                <span class="hljs-number">604800</span> ) <span class="hljs-comment">; Negative Cache TTL</span>
        <span class="hljs-comment">;</span>
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">NS</span>  ns.example.com.
        @   <span class="hljs-keyword">IN</span>  <span class="hljs-keyword">A</span>   <span class="hljs-number">203.0.113.1</span>
        
        ```
4. **重啟 Bind** 重啟 Bind 服務：
    
    ```
    sudo systemctl restart <span class="hljs-built_in">bind</span>9
    
    ```

---

### 使用 `dnsmasq` 實現（輕量級）

#### 配置步驟

1. **安裝 dnsmasq**
    
    ```
    sudo apt <span class="hljs-keyword">install</span> dnsmasq
    
    ```
2. **配置條件解析** 編輯 `/etc/dnsmasq.conf`，添加基於來源 IP 的條件解析規則：
    
    ```
    # 為內部網絡配置
    dhcp-range=set:internal,<span class="hljs-number">192.168</span><span class="hljs-meta">.1</span><span class="hljs-meta">.0</span>,<span class="hljs-number">192.168</span><span class="hljs-meta">.1</span><span class="hljs-meta">.255</span>
    address=/example.com/<span class="hljs-number">192.168</span><span class="hljs-meta">.1</span><span class="hljs-meta">.1</span>
    
    # 為外部網絡配置
    dhcp-range=set:external,<span class="hljs-number">0.0</span><span class="hljs-meta">.0</span><span class="hljs-meta">.0</span>,<span class="hljs-number">255.255</span><span class="hljs-meta">.255</span><span class="hljs-meta">.255</span>
    address=/example.com/<span class="hljs-number">203.0</span><span class="hljs-meta">.113</span><span class="hljs-meta">.1</span>
    
    ```
3. **重啟 dnsmasq**
    
    ```
    <span class="hljs-attribute">sudo systemctl restart dnsmasq</span>
    
    ```

---

### 使用 PowerDNS（動態解析）

- [https://wiki.freedomstu.com/books/%E9%96%8B%E6%BA%90%E8%BB%9F%E9%AB%94%E5%AE%89%E8%A3%9D%E6%B5%81%E7%A8%8B/page/powerdns-debian](https://wiki.freedomstu.com/books/%E9%96%8B%E6%BA%90%E8%BB%9F%E9%AB%94%E5%AE%89%E8%A3%9D%E6%B5%81%E7%A8%8B/page/powerdns-debian)
- [https://doc.powerdns.com/authoritative/indexTOC.html](https://doc.powerdns.com/authoritative/indexTOC.html)
- [https://blog.csdn.net/sdhzdtwhm/article/details/135910057](https://blog.csdn.net/sdhzdtwhm/article/details/135910057)
- [https://lantian.pub/article/modify-website/powerdns-lua-diy-geodns.lantian/](https://lantian.pub/article/modify-website/powerdns-lua-diy-geodns.lantian/)
- [https://github.com/PowerDNS/pdns/blob/master/docker-compose.yml](https://github.com/PowerDNS/pdns/blob/master/docker-compose.yml)

#### 配置 PowerDNS + Lua 脚本

PowerDNS 支持使用 Lua 腳本進行動態解析。

1. **安裝 PowerDNS 和相關組件**
    
    ```
    sudo apt <span class="hljs-keyword">install</span> pdns-<span class="hljs-keyword">server</span> pdns-backend-sqlite3
    
    ```
2. **啟用 Lua 腳本支持** 在 `/etc/powerdns/pdns.conf` 中啟用 Lua Backend：
    
    ```
    <span class="hljs-attr">launch</span>=gsqlite3,lua
    <span class="hljs-attr">lua-dns-script</span>=/etc/powerdns/dns.lua
    
    ```
3. **編寫 Lua 腳本** 創建 `/etc/powerdns/dns.lua`，根據來源 IP 返回不同的結果：
    
    ```
    <span class="hljs-keyword">function</span> postresolve(remoteip, domain, qtype)
        <span class="hljs-keyword">if</span> string.match(remoteip, <span class="hljs-string">"^192%.168%.1%."</span>) <span class="hljs-keyword">then</span>
            <span class="hljs-keyword">return</span> {{qtype=<span class="hljs-string">"A"</span>, content=<span class="hljs-string">"192.168.1.1"</span>, ttl=<span class="hljs-number">60</span>}}
        <span class="hljs-keyword">else</span>
            <span class="hljs-keyword">return</span> {{qtype=<span class="hljs-string">"A"</span>, content=<span class="hljs-string">"203.0.113.1"</span>, ttl=<span class="hljs-number">60</span>}}
        <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">end</span>
    
    ```
4. **重啟 PowerDNS**
    
    ```
    <span class="hljs-attribute">sudo systemctl restart pdns</span>
    
    ```

---

### 測試

#### 使用 `dig` 測試

針對不同的來源 IP 測試返回的解析結果。

- 從內部網絡：
    
    ```
    <span class="hljs-keyword">dig</span> @<span class="hljs-symbol"><DNS_SERVER_IP></span> example.<span class="hljs-keyword">com</span>
    
    ```
    
    返回內部地址（例如 `192.168.1.1`）。
- 從外部網絡：
    
    ```
    <span class="hljs-keyword">dig</span> @<span class="hljs-symbol"><DNS_SERVER_IP></span> example.<span class="hljs-keyword">com</span>
    
    ```
    
    返回外部地址（例如 `203.0.113.1`）。

---

### 注意事項

1. **來源 IP 檢測**：
    
    
    - 檢查網絡路由，確保 DNS 伺服器能正確檢測請求的來源 IP。
    - 若有 NAT 設置，需配置正確的來源地址。
2. **DNS 緩存**：
    
    
    - 若存在 DNS 緩存伺服器，可能會干擾條件解析結果。
3. **性能**：
    
    
    - `Bind` 和 `PowerDNS` 適合高流量環境。
    - `dnsmasq` 適合輕量級應用場景。

這些方案可以靈活地根據來源 IP 實現不同的 DNS 解析結果。