【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 & 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() 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 可分優先層級,例如: www IN LUA A "ifportup(443, {{'192.0.2.1', '192.0.2.2'}, {'192.0.3.1'}})" 這表示: 若第一組中的任一 IP 可用 → 回第一組; 否則 → 試第二組。 因為 DNS 查詢要求極快回應,PowerDNS 不會即時檢查連線狀態, 而是由背景程序定期檢測這些 IP 是否可用。 2️⃣ pickclosest() www IN LUA A "pickclosest({'192.0.2.1','192.0.2.2','198.51.100.1'})" 這會根據查詢者的地理位置(GeoIP), 選擇最靠近使用者的 IP 回覆。 也可以與 ifportup() 結合: www IN LUA A ("ifportup(443, {'192.0.2.1', '192.0.2.2', '198.51.100.1'}, {selector='pickclosest'})") 這會在可用的 IP 中挑出距離使用者最近的一個。 3️⃣ 複雜 Lua 程式碼範例 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 的例子 *.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 時需特別轉義。 範例如下: -- 建立 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 例如: www IN LUA A "pickclosest({'1.1.1.1','8.8.8.8'})" 可設定 TTL,PowerDNS 會照常套用; 可被 DNSSEC 簽章(需在同一伺服器即時簽署)。 五、更強大的範例 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 可用 → 回第一組;否則 → 回第二組。 與地理導向結合: www IN LUA CNAME (";if(continent('EU')) then return 'west.powerdns.org' else return 'usa.powerdns.org' end") 對應的 usa 名稱配置如下: 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() 引用共用設定: 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」章節中詳細列出) 🔚 總結 功能 說明 LUA Record PowerDNS 內建的動態 DNS 回覆機制 語言 Lua 用途 智能選址、健康檢查、地理導向、服務偵測 啟用方式 enable-lua-records=yes 或 ENABLE-LUA-RECORDS=1 安全性 僅限信任 zone;建議使用 TSIG 效能優化 enable-lua-records=shared 可大幅提高 QPS 是否要我幫你把這篇翻譯版整理成 可直接放進公司內部 Wiki 的 Markdown 版(含語法高亮與範例區塊)? 我可以自動加上標題層級、代碼框、注意區塊與翻譯對照欄位。