smartdns3智能 dns 系統(tǒng)
smartdns 是 python3 語言編寫,smartdns 基于小米 smartdns 二次開發(fā),支持類似 Dnspod 的 D 監(jiān)控功能,能夠支持針對不同的 dns 請求根據(jù)配置返回不同的解析結(jié)果。smartdns獲取dns請求的源IP或者客戶端IP(支持edns協(xié)議的請求可以獲取客戶端IP),根據(jù)本地的靜態(tài)IP庫獲取請求IP的特性,包括所在的國家、省份、城市、ISP等,然后根據(jù)我們的調(diào)度配置返回解析結(jié)果,smartdns 的典型使用場景:
- 服務(wù)的多機房流量調(diào)度,比如電信流量調(diào)度到電信機房、聯(lián)通流量調(diào)度到聯(lián)通機房;
- 用戶訪問控制,將用戶調(diào)度到離用戶最近或者鏈路質(zhì)量最好的節(jié)點上。
舉個簡單的例子,我們的一個站點test.test.com同時部署在電信和聯(lián)通兩個機房,該站點在電信機房的ip為1.1.1.1、在聯(lián)通機房的ip為2.2.2.2,就可以通過smartdns做到該站點域名解析時判斷源IP為電信的IP時返回1.1.1.1、判斷源IP為聯(lián)通的IP時返回2.2.2.2,從而達(dá)到不同運營商機房流量調(diào)度的目的。
安裝方法
- 安裝python-devel以及bzip2包,以centos為例:
yum install -y bzip2 python-devel - 執(zhí)行
pip install smartdns腳本即可完成安裝
支持的功能
支持A、SOA、NS記錄的查詢,支持DNS forward功能
性能
在虛擬機2.4G CPU上能夠處理1000QPS查詢請求,打開debug日志后可以到800QPS。3-5臺dns server組成的集群已經(jīng)能夠滿足大部分站點的需求。
目前我們正在實現(xiàn)和小流量測試go語言實現(xiàn)的smartdns,能夠達(dá)到3wQPS以上,后續(xù)測試穩(wěn)定后會開源出來,大家敬請期待:)
原理
smartdns響應(yīng)dns請求的處理流程如下:
IPPool類的初始化和該類中FindIP方法進行解析處理是smartdns中最關(guān)鍵的兩個要素,這兩個要素在下面詳細(xì)介紹。其他的特性比如繼承twisted中dns相關(guān)類并重寫處理dns請求的方法、升級twisted代碼支持解析和處理edns請求等大家可以通過代碼了解。edns知識可以猛戳這里:DNS support edns-client-subnet
IPPool初始化
ip.csv內(nèi)容格式如下: 200000001, 200000010,中國,陜西,西安,電信
其中各個字段含義分別為 IP段起始,IP段截止,IP段所屬國家,IP段所屬省份,IP段所屬城市,IP段所屬ISP
a.yaml配置文件格式:
test.test.com: ttl: 3600 default: 5.5.5.5 2.2.2.2 中國,廣東,,聯(lián)通: 1.1.1.1 3.3.3.1 中國,廣東,,電信: 1.1.1.2 3.3.3.2
配置中地域信息的key包括四個字段,分別帶有不同的權(quán)重:
- 國家: 8
- 省份: 4
- 城市: 2
- 運營商: 1
初始化階段,會生成一個名為iphash的dict,具體數(shù)據(jù)結(jié)構(gòu)如下圖:
其中,iphash的key為ip.csv每一條記錄的起始IP,value為一個list,list長度為6,list前5個字段分別為以該key為起始IP記錄的IP段截止、IP段所屬國家、IP段所屬省份、IP段所屬城市、IP段所屬ISP,第六個字段是一個hash,key為a.yaml里面配置的域名,value為長度為2的list,iphash[IP段起始][6][域名1][0]為域名1在該IP段的最優(yōu)解析,iphash[IP段起始][6][域名1][1]為該最優(yōu)解析的總權(quán)值,該總權(quán)值暫時只做參考。
iphash初始化過程中最關(guān)鍵的是iphash[IP段起始][6][域名1]的最優(yōu)解析的計算,最簡單直接的方式是直接遍歷域名1的所有調(diào)度配置,挑選出滿足條件且總權(quán)值最高的解析,即為最優(yōu)解析。這種方式記錄整個iphash的時間復(fù)雜度為O(xyz),x為ip.csv記錄數(shù),y為域名總數(shù)量,z為各個域名的調(diào)度配置數(shù)。為了優(yōu)化啟動速度,優(yōu)化了尋找最優(yōu)解析的方法:事先將每個域名調(diào)度配置生成一顆樹,這棵樹是用dict模擬出來的,這樣需要最優(yōu)解的時候就不需要遍歷所有調(diào)度配置,而是最多檢索15次即可找到最優(yōu),即時間復(fù)雜度為O(15xy),具體實現(xiàn)參考IPPool的LoadRecord和JoinIP兩個方法。
有了初始化后的iphash數(shù)據(jù)結(jié)構(gòu)之后,每次請求處理的時候,只需要定位請求IP處在哪個IP段,找到IP段起始IP,然后從iphash中取出最優(yōu)解析,取出最優(yōu)解析的過程是O(1)的。具體流程如下:
監(jiān)控
監(jiān)控配置詳見配置目錄的monitor.yaml,內(nèi)容如下:
test.test.cn:
interval: 30
frequency: 3
url: https://www.baidu.com
分別代表監(jiān)控域名、監(jiān)控周期(秒)、容錯次數(shù)、監(jiān)控url,監(jiān)控失敗的次數(shù)大于容錯次數(shù)則停止該條記錄的解析。
代碼
github: https://github.com/duanhongyi/smartdns
安裝
依賴:
gcc bzip2 python3以及相關(guān)dev包 Twisted
安裝:
git clone smartdns到本地路徑,執(zhí)行python setup.py install命令安裝。
啟動:
執(zhí)行sdns /etc/smartdns即可啟動smartdns
測試
本地測試 dig test.test.com @127.0.0.1
或者將搭建的smartdns加到測試域名的ns中進行測試。
支持
mail: [email protected]
github: duanhongyi
EDNS相關(guān)請參考:DNS support edns-client-subnet
