# 網路相關

# 【Cisco】Switch相關指令

```
LAB 2-1:Switch基本環境設定

清除Switch的組態設定
Switch>enable 
Switch#erase startup-config 
Switch#delete vlan.dat
Switch#reload

Switch設主機名稱
Switch#configure terminal 
Switch(config)#hostname lab2

console閒置設0分,啟用logging訊息輸出後自動換行功能
lab2(config)#line console 0
lab2(config-line)#exec-timeout 0  (閒置登出)
lab2(config-line)#logging synchronous  (訊息同步)

停用網域名稱反查
lab2(config-line)#exit
lab2(config)#no ip domain-lookup

設定界面資訊(description),雙工(duplex)模式及介面速度(speed)
lab2(config)#interface fastEthernet 0/12
lab2(config-if)#description TORouter
lab2(config-if)#duplex auto (預設auto)
lab2(config-if)#speed auto  (預設auto)
lab2(config-if)#exit

設定Switch IP及Gateway (L2 Switch訂IP管理用)
lab2(config)#interface vlan 1
lab2(config-if)#ip address 192.168.0.250 255.255.255.0
lab2(config-if)#no shutdown 
lab2(config-if)#exit
lab2(config)#ip default-gateway 192.168.0.254 (跨網段管理)

show 相關設定,存入NVRAM
lab2#show running-config 
lab2#show vlan 1
lab2#show interfaces fastEthernet 0/12
lab2#copy running-config startup-config 
LAB 2-2:Switch安全防護設定

設定Console及vty密碼
lab2#configure terminal 
lab2(config)#line console 0
lab2(config-line)#password console
lab2(config-line)#login 
lab2(config-line)#exit
lab2(config)#line vty 0 15
lab2(config-line)#password vty
lab2(config-line)#login
lab2(config-line)#exit

設定privileged mode的密碼並檢視
lab2(config)#enable password password
lab2(config)#enable secret cisco
lab2(config)#end
lab2#sh running-config

設定SSH
lab2#configure terminal 
lab2(config)#ip domain-name example.com
lab2(config)#crypto key generate rsa 
lab2(config)#username netadmin password netadmin
lab2(config)#ip ssh version 2
lab2(config)#line vty 0 15
lab2(config-line)#login local
lab2(config-line)#transport input ssh telnet

直接進入特權模式
lab2(config)#no username {netadmin}
lab2(config)#username {name} privilege 15 password {password}

啟用密碼加密服務
lab2#conf t
lab2(config)#service password-encryption 
lab2(config)#do show running-config | begin line

設定Login banner
lab2(config)#banner login >
  HI !!!! >
LAB 2-3:Port Security(防非法MAC存取)

 

Port security 只能針對Access mode的Port設定
enable port security
(Optional)設定最大MAC數量,預設 1 sh不顯示,Cisco設備預設值通常不顯示
違規時switch的動作violation{ shutdown預設 | restrict | protect}
1~4只防阻MAC Flooding攻擊,每一個port只能有1個MAC通過,但還不能防止非法MAC接到設備上,把合法MAC寫到table,只要MAC有錯port shutdown
在Switch上查看MAC-Address-Table
lab2#show mac-address-table (有些版本 show mac address-table)

將FA0/24啟用Port-Security功能,指定只學習一筆MAC資訊,使用Sticky方式學習到PC的MAC,並設定違規處理方式為Shutdown
lab2#configure terminal 
lab2(config)#interface fastEthernet 0/24  (多個Port可用range)
lab2(config-if)#switchport mode access  (將Port改成Access Mode)
lab2(config-if)#switchport port-security  (啟用Port Security)
lab2(config-if)#switchport port-security maximum 1  (設定最大的MAC數量)
lab2(config-if)#switchport port-security mac-address sticky 
lab2(config-if)#switchport port-security violation shutdown(預設,處理err-disabled)
或
lab2(config-if)#switchport port-security violation restrict  (合法MAC接回就會通)


range 多個Port要設定
lab2(config)#interface range fastEthernet 0/4 - 7 , fastEthernet 0/9 - 11
lab2(config-if-range)#switchport mode accesss

檢查所有界面的狀態(Port,Description Name,Status,Vlan,Duplex,Speed,Type)
lab2#sh interfaces status

檢查Switch上有哪些Port啟用Port-security
lab2(config-if)#do sh port-security

檢查Switch上有哪些Port有sticky或手動輸入合法MAC Address
lab2(config-if)#do sh port-security address

檢查Fa0/24的Port-security的詳細設定
lab2(config-if)#do sh port-security interface fastethernet 0/24

檢查Fa0/24的介面狀態(注意err-disabled)
lab2(config-if)#do sh int fa 0/24
            

將Fa0/24接另一台PC,因為Fa0/24有啟用Port-security,並將之前自動學習到的MAC以Sticky記錄,檢查Fa0/24的介面狀態會出現err-disabled:以下處理方法
lab2#sh int fa 0/24
FastEthernet0/24 is down, line protocol is down (err-disabled)
lab2#sh run | begin FastEthernet0/24
!
interface FastEthernet0/24
 switchport mode access
 switchport port-security
 switchport port-security mac-address sticky 
 switchport port-security mac-address sticky 0030.F22D.9A05
!
lab2#conf t
lab2(config)#int fa 0/24
lab2(config-if)#no switchport port-security mac-address sticky 0030.F22D.9A05
lab2(config-if)#do sh int fa 0/24
FastEthernet0/24 is down, line protocol is down (err-disabled)
lab2(config-if)#shutdown 
lab2(config-if)#no shutdown 
LAB 2-4:CDP與檔案備份練習

CDP查詢鄰近設備
lab2#sh cdp neighbors  (Device ID =>ro)
lab2#sh cdp entry ro

將Switch的fa0/3介面CDP功能關閉
lab2(config)#int fa 0/3
lab2(config-if)#no cdp enable

將設備dcp功能關閉
lab2(config)#no cdp run

將Switch的IOS與startup-config複製到TFTP
lab2#sh flash
lab2#copy flash tftp
lab2#copy running-config startup-config 
lab2#copy startup-config tftp

 

show 的使用
lab2#sh running-config | begin line
lab2#sh running-config | include line
lab2#sh interfaces status
lab2#sh mac address-table
#
#
#
```

# 【Fiddler】玩轉 Fiddler－HTTP(s) 抓包能手

# [玩轉 Fiddler－HTTP(s) 抓包能手 &amp; 常見「特殊」用途](https://ryanlee.tw/2021/08/23/fiddler/)

[https://ryanlee.tw/2021/08/23/fiddler/](https://ryanlee.tw/2021/08/23/fiddler/)

# 【Mac】透過console連接網路設備

需求：一條usb - console 線

[![image-1656036189511.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-06/scaled-1680-/6FeDtIIUNCCWS8hW-image-1656036189511.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-06/6FeDtIIUNCCWS8hW-image-1656036189511.png)

接上後，打開終端機，使用screen 登入設備

```shell
#找到 console 線
ll /dev/tty.*
crw-rw-rw-  1 root  wheel    9,   0  6 22 22:26 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw-  1 root  wheel    9,   2  6 24 09:58 /dev/tty.usbserial-A50285BI

#登入設備
screen /dev/tty.usbserial-A50285BI 9600
```

---

### screen其他操作

##### 退出後重連失敗

[![image-1656038788632.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-06/scaled-1680-/cllKnxGHBiZhc1Jj-image-1656038788632.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-06/cllKnxGHBiZhc1Jj-image-1656038788632.png)

```shell
#找到screen pid
screen -list

There are screens on:
        15520.ttys004.Treeman-Mac       (Attached)
        9100.ttys003.Treeman-Mac        (Detached)
2 Sockets in /var/folders/px/8z7kvlwj5278qcf92c71q6_h0000gn/T/.screen.

#方法一 刪除socket 重新連線
#刪除sccket screen -X -S {pid} quit
# -X: 執行cmd, -S: screen socket name, quit: 離開
screen -X -S 9100.ttys003.Treeman-Mac quit
#在連線一次
screen /dev/tty.usbserial-A50285BI 9600

#方法二 使用screen pid.name重新連線
screen -R 9100.ttys003.Treeman-Mac

#方法三 重新連線上次中斷screen
screen -r
```

# 【zabbix】自定義通知(轉貼)

 開啟 https://notify-bot.line.me/zh\_TW/

登入帳號後，下拉選項，選取「個人頁面」→「發行權杖」→「透過1對1聊天接收LINE Notify的通知」

之後就會得到一組權杖「Token」，這組Token務必要記錄下來，出現後便不再顯示

<div id="bkmrk-zabbix-server%E7%AB%AF">Zabbix Server端</div> **設定Scritp**

`sudo vi /usr/lib/zabbix/alertscripts/line_notify.sh`

<table border="1" cellpadding="1" cellspacing="1" id="bkmrk-%23%21%2Fbin%2Fbash%23-line-no"><tbody><tr><td>\#!/bin/bash  
\# LINE Notify Token - Media &gt; "Send to".  
TOKEN="$1"

\# {ALERT.SUBJECT}  
subject="$2"

\# {ALERT.MESSAGE}  
message="$3"

curl https://notify-api.line.me/api/notify -H "Authorization: Bearer ${TOKEN}" -F "message=${message}"

</td></tr></tbody></table>

`sudo chmod 755 /usr/lib/zabbix/alertscripts/line_notify.sh<br></br>sudo chown zabbix:zabbix line_notify.sh`

<div id="bkmrk-zabbix-ui-%E8%A8%AD%E5%AE%9A">Zabbix Ui 設定</div>**1. 「管理」→「示警媒介類型」→「創建示警媒介類型」**

[![image-1656924835958.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/ZpS1LqW4Q8srpH7v-image-1656924835958.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/ZpS1LqW4Q8srpH7v-image-1656924835958.png)

Name：Line Notify  
Type：Script  
Script name：line\_notify.sh  
Script parameters：  
{ALERT.SENDTO}  
{ALERT.SUBJECT}  
{ALERT.MESSAGE}

**2.「管理」→「用戶」→「Admin」→「示警媒介」→「新增」**

[![image-1656924854811.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/SWH7ljpOvKazuqGv-image-1656924854811.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/SWH7ljpOvKazuqGv-image-1656924854811.png)

Send to：填入上面步驟拿到的ˊTOKEN

**3.「組態」→「動作」→「創建動作」**

[![image-1656925027773.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/FRLGArWWJ8MlS9IG-image-1656925027773.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/FRLGArWWJ8MlS9IG-image-1656925027773.png)

<table border="1" cellpadding="1" cellspacing="1" id="bkmrk-%7Bhost.name1%7D%3A-%7Btrigg"><tbody><tr><td>{HOST.NAME1}: {TRIGGER.STATUS}: {TRIGGER.NAME}</td></tr></tbody></table>

<table border="1" cellpadding="1" cellspacing="1" id="bkmrk-%E4%B8%BB%E6%A9%9F%E5%90%8D%E7%A8%B1%3A-%7Bhostname1%7D%E7%99%BC%E7%94%9F%E6%99%82"><tbody><tr><td>主機名稱: {HOSTNAME1}  
發生時間: {EVENT.DATE} {EVENT.TIME}  
警示等級: {TRIGGER.SEVERITY}  
警示訊息: {TRIGGER.NAME}  
警示項目: {TRIGGER.KEY1}  
問題說明: {ITEM.NAME}: {ITEM.VALUE}  
當前狀態: {TRIGGER.STATUS}: {ITEM.VALUE1}  
事件ID: {EVENT.ID}</td></tr></tbody></table>

備註：**Recovery operations** 的欄位主旨和訊息都和這邊一樣

[![image-1656925062406.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/Rb864yoX03cXFsJe-image-1656925062406.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/Rb864yoX03cXFsJe-image-1656925062406.png)

[![image-1656925084845.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/ooN5dFnxHY2U45aD-image-1656925084845.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/ooN5dFnxHY2U45aD-image-1656925084845.png)

Recovery operations 的操作配置

[![image-1656925100227.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/ntcd5VSZGqWifrC6-image-1656925100227.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/ntcd5VSZGqWifrC6-image-1656925100227.png)

---

**配置完成後，進行測試**

將監控主機關機，五分鐘後，LINE就會進行報警

[![image-1656925113010.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/scaled-1680-/8vfTYxmODyCHQsCg-image-1656925113010.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-07/8vfTYxmODyCHQsCg-image-1656925113010.png)

出處：[﹝Linux﹞Zabbix LINE Notify 警報通知 | 工程師的江湖 - 點部落 (dotblogs.com.tw)](https://dotblogs.com.tw/xerion30476/2019/08/28/153643)

# 學習相關連結

**[《网络工程师的Python之路》教学文章、视频汇总 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/486260131)**

# smokeping install

```
timedatectl set-timezone Asia/Taipei
```

install docker

```
curl -fsSL https://get.docker.com | bash -s docker
```

run smokeping in docker

```
mkdir -p /home/monitor/smokeping/config
mkdir -p /home/monitor/smokeping/data
chown -R monitor /home/monitor/smokeping/

systemctl enable docker
systemctl start docker

docker pull linuxserver/smokeping
docker run -d \
--name=smokeping \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Asia/Taipei \
-p 9080:80 \
-v /home/monitor/smokeping/config:/config \
-v /home/monitor/smokeping/data:/data \
--restart unless-stopped \
linuxserver/smokeping
```

## fix config

<span style="font-family: tahoma, arial, helvetica, sans-serif;">路径 /home/monitor/smokeping/config/Targets</span>

```shell
#!/bin/bash
docker rm -f smokeping

docker run -d \
--name=smokeping \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Asia/Taipei \
-p 9080:80 \
-v /home/monitor/smokeping/config:/config \
-v /home/monitor/smokeping/data:/data \
--restart unless-stopped \
linuxserver/smokeping


```

<span style="font-family: tahoma, arial, helvetica, sans-serif;">page</span>

##### <span style="font-family: tahoma, arial, helvetica, sans-serif;">http://localhost:9080/smokeping/?target=InternetSites</span>

https://www.ssvip.net/971.html

# 【DNS】台灣地區常用 DNS IP 整合表

### 🇹🇼 台灣地區常用 DNS IP 整合表：

<div id="bkmrk-%E6%A5%AD%E8%80%85-%E4%B8%BB%E7%94%A8-dns-ip-%E5%82%99%E7%94%A8-%2F-%E5%8D%80%E5%9F%9F"><table data-end="1306" data-start="123"><thead data-end="220" data-start="123"><tr data-end="220" data-start="123"><th data-end="136" data-start="123">業者</th><th data-end="156" data-start="136">主用 DNS IP</th><th data-end="212" data-start="156">備用 / 區域性 DNS IP</th><th data-end="220" data-start="212">備註說明</th></tr></thead><tbody data-end="1306" data-start="334"><tr data-end="439" data-start="334"><td>**中華電信**</td><td>168.95.1.1</td><td>168.95.192.1</td><td>全台通用</td></tr><tr data-end="562" data-start="440"><td>**台灣大哥大**</td><td>203.73.24.1</td><td>203.73.25.1、61.31.233.1</td><td>固網與行動使用者常見 IP，會依區域調整</td></tr><tr data-end="735" data-start="563"><td>**遠傳電信 (SeedNet)**</td><td>139.175.1.1</td><td>139.175.55.244、8.8.8.8（Google DNS）、其他區域性如下：</td><td>官方資料來源 <a data-end="733" data-start="671" rel="noopener" target="_new">SeedNet</a></td></tr><tr data-end="850" data-start="736"><td>→ 北區</td><td>139.175.55.244</td><td>139.175.252.16</td><td>台北、桃園、新竹等</td></tr><tr data-end="965" data-start="851"><td>→ 中區</td><td>139.175.150.20</td><td>139.175.55.244</td><td>台中、彰化、南投等</td></tr><tr data-end="1080" data-start="966"><td>→ 南區</td><td>139.175.10.20</td><td>139.175.55.244</td><td>高雄、台南、嘉義等</td></tr><tr data-end="1192" data-start="1081"><td>**亞太電信**</td><td>多沿用中華電信</td><td> </td><td>建議手動指定 168.95.1.1</td></tr><tr data-end="1306" data-start="1193"><td>**台固媒體**</td><td>203.75.129.130</td><td>203.75.129.131</td><td>固定使用者常見 DNS</td></tr></tbody></table>

</div>---

### 🌐 國際公共 DNS（可自由選擇）：

<div id="bkmrk-%E6%9C%8D%E5%8B%99%E5%95%86-%E4%B8%BB%E7%94%A8-dns-ip-%E5%82%99%E7%94%A8-dns"><table data-end="1759" data-start="1338"><thead data-end="1401" data-start="1338"><tr data-end="1401" data-start="1338"><th data-end="1351" data-start="1338">服務商</th><th data-end="1367" data-start="1351">主用 DNS IP</th><th data-end="1385" data-start="1367">備用 DNS IP</th><th data-end="1401" data-start="1385">備註</th></tr></thead><tbody data-end="1759" data-start="1477"><tr data-end="1547" data-start="1477"><td>Google DNS</td><td>8.8.8.8</td><td>8.8.4.4</td><td>全球穩定快速</td></tr><tr data-end="1619" data-start="1548"><td>Cloudflare</td><td>1.1.1.1</td><td>1.0.0.1</td><td>快速且注重隱私</td></tr><tr data-end="1689" data-start="1620"><td>Quad9</td><td>9.9.9.9</td><td>149.112.112.112</td><td>防惡意網站 DNS</td></tr><tr data-end="1759" data-start="1690"><td>OpenDNS</td><td>208.67.222.222</td><td>208.67.220.220</td><td>可選擇家長過濾功能</td></tr></tbody></table>

</div>

# 【常見問題】通訊協定＆port 在呼叫上的差異

以下是針對你提到的三種不同 URL 呼叫方式：

```
1. https://a.b.com:3000
2. http://a.b.com:3000
3. http://a.b.com

```

---

## ✅ 一、三種呼叫差異總覽

<table id="bkmrk-%E5%91%BC%E5%8F%AB%E6%96%B9%E5%BC%8F-%E5%8D%94%E5%AE%9A-port-%E6%98%AF%E5%90%A6%E5%8A%A0%E5%AF%86-%E5%B0%8D-"><thead><tr><th>呼叫方式</th><th>協定</th><th>Port</th><th>是否加密</th><th>對 Nginx 的需求</th><th>常見用途</th></tr></thead><tbody><tr><td>`https://a.b.com:3000`</td><td>HTTPS</td><td>3000</td><td>✅ 是</td><td>`listen 3000 ssl;`</td><td>測試自訂 HTTPS port</td></tr><tr><td>`http://a.b.com:3000`</td><td>HTTP</td><td>3000</td><td>❌ 否</td><td>`listen 3000;`</td><td>自訂 HTTP port 開發</td></tr><tr><td>`http://a.b.com`</td><td>HTTP</td><td>80</td><td>❌ 否</td><td>`listen 80;`（預設）</td><td>一般公開網站</td></tr></tbody></table>

---

## ✅ 二、為什麼會有差異？

### 1. 協定不同（HTTP vs HTTPS）

- HTTP：明文傳輸，不需要 TLS 憑證。
- HTTPS：加密傳輸，需要 SSL 憑證，並透過 TLS 握手。

### 2. Port 不同（預設 vs 自訂）

- HTTP 預設是 80、HTTPS 預設是 443。
- 如果你指定其他 port（如 3000），伺服器端（如 Nginx）**必須額外開啟對應的 port 並配置好 listen 與憑證**。

---

## ✅ 三、Nginx 實際設定對應

### 1️⃣ 對應 `https://a.b.com:3000`

```nginx
server {
    listen 3000 ssl;
    server_name a.b.com;

    ssl_certificate     /etc/nginx/certs/a.b.com.crt;
    ssl_certificate_key /etc/nginx/certs/a.b.com.key;

    location / {
        proxy_pass http://localhost:4000;
    }
}

```

> 🔒 加密連線，必須設定 `ssl` 與有效憑證。

---

### 2️⃣ 對應 `http://a.b.com:3000`

```nginx
server {
    listen 3000;
    server_name a.b.com;

    location / {
        proxy_pass http://localhost:4000;
    }
}

```

> 🔓 明文傳輸，不需要 SSL 憑證。適用於測試環境或內網。

---

### 3️⃣ 對應 `http://a.b.com`

```nginx
server {
    listen 80;
    server_name a.b.com;

    location / {
        proxy_pass http://localhost:4000;
    }
}

```

> 🌐 最常見的網站 HTTP 配置。不需帶 port。

---

## ✅ 四、連線行為對照表

<table id="bkmrk-%E4%BD%BF%E7%94%A8%E8%80%85%E8%BC%B8%E5%85%A5%E7%B6%B2%E5%9D%80-%E7%80%8F%E8%A6%BD%E5%99%A8%E6%88%96-curl-%E7%99%BC%E5%87%BA"><thead><tr><th>使用者輸入網址</th><th>瀏覽器或 curl 發出的請求會去到哪裡？</th></tr></thead><tbody><tr><td>`https://a.b.com:3000`</td><td>`a.b.com` 的 **port 3000**（用 TLS）</td></tr><tr><td>`http://a.b.com:3000`</td><td>`a.b.com` 的 **port 3000**（無加密）</td></tr><tr><td>`http://a.b.com`</td><td>`a.b.com` 的 **port 80**</td></tr></tbody></table>

---

## ✅ 五、常見錯誤與排查

<table id="bkmrk-%E5%95%8F%E9%A1%8C-%E5%8E%9F%E5%9B%A0-%E8%A7%A3%E6%B3%95-curl-https%3A"><thead><tr><th>問題</th><th>原因</th><th>解法</th></tr></thead><tbody><tr><td>`curl https://a.b.com:3000` 報錯 TLS</td><td>你設定了 HTTPS，但 Nginx 未加上 `ssl` 或憑證有誤</td><td>加上 `ssl` 並設定憑證</td></tr><tr><td>只能用 `http://a.b.com`，其他都失敗</td><td>Nginx 只開 port 80，沒開 3000</td><td>增加對應 `listen 3000` 的設定</td></tr><tr><td>呼叫 `http://a.b.com:3000` 被拒絕</td><td>Server 未開啟該 port</td><td>檢查防火牆、Nginx、Docker 映射是否有允許 3000</td></tr></tbody></table>

---

## ✅ 六、總結：選擇哪一種？

<table id="bkmrk-%E4%BD%BF%E7%94%A8%E5%A0%B4%E6%99%AF-%E5%BB%BA%E8%AD%B0%E5%91%BC%E5%8F%AB%E6%96%B9%E5%BC%8F-%E5%85%A7%E9%83%A8%E9%96%8B%E7%99%BC%E6%B8%AC%E8%A9%A6-h"><thead><tr><th>使用場景</th><th>建議呼叫方式</th></tr></thead><tbody><tr><td>內部開發測試</td><td>`http://a.b.com:3000` 或 `https://a.b.com:3000`</td></tr><tr><td>正式站公開服務</td><td>`https://a.b.com`（預設 port 443）</td></tr><tr><td>Nginx 反向代理串接後端</td><td>視你要轉發的是 HTTP or HTTPS 及 port 而定</td></tr></tbody></table>

---

如你需要一份完整支援三種 port 的 `nginx.conf` 以及搭配 Express 的後端範例，我可以幫你整合好。需要嗎？

# 【常見問題】https 使用domain 與 ip 差異

好的，以下補上：

---

## ✅ 比較 `https://a.b.com` 與 `https://168.23.1.1` 的差異

這兩者**協定一樣**（都是 HTTPS），但**主機名稱（Host）差異會影響 SSL 憑證驗證、DNS 解析、與 Nginx 的設定行為**。

---

##  差異對照表

<table id="bkmrk-%E9%A0%85%E7%9B%AE-https%3A%2F%2Fa.b.com-h"><thead><tr><th>項目</th><th>`https://a.b.com`</th><th>`https://168.23.1.1`</th></tr></thead><tbody><tr><td>**協定**</td><td>HTTPS（加密）</td><td>HTTPS（加密）</td></tr><tr><td>**主機名稱**</td><td>網域名稱（FQDN）</td><td>IP 位址</td></tr><tr><td>**DNS 解析**</td><td>會經過 DNS 解析 → IP</td><td>不經 DNS</td></tr><tr><td>**SSL 憑證驗證**</td><td>通常需要**憑證中的 CN/SAN 包含 a.b.com**</td><td>需要**憑證中包含 IP 位址**（不常見）</td></tr><tr><td>**Nginx `server_name`** 配置</td><td>`server_name a.b.com;`</td><td>`server_name 168.23.1.1;`（不建議）或 `_`</td></tr><tr><td>**常見用法**</td><td>公網、正式站、內部網域皆可</td><td>測試、開發、內網 IP 使用</td></tr><tr><td>**風險與限制**</td><td>SSL 憑證驗證容易通過</td><td>一般憑證不支援 IP → 會出現 TLS 錯誤</td></tr><tr><td>**信任憑證**</td><td>可用 Let's Encrypt、商業憑證</td><td>除非特別申請 IP 憑證，否則會有警告</td></tr></tbody></table>

---

##  SSL 憑證驗證差異舉例

### `https://a.b.com`

- 若你使用 Let's Encrypt 為 `a.b.com` 建立憑證：  
    ✅ `curl https://a.b.com` ➜ 成功（CN/SAN 包含 `a.b.com`）

### `https://168.23.1.1`

- 若你拿 `a.b.com` 憑證套用到 IP 上：  
    ❌ `curl https://168.23.1.1` ➜ 失敗，出現 `SSL: certificate subject name does not match`

###  解法（不建議用於正式環境）：

- 為 IP 簽發 SSL 憑證（需自簽或企業憑證）
- 用 `curl -k` 忽略憑證錯誤

```bash
curl -k https://168.23.1.1  # 跳過憑證驗證（不安全）

```

---

## ✅ Nginx 設定差異

### `a.b.com` 對應設定：

```nginx
server {
    listen 443 ssl;
    server_name a.b.com;

    ssl_certificate     /etc/nginx/certs/a.b.com.crt;
    ssl_certificate_key /etc/nginx/certs/a.b.com.key;

    location / {
        proxy_pass http://localhost:3000;
    }
}

```

---

### IP 直接連線時，通常會用：

```nginx
server {
    listen 443 ssl;
    server_name _;  # 匹配所有 hostname（或不設定）

    ssl_certificate     /etc/nginx/certs/selfsigned.crt;
    ssl_certificate_key /etc/nginx/certs/selfsigned.key;

    location / {
        proxy_pass http://localhost:3000;
    }
}

```

> 🧨 若直接用 IP，也許不會觸發 `server_name` 對應，取決於 Nginx 設定順序與 SNI。

---

## ✅ 小結

<table id="bkmrk-url-%E9%81%A9%E7%94%A8%E6%99%82%E6%A9%9F-%E6%86%91%E8%AD%89%E9%9C%80%E6%B1%82-%E9%A2%A8%E9%9A%AA-htt"><thead><tr><th>URL</th><th>適用時機</th><th>憑證需求</th><th>風險</th></tr></thead><tbody><tr><td>`https://a.b.com`</td><td>公網、正常使用</td><td>CN/SAN 需含 `a.b.com`</td><td>正常通過憑證驗證</td></tr><tr><td>`https://168.23.1.1`</td><td>內部測試或特例</td><td>憑證需含 IP 或自簽</td><td>容易驗證失敗、跳警告</td></tr></tbody></table>

---

##  

## ✅Curl Domain 與 ip 的 差異

這是一個非常關鍵的細節問題，涉及到 **HTTPS、Host Header、SNI（Server Name Indication）**，我們來完整拆解：

---

## 你提供的兩個請求：

```bash
curl https://a.b.com

```

```bash
curl https://168.23.1.1 -H 'Host: a.b.com'

```

看起來類似，實際上在底層**行為非常不同**：

---

##  核心差異一覽

<table id="bkmrk-%E9%A0%85%E7%9B%AE-curl-https%3A%2F%2Fa.b."><thead><tr><th>項目</th><th>`curl https://a.b.com`</th><th>`curl https://168.23.1.1 -H 'Host: a.b.com'`</th></tr></thead><tbody><tr><td>**連線 IP**</td><td>DNS 解析 `a.b.com` → IP</td><td>直接指定 IP `168.23.1.1`</td></tr><tr><td>**TLS SNI 傳送內容**</td><td>`a.b.com`（🔑 用來選擇憑證）</td><td>`168.23.1.1`（🚨 TLS 層不包含 `a.b.com`）</td></tr><tr><td>**Host Header（HTTP 層）**</td><td>`Host: a.b.com`（由 curl 自動加）</td><td>`Host: a.b.com`（你手動加）</td></tr><tr><td>**SSL 憑證是否驗證成功？**</td><td>✅ 通常會成功</td><td>❌ 若憑證是發給 `a.b.com` 則會 mismatch</td></tr><tr><td>**Nginx 是否能進到正確的 server**</td><td>✅ 通常會進到 `server_name a.b.com`</td><td>❌ 取決於 SNI，可能進入 default server</td></tr></tbody></table>

---

##  為何 TLS 憑證驗證會失敗？

###  SNI 是什麼？

- TLS 層在握手階段會送出 `Server Name`（來自 `curl` 的 `--resolve` 或 URL）。
- 用來讓伺服器知道要回哪一張憑證。

### 在兩種情況下比較：

#### ✅ `curl https://a.b.com`：

- DNS → 168.23.1.1
- SNI: `a.b.com`
- Host header: `a.b.com`
- Nginx 匹配成功，憑證也是給 `a.b.com`，一切正常

#### ❌ `curl https://168.23.1.1 -H 'Host: a.b.com'`：

- SNI: `168.23.1.1`（預設值，非 a.b.com）
- Host header: `a.b.com`（只有 HTTP 層有用）
- 若 Nginx 用 `server_name a.b.com` 並綁定憑證，那會 **因為 SNI 不符無法選中正確的憑證 → TLS 握手失敗**

---

## Nginx 對這兩種請求的反應

```nginx
server {
    listen 443 ssl;
    server_name a.b.com;

    ssl_certificate     /etc/nginx/certs/a.b.com.crt;
    ssl_certificate_key /etc/nginx/certs/a.b.com.key;

    location / {
        return 200 "hello a.b.com\n";
    }
}

server {
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/certs/default.crt;
    ssl_certificate_key /etc/nginx/certs/default.key;

    location / {
        return 200 "default server\n";
    }
}

```

### 測試結果：

<table id="bkmrk-%E6%B8%AC%E8%A9%A6%E6%8C%87%E4%BB%A4-%E4%BC%BA%E6%9C%8D%E5%99%A8-block-%E5%91%BD%E4%B8%AD-%E5%9B%9E%E5%82%B3"><thead><tr><th>測試指令</th><th>伺服器 block 命中</th><th>回傳內容</th><th>是否 SSL 通過</th></tr></thead><tbody><tr><td>`curl https://a.b.com`</td><td>`server_name a.b.com`</td><td>hello a.b.com</td><td>✅ 是</td></tr><tr><td>`curl https://168.23.1.1 -H 'Host: a.b.com'`</td><td>`server_name _`（default）</td><td>default server</td><td>⚠️ 通常憑證不符（或需 `-k`）</td></tr></tbody></table>

---

## ✅ 解法：讓 IP 請求也能通過 SSL

### 方法一：用自簽或專門支援 IP 的憑證

但大多數公開 CA（如 Let's Encrypt）**不發給 IP 憑證**。

### 方法二：用 curl 忽略 TLS 驗證

```bash
curl -k https://168.23.1.1 -H 'Host: a.b.com'

```

### 方法三：讓 curl 傳送正確的 SNI（推薦）

```bash
curl --resolve a.b.com:443:168.23.1.1 https://a.b.com

```

- 這會讓 curl：
    
    
    - SNI 傳 `a.b.com`
    - Host header 是 `a.b.com`
    - 實際連到 IP `168.23.1.1`
- ✅ 完整模擬瀏覽器行為

---

## ✅ 總結

<table id="bkmrk-%E6%AF%94%E8%BC%83%E9%A0%85%E7%9B%AE-curl-https%3A%2F%2Fa."><thead><tr><th>比較項目</th><th>`curl https://a.b.com`</th><th>`curl https://168.23.1.1 -H 'Host: a.b.com'`</th></tr></thead><tbody><tr><td>DNS 解析</td><td>✅ 有</td><td>❌ 無</td></tr><tr><td>TLS SNI</td><td>`a.b.com`</td><td>`168.23.1.1`</td></tr><tr><td>Host Header</td><td>`a.b.com`</td><td>`a.b.com`</td></tr><tr><td>SSL 憑證驗證</td><td>✅ 通常成功</td><td>❌ 會失敗（除非用 `-k`）</td></tr><tr><td>建議用法</td><td>✅ 正常連線方式</td><td>⚠️ 用於測試或模擬</td></tr></tbody></table>

---

如果你需要模擬真實請求又繞過 DNS，可使用：

```bash
curl --resolve a.b.com:443:168.23.1.1 https://a.b.com

```

這是最穩定且最貼近瀏覽器 SNI 行為的方式。

# 【PowerDNS】

Lua records

[https://doc.powerdns.com/authoritative/lua-records/index.html](https://doc.powerdns.com/authoritative/lua-records/index.html)

```
-- 返回请求方 IP
who:toString()

-- 根据请求方 IP 不同返回不同地址
view({
  {{'10.10.0.0/16'}, {'10.10.1.1'}}
  {{'0.0.0.0/0'}, {'192.0.2.1'}}
})

-- 返回存活的 IP
-- 异步检测 - 如果都不存活则都返回
ifportup(443, {'192.0.2.1', '192.0.2.2'})
-- 使用 URL 检测存活 - stringmatch 为可选的内容匹配条件
ifurlup("example.com/status", { {"192.0.2.20", "203.0.113.4"}, {"203.0.113.2"} },{stringmatch='ok'})

-- 基于请求方的 HASH(bestwho) 进行返回
pickwhashed({{10,'192.168.0.1'},{100,'192.168.0.2'}})
-- 随机返回 - 有带权重版
pickrandom({{'192.168.0.1'},{'192.168.0.2'}})
pickwrandom({{10,'192.168.0.1'},{100,'192.168.0.2'}})
```

### **`pdnsutil`**

下面是 **`pdnsutil`**（PowerDNS 的指令工具，用於 DNS 區域與 DNSSEC 管理）的一份常用語法與操作範例教學。你可以把它當作 cheat-sheet 或操作對照表。  
（若你的 PowerDNS 版本略有不同或後續改版，部分語法可能略有出入，建議搭配 `man pdnsutil` 或官方文檔確認） ([doc.powerdns.com](https://doc.powerdns.com/authoritative/manpages/pdnsutil.1.html?utm_source=chatgpt.com "pdnsutil — PowerDNS Authoritative Server documentation"))

---

## 基本語法結構與通用選項

```
pdnsutil [OPTIONS] COMMAND [ARGUMENTS...]

```

常見的選項：

<table id="bkmrk-%E9%81%B8%E9%A0%85-%E8%AA%AA%E6%98%8E--h%2C---help-%E9%A1%AF%E7%A4%BA%E5%8D%94"><thead><tr><th>選項</th><th>說明</th></tr></thead><tbody><tr><td>`-h, --help`</td><td>顯示協助訊息</td></tr><tr><td>`-v, --verbose`</td><td>輸出較詳細訊息</td></tr><tr><td>`--force`</td><td>強制執行（覆寫、跳過某些檢查等）</td></tr><tr><td>`--config-name <NAME>`</td><td>指定虛擬設定名稱</td></tr><tr><td>`--config-dir <DIR>`</td><td>指定 pdns.conf 所在目錄（預設 `/etc/powerdns`）</td></tr></tbody></table>

---

## 常見區域 (zone) 管理指令

以下指令幾乎涵蓋新增、查看、編輯、刪除、檢查等需求。

<table id="bkmrk-%E5%8A%9F%E8%83%BD-%E6%8C%87%E4%BB%A4%E7%AF%84%E4%BE%8B-%E8%AA%AA%E6%98%8E-%2F-%E5%82%99%E8%A8%BB-%E5%BB%BA%E7%AB%8B%E5%8D%80%E5%9F%9F"><thead><tr><th>功能</th><th>指令範例</th><th>說明 / 備註</th></tr></thead><tbody><tr><td>建立區域</td><td>`pdnsutil create-zone example.com`</td><td>建立一個空的 zone `example.com`，內部會自動加入一条 NS 記錄 ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>刪除區域</td><td>`pdnsutil delete-zone example.com`</td><td>將該 zone 從後端資料庫中移除</td></tr><tr><td>顯示區域內容</td><td>`pdnsutil show-zone example.com`</td><td>列出 zone 的所有 resource record 和 meta 資訊 ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>列出區域</td><td>`pdnsutil list-zone example.com`</td><td>列出該區域的所有資料記錄 ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>列出所有區域</td><td>`pdnsutil list-all-zones`</td><td>顯示所有已註冊的 zone 名稱 ([Debian Manpages](https://manpages.debian.org/testing/pdns-server/pdnsutil.1.en.html?utm_source=chatgpt.com "pdnsutil(1) — pdns-server — Debian testing"))</td></tr><tr><td>檢查單個區域</td><td>`pdnsutil check-zone example.com`</td><td>檢查該 zone 是否有錯誤（語法、衝突等） ([cPanel Support](https://support.cpanel.net/hc/en-us/articles/360058804574-How-to-use-PowerDNS-tools-to-find-zone-errors?utm_source=chatgpt.com "How to use PowerDNS tools to find zone errors – cPanel"))</td></tr><tr><td>檢查所有區域</td><td>`pdnsutil check-all-zones`</td><td>對所有 zones 執行檢查 ([CloudWizard.nl](https://www.cloudwizard.nl/powerdns-part-3-create-zone-ubuntu/?utm_source=chatgpt.com "PowerDNS Part 3 - Create zone (Ubuntu) - CloudWizard.nl"))</td></tr><tr><td>編輯區域（交互式）</td><td>`pdnsutil edit-zone example.com`</td><td>進入文字編輯介面，可以手動修改 zone 的所有記錄（系統會做基本檢查） ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>增加記錄</td><td>`pdnsutil add-record example.com sub A 3600 1.2.3.4`</td><td>在 `example.com` 區域新增一條 A 紀錄： `sub.example.com` TTL 3600 指向 1.2.3.4 ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>更新（替換）整組記錄</td><td>`pdnsutil replace-rrset example.com sub A 3600 5.6.7.8`</td><td>將 sub 的 A 類型記錄整組替換為新的值（如果有多條） ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr><tr><td>刪除一組記錄</td><td>`pdnsutil delete-rrset example.com sub A`</td><td>刪除 sub 的所有 A 類型記錄（整個 RRset） ([HackMD](https://hackmd.io/%40haquenafeem/Sy20t2W6d?utm_source=chatgpt.com "PowerDNS R&D"))</td></tr><tr><td>增加序號</td><td>`pdnsutil increase-serial example.com`</td><td>手動把 SOA 的 Serial 加一（通常在變更後需告知 slave） ([CloudWizard.nl](https://www.cloudwizard.nl/powerdns-part-3-create-zone-ubuntu/?utm_source=chatgpt.com "PowerDNS Part 3 - Create zone (Ubuntu) - CloudWizard.nl"))</td></tr><tr><td>設定 zone 類型</td><td>`pdnsutil set-kind example.com MASTER`</td><td>設定該 zone 為主(zone master)、從(zone slave)或其他類型 ([CloudWizard.nl](https://www.cloudwizard.nl/powerdns-part-3-create-zone-ubuntu/?utm_source=chatgpt.com "PowerDNS Part 3 - Create zone (Ubuntu) - CloudWizard.nl"))</td></tr><tr><td>設定 meta (zone metadata)</td><td>`pdnsutil set-meta example.com ALLOW-AXFR-FROM AUTO-NS`</td><td>為該 zone 加上 metadata，例如允許哪些 IP 做 AXFR 等 ([blog.powerdns.com](https://blog.powerdns.com/2016/02/02/powerdns-authoritative-the-new-old-way-to-manage-domains?utm_source=chatgpt.com "PowerDNS Authoritative: the new old way to manage domains"))</td></tr></tbody></table>

---

## DNSSEC / 金鑰 (key) 管理指令

如果你要為 zone 啟用 DNSSEC、管理金鑰或做 key rollover 等，這些指令就會派上用場。 ([doc.powerdns.com](https://doc.powerdns.com/authoritative/dnssec/pdnsutil.html?utm_source=chatgpt.com "pdnsutil and DNSSEC - PowerDNS Documentation"))

<table id="bkmrk-%E5%8A%9F%E8%83%BD-%E6%8C%87%E4%BB%A4%E7%AF%84%E4%BE%8B-%E8%AA%AA%E6%98%8E-%2F-%E5%82%99%E8%A8%BB-%E5%95%9F%E7%94%A8-d"><thead><tr><th>功能</th><th>指令範例</th><th>說明 / 備註</th></tr></thead><tbody><tr><td>啟用 DNSSEC（簽名 zone）</td><td>`pdnsutil secure-zone example.com`</td><td>為該 zone 建立金鑰並簽名（預設配置） ([doc.powerdns.com](https://doc.powerdns.com/authoritative/dnssec/pdnsutil.html?utm_source=chatgpt.com "pdnsutil and DNSSEC - PowerDNS Documentation"))</td></tr><tr><td>列出該 zone 的金鑰</td><td>`pdnsutil list-keys example.com`</td><td>顯示該 zone 所有的 KSK / ZSK 金鑰資訊 ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>新增金鑰</td><td>`pdnsutil add-zone-key example.com ZSK active 2048 rsasha256`</td><td>為例：在 zone `example.com` 新增一組 ZSK 金鑰，256 RSA, 2048 位元長度。可調整參數。 ([Debian Manpages](https://manpages.debian.org/testing/pdns-server/pdnsutil.1.en.html?utm_source=chatgpt.com "pdnsutil(1) — pdns-server — Debian testing"))</td></tr><tr><td>啟用金鑰</td><td>`pdnsutil activate-zone-key example.com 12345`</td><td>啟用某一個金鑰（以其 key-id 為識別） ([Debian Manpages](https://manpages.debian.org/testing/pdns-server/pdnsutil.1.en.html?utm_source=chatgpt.com "pdnsutil(1) — pdns-server — Debian testing"))</td></tr><tr><td>停用金鑰</td><td>`pdnsutil deactivate-zone-key example.com 12345`</td><td>停用該金鑰（使其不再用於簽名） ([Debian Manpages](https://manpages.debian.org/testing/pdns-server/pdnsutil.1.en.html?utm_source=chatgpt.com "pdnsutil(1) — pdns-server — Debian testing"))</td></tr><tr><td>匯出公鑰與 DS 記錄</td><td>`pdnsutil export-zone-ds example.com`</td><td>匯出該 zone 所有 KSK 的 DS 記錄（可提交給上層域名註冊商） ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>匯出金鑰</td><td>`pdnsutil export-zone-key example.com 12345`</td><td>匯出該 zone 指定金鑰（含私鑰）到檔案或標準輸出 ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>移除金鑰</td><td>`pdnsutil remove-zone-key example.com 12345`</td><td>將指定金鑰從 zone 中移除（不再保留） ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>停用 DNSSEC（取消簽名）</td><td>`pdnsutil disable-dnssec example.com`</td><td>將 zone 還原為不使用 DNSSEC 狀態 ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>修正 (rectify) zone 資料庫</td><td>`pdnsutil rectify-zone example.com`</td><td>重建 zone 在資料庫中的 internal 欄位（如 auth / ordername） ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr><tr><td>修正所有 zone</td><td>`pdnsutil rectify-all-zones`</td><td>對所有已存在的 zone 執行 rectify 操作 ([SIDN - Het bedrijf achter .nl](https://www.sidn.nl/en/modern-internet-standards/dnssec-on-the-powerdns-authoritative-server?utm_source=chatgpt.com "DNSSEC on the PowerDNS Authoritative Server - SIDN"))</td></tr></tbody></table>

---

## 一些操作流程範例

以下是比較常見的操作流程，依步驟示範怎麼做：

### 範例：建立一個新的 zone 並設定記錄 + 啟用 DNSSEC

假設 domain 為 `example.com`：

```bash
pdnsutil create-zone example.com
pdnsutil set-kind example.com MASTER
pdnsutil add-record example.com @ NS ns1.example.com.
pdnsutil add-record example.com @ NS ns2.example.com.
pdnsutil add-record example.com ns1 A 1.2.3.4
pdnsutil add-record example.com ns2 A 5.6.7.8
pdnsutil replace-rrset example.com . SOA 'ns1.example.com. hostmaster.example.com. 1 10800 3600 604800 3600'
pdnsutil secure-zone example.com
pdnsutil increase-serial example.com
pdns_control notify example.com

```

這樣做完後，你可以用 `pdnsutil show-zone example.com` 檢查結果。 ([CloudWizard.nl](https://www.cloudwizard.nl/powerdns-part-3-create-zone-ubuntu/?utm_source=chatgpt.com "PowerDNS Part 3 - Create zone (Ubuntu) - CloudWizard.nl"))

### 範例：修改已有記錄

假設要把 `www.example.com` 的 A 紀錄從 `1.2.3.4` 換成 `5.5.5.5`：

```bash
pdnsutil replace-rrset example.com www A 3600 5.5.5.5
pdnsutil increase-serial example.com
pdns_control notify example.com

```

或若要直接刪除 `www` 的 A 紀錄：

```bash
pdnsutil delete-rrset example.com www A
pdnsutil increase-serial example.com
pdns_control notify example.com

```

最後別忘了通知 slave 或其他 server 更新：`pdns_control notify example.com`。

---

## 注意事項與建議

1. **後端限制**  
    某些後端 (特別是 BIND 後端) 可能不支援修改操作（只能透過 zone transfer）或不支援 `pdnsutil` 操作。要確認你使用的後端是否允許這些操作。 ([Reddit](https://www.reddit.com/r/dns/comments/ju57uf/powerdns_cannot_add_records_with_pdnsutil/?utm_source=chatgpt.com "PowerDNS: cannot add records with pdnsutil : r/dns - Reddit"))
2. **版本差異**  
    不同 PowerDNS 版本對於 DNSSEC 的預設邏輯、支援的演算法、金鑰長度限制等可能不同。建議查看你系統上 `man pdnsutil` 或官方版本對照表。 ([Debian Manpages](https://manpages.debian.org/testing/pdns-server/pdnsutil.1.en.html?utm_source=chatgpt.com "pdnsutil(1) — pdns-server — Debian testing"))
3. **序號 (Serial) 管理**  
    在變更 zone 後，務必更新 SOA 的 serial（可用 `increase-serial` 或手動編輯 SOA）並通知 slave。否則 slave 可能不會接收到變更。
4. **測試 / 錯誤檢查**  
    使用 `check-zone` / `check-all-zones` 來檢查語法或邏輯錯誤，以免上線後 DNS 無法解析。 ([cPanel Support](https://support.cpanel.net/hc/en-us/articles/360058804574-How-to-use-PowerDNS-tools-to-find-zone-errors?utm_source=chatgpt.com "How to use PowerDNS tools to find zone errors – cPanel"))
5. **備份與金鑰匯出**  
    在做 DNSSEC 金鑰 rollover 或改動前，建議匯出金鑰備份（`export-zone-key`）及對 DS 記錄操作要小心，避免中斷解析鏈。

---

## 🧩 一、PowerDNS 查詢流程（簡化版）

當你執行：

```bash
dig app-wekan.momoshop.com.tw

```

時，PDNS 的查詢處理順序如下：

1. **找 zone（domains 表）**
    
    
    - 從 `domains.name` 開始，找最匹配的 zone（例如 `momoshop.com.tw`）。
2. **在 records 表中找符合的 name**
    
    
    - 順序為：
        
        
        - 精確比對 `name='app-wekan.momoshop.com.tw'`
        - 如果找不到，則依序比對：
            
            
            - `*.momoshop.com.tw`
            - `*.com.tw`
            - `*.tw`
    - 每一層可能都會回傳多筆記錄。
3. **根據 type 過濾**
    
    
    - 只會選出符合查詢類型（例如 A）或可解譯的 LUA record。
4. **若有 LUA 記錄，執行 Lua 腳本**
    
    
    - 若多筆 LUA record，PDNS 會依「**資料庫記錄順序（id 由小到大）**」逐筆執行；
    - 直到第一筆成功產生合法的回應為止。
5. **若多筆普通記錄（A, CNAME）**
    
    
    - 會**全部回傳**；
    - 若 TTL 不同，取最小 TTL 為最終 TTL。
6. **若無任何匹配**
    
    
    - 回覆 `NXDOMAIN` 或 `SERVFAIL`（視 zone 與設定而定）。

---

## 🧠 二、LUA Record 的詳細執行順序

當 PDNS 找到多筆 `type='LUA'` 的記錄時：

<table id="bkmrk-%E9%A0%86%E5%BA%8F-%E8%A1%8C%E7%82%BA-1%EF%B8%8F%E2%83%A3-%E6%8C%89%E7%85%A7-id-%E7%94%B1%E5%B0%8F%E5%88%B0%E5%A4%A7"><thead><tr><th>順序</th><th>行為</th></tr></thead><tbody><tr><td>1️⃣</td><td>按照 `id` 由小到大排序</td></tr><tr><td>2️⃣</td><td>依序執行每筆 LUA 程式</td></tr><tr><td>3️⃣</td><td>第一個「有成功回傳記錄」的 LUA 結果會被採用</td></tr><tr><td>4️⃣</td><td>若 LUA 執行失敗（語法錯誤或回傳空值） → 嘗試下一筆</td></tr><tr><td>5️⃣</td><td>全部失敗 → 回 `SERVFAIL`</td></tr></tbody></table>

### ✅ 範例：

假設你有：

```sql
id | name               | type | content
---+--------------------+------+------------------------------------------
 1 | *.momoshop.com.tw  | LUA  | return getdns("10.2.1.11", qname, qtype)
 2 | *.momoshop.com.tw  | LUA  | return getdns("8.8.8.8", qname, qtype)

```

查詢 `app.momoshop.com.tw` 時：

- PDNS 會先執行第 1 筆（id=1），  
    如果 10.2.1.11 無法回應或錯誤 → 自動執行第 2 筆（id=2）。
- 若第 1 筆成功，第二筆不會被執行。

👉 因此你可以用多筆 LUA record 來實作「多層 fallback」。

---

## ⚙️ 三、普通記錄（非 LUA）的多筆處理邏輯

若同一個 name 有多筆非 LUA 記錄（例如多個 A 記錄）：

<table id="bkmrk-%E8%A8%98%E9%8C%84-ttl-ip-app.momosh"><thead><tr><th>記錄</th><th>TTL</th><th>IP</th></tr></thead><tbody><tr><td>app.momoshop.com.tw</td><td>60</td><td>10.2.1.11</td></tr><tr><td>app.momoshop.com.tw</td><td>120</td><td>10.2.1.12</td></tr></tbody></table>

PDNS 會：

- 同時回傳兩筆；
- 最終 TTL = min(60, 120) = 60。

回覆結果：

```
app.momoshop.com.tw. 60 IN A 10.2.1.11
app.momoshop.com.tw. 60 IN A 10.2.1.12

```

---

## 🔍 四、查詢過程中，實際的比對順序（Wildcard / LUA 混合時）

PowerDNS 在有通配符與 LUA 混用的情況下，查詢順序如下：

<table id="bkmrk-%E5%84%AA%E5%85%88%E9%A0%86%E5%BA%8F-%E6%AF%94%E5%B0%8D%E5%9E%8B%E6%85%8B-%E6%98%AF%E5%90%A6%E5%9F%B7%E8%A1%8C-lua-1"><thead><tr><th>優先順序</th><th>比對型態</th><th>是否執行 LUA</th></tr></thead><tbody><tr><td>1️⃣</td><td>精確比對（如 `app.momoshop.com.tw`）</td><td>是（若 type=LUA）</td></tr><tr><td>2️⃣</td><td>wildcard 比對（如 `*.momoshop.com.tw`）</td><td>是（若 type=LUA）</td></tr><tr><td>3️⃣</td><td>更高層 wildcard（如 `*.com.tw`）</td><td>是（若 type=LUA）</td></tr><tr><td>4️⃣</td><td>zone SOA / NS</td><td>否</td></tr><tr><td>5️⃣</td><td>沒有符合 → `NXDOMAIN` 或 `SERVFAIL`</td><td> </td></tr></tbody></table>

---

## 🧩 五、如何查看 PowerDNS 真實回應順序

你可以用：

```bash
pdnsutil list-zone momoshop.com.tw

```

觀察記錄順序。  
PowerDNS 的執行順序就是按照這個清單的排列（id遞增）。

若你要控制順序，可以直接修改 id 或刪除後重新新增。

---

## 🧪 六、測試方式建議

建立多筆 LUA fallback：

```sql
INSERT INTO records (domain_id, name, type, content, ttl)
VALUES
  (3, '*.momoshop.com.tw', 'LUA', 'return getdns("10.2.1.11", qname, qtype)', 60),
  (3, '*.momoshop.com.tw', 'LUA', 'return getdns("8.8.8.8", qname, qtype)', 60);

```

測試：

```bash
journalctl -u pdns -f &
dig @127.0.0.1 -p 5501 app.momoshop.com.tw

```

你會看到：

```
Executing LUA record id=1: getdns(10.2.1.11)
Failed: timeout
Executing LUA record id=2: getdns(8.8.8.8)
Success → returning result

```

---

## 🔚 結論摘要

<table id="bkmrk-%E9%A1%9E%E5%9E%8B-%E8%A1%8C%E7%82%BA-%E5%9B%9E%E6%87%89%E6%96%B9%E5%BC%8F-%E5%A4%9A%E7%AD%86-a-%E8%A8%98%E9%8C%84-%E5%85%A8"><thead><tr><th>類型</th><th>行為</th><th>回應方式</th></tr></thead><tbody><tr><td>多筆 A 記錄</td><td>全部回傳</td><td>TTL 取最小</td></tr><tr><td>多筆 LUA 記錄</td><td>依 ID 順序執行</td><td>第一筆成功即返回</td></tr><tr><td>通配符 vs 精確匹配</td><td>精確優先於通配符</td><td> </td></tr><tr><td>LUA 與非 LUA 混用</td><td>LUA 先執行</td><td>若 LUA 無結果再回傳靜態記錄</td></tr></tbody></table>

---

是否要我幫你畫一張「PowerDNS 回應決策順序」的流程圖（含 fallback 流程）？  
會清楚標出「多筆 LUA record 執行順序 → fallback 判斷 → 最終回應」。

# 【PowerDNS】Lua Records

這是一份 PowerDNS 官方文件的完整中文翻譯。  
它說明了 **LUA Record（Lua 動態記錄）** 的用途、語法、應用範例、進階用法與安全注意事項。  
我保留了原文段落結構與技術名詞，方便你比對。

---

# 🧩 PowerDNS — Lua Records 中文說明文件

## 一、概述

為了提供動態行為（例如全球負載平衡 Global Server Load Balancing），  
PowerDNS Authoritative Server 自 **4.2 版起** 支援 **動態 DNS 記錄（LUA Records）**。

這些記錄中包含了小段設定程式（Lua 程式碼），  
可根據「查詢者 IP」、「EDNS Client Subnet」、「伺服器可用性」等因素，  
動態決定要回應哪個 IP 或 CNAME。

功能範圍從簡單到複雜，  
可實現多池（multi-pool）地理與權重負載平衡（Geo &amp; Weighted Load Balancing）。

雖然使用者不必了解內部原理，  
但 PowerDNS 的動態記錄本質上是 **嵌入在 DNS 內的小型 Lua 腳本**。

> 💡 注意：  
> 這是 **PowerDNS 專屬功能**，目前尚未成為 IETF 或其他標準機構的標準。  
> PowerDNS 官方承諾會致力於互通性，並希望最終能成為被廣泛支持的標準。

要啟用此功能，可在設定檔中加入：

```
enable-lua-records=yes

```

或對單一 zone 設定 metadata：

```
ENABLE-LUA-RECORDS=1

```

若要使用地理位置功能，請確認 `launch` 設定中包含：

```
launch=gpgsql,geoip

```

> ⚠️ 警告：  
> 使用 AXFR 傳輸包含長 Lua 記錄的 zone 時，請確保每筆記錄內容（TXT 型態傳輸）  
> 不超過 255 bytes。超過時會被分割成多段，導致次伺服器解析錯誤。

---

## 二、範例說明

### 1️⃣ ifportup()

```dns
www IN LUA A "ifportup(443, {'192.0.2.1', '192.0.2.2'})"

```

這會讓 `www` 這個名稱隨機回應 `192.0.2.1` 或 `192.0.2.2`，  
前提是這些 IP 的 **TCP 443 port 是開放的**。

若其中一個 IP 不再回應 443，則僅回傳另一個。  
若全部都不通，則全部地址會被回傳。

多組 IP 可分優先層級，例如：

```dns
www IN LUA A "ifportup(443, {{'192.0.2.1', '192.0.2.2'}, {'192.0.3.1'}})"

```

這表示：

- 若第一組中的任一 IP 可用 → 回第一組；
- 否則 → 試第二組。

因為 DNS 查詢要求極快回應，PowerDNS 不會即時檢查連線狀態，  
而是由背景程序定期檢測這些 IP 是否可用。

---

### 2️⃣ pickclosest()

```dns
www IN LUA A "pickclosest({'192.0.2.1','192.0.2.2','198.51.100.1'})"

```

這會根據查詢者的地理位置（GeoIP），  
選擇最靠近使用者的 IP 回覆。

也可以與 `ifportup()` 結合：

```dns
www IN LUA A ("ifportup(443, {'192.0.2.1', '192.0.2.2', '198.51.100.1'}, {selector='pickclosest'})")

```

這會在可用的 IP 中挑出距離使用者最近的一個。

---

### 3️⃣ 複雜 Lua 程式碼範例

```dns
www IN LUA A ";if country('US') then return {'192.0.2.1','192.0.2.2','198.51.100.1'} else return '192.0.2.2' end"

```

> 可同時回傳單一字串或多筆字串（array）。

---

### 4️⃣ 使用 qname 的例子

```dns
*.example.net 10 IN LUA TXT "; return 'Got a TXT query for ' .. qname:toString() .. '; First label is: ' .. qname:getRawLabels()[1]"

```

> 注意：`qtype` 無法從 Lua 內直接取得（它是固定的）。  
> 可使用預設變數（Preset Variables）取得其他查詢相關資訊。

---

## 三、在 SQL 後端使用 Lua Records

LUA Records 可與一般的 gmysql / gpgsql 通用 SQL 後端一起使用。

由於內容同時包含單引號與雙引號，  
在 `INSERT` 或 `UPDATE` 時需特別轉義。

範例如下：

```sql
-- 建立 zone
INSERT INTO domains (id, name, type) VALUES (1, 'example.com', 'NATIVE');

-- 啟用 Lua 記錄功能
INSERT INTO domainmetadata (domain_id, kind, content)
VALUES (1, 'ENABLE-LUA-RECORDS', 1);

-- 建立 pickclosest() 記錄
INSERT INTO records (domain_id, name, type, content, ttl)
VALUES (
  1,
  'www.example.com',
  'LUA',
  'A "pickclosest({''192.0.2.1'',''192.0.2.2'',''198.51.100.1''})"',
  600
);

```

這三筆 SQL：

- 建立 `example.com` zone，
- 啟用 Lua Records，
- 新增一筆 `www.example.com` 的動態 A 記錄。

---

## 四、LUA Record 格式

> 💡 名稱由來：  
> “Lua” 在葡萄牙文中意為「月亮」，**不是縮寫**。  
> 但 DNS 慣例記錄類型一律大寫，因此用 `LUA`。

一筆 LUA Record 結構如下：

```
LUA <query_type> <Lua 程式>

```

例如：

```dns
www IN LUA A "pickclosest({'1.1.1.1','8.8.8.8'})"

```

- 可設定 TTL，PowerDNS 會照常套用；
- 可被 DNSSEC 簽章（需在同一伺服器即時簽署）。

---

## 五、更強大的範例

```dns
west IN LUA A ("ifurlup('https://www.lua.org/', {{'192.0.2.1', '192.0.2.2'}, {'198.51.100.1'}}, {stringmatch='Programming in Lua'})")

```

這會：

- 嘗試對 `www.lua.org` 發出 HTTPS；
- 若回應內容包含 `Programming in Lua`，則視為可用；
- 第一組 IP 可用 → 回第一組；否則 → 回第二組。

與地理導向結合：

```dns
www IN LUA CNAME (";if(continent('EU')) then return 'west.powerdns.org' else return 'usa.powerdns.org' end")

```

對應的 `usa` 名稱配置如下：

```dns
usa IN LUA A ("ifurlup('https://www.lua.org/', {{'198.51.100.1'}, {'192.0.2.1', '192.0.2.2'}}, {stringmatch='Programming in Lua'})")

```

歐洲以外的訪客會優先使用 `198.51.100.1`，  
若失效則回到 `192.0.2.1` / `192.0.2.2`。

---

## 六、進階主題

### (1) 語法模式

若記錄內容未以 `;` 開頭，PDNS 會自動加上 `return`。  
若要撰寫完整 Lua 腳本，請以分號 `;` 開頭。

### (2) 可引用其他記錄的設定

可用 `include()` 引用共用設定：

```dns
config IN LUA LUA ("settings={stringmatch='Programming in Lua'} EUips={'192.0.2.1','192.0.2.2'} USAips={'198.51.100.1'}")

usa IN LUA A (";include('config') return ifurlup('https://www.lua.org/', {USAips, EUips}, settings)")
west IN LUA A (";include('config') return ifurlup('https://www.lua.org/', {EUips, USAips}, settings)")

```

---

## 七、安全與同步機制

- LUA Record 是查詢時即時生成；
- 可透過 AXFR 同步至其他 PDNS 伺服器；
- 但無法直接查詢（防止外部洩露負載邏輯）。

> ⚠️ **警告：**
> 
> - 絕對不要從不信任的來源匯入含 LUA Record 的 zone！  
>     惡意 Lua 可能導致伺服器崩潰甚至被接管。
> - 即使是可信來源也請使用 TSIG 保護 AXFR 傳輸。

若有 DNSSEC 簽章需求，  
LUA Record 必須由主伺服器即時簽署（無法預先簽署 zone）。

---

## 八、共享 Lua 狀態模式（shared mode）

預設情況下，PDNS 每次查詢都會建立新的 Lua 執行環境。  
這樣每筆 LUA Record 彼此獨立，不會污染變數。  
但建立 Lua state 很耗時。

可啟用共用模式：

```
enable-lua-records=shared

```

- 每個執行緒建立一個 Lua 狀態並重複使用；
- 約可提升 QPS 10 倍；
- 各執行緒 Lua 環境獨立（UDP 為多實例，TCP 共用一個）。

---

## 九、Reference（函式與物件類別）

PowerDNS 提供的 Lua 內建 API 包含：

### 預設變數（Preset Variables）

- `qname`, `qtype`, `remoteip`, `ednssubnet` 等

### 可用函式

- `getdns()`, `ifportup()`, `pickclosest()`, `country()`, `continent()`
- `ifurlup()`, `include()`, `pdnslog()`, 等

### 物件類別

- `DNSName`, `ComboAddress`, `DNSResourceRecord`, `DNSHeader`, `QType`
- `Netmask`, `ComboAddressSet`, `DNSRecord`, 及輔助函式群組

（這些內容在官方文件的「LUA Reference」章節中詳細列出）

---

## 🔚 總結

<table id="bkmrk-%E5%8A%9F%E8%83%BD-%E8%AA%AA%E6%98%8E-lua-record-pow"><thead><tr><th>功能</th><th>說明</th></tr></thead><tbody><tr><td>**LUA Record**</td><td>PowerDNS 內建的動態 DNS 回覆機制</td></tr><tr><td>**語言**</td><td>Lua</td></tr><tr><td>**用途**</td><td>智能選址、健康檢查、地理導向、服務偵測</td></tr><tr><td>**啟用方式**</td><td>`enable-lua-records=yes` 或 `ENABLE-LUA-RECORDS=1`</td></tr><tr><td>**安全性**</td><td>僅限信任 zone；建議使用 TSIG</td></tr><tr><td>**效能優化**</td><td>`enable-lua-records=shared` 可大幅提高 QPS</td></tr></tbody></table>

---

是否要我幫你把這篇翻譯版整理成 **可直接放進公司內部 Wiki 的 Markdown 版（含語法高亮與範例區塊）**？  
我可以自動加上標題層級、代碼框、注意區塊與翻譯對照欄位。

# 【PowerDns】dnsdist

傳遞來源ip  
[https://www.dnsdist.org/advanced/passing-source-address.html](https://www.dnsdist.org/advanced/passing-source-address.html)

```shell
addLocal("0.0.0.0:53")

-- Recursor 作為唯一後端
-- useClientSubnet=true 傳送ECS 來源端資訊 
newServer({ name="rec", address="127.0.0.1:5301", pool="recursor", useClientSubnet=true })

--設定ipv4顯示的位數 
setECSSourcePrefixV4(32)
setECSSourcePrefixV6(128)

-- 不加任何分流規則，全部都送 recursor
addAction(AllRule(), PoolAction("recursor"))
```