WHOIS是網際網路中用來查詢網域名稱和IP的服務,可以讓我們在連結到對方的伺服器前,先行確認對方究竟是誰(沒錯,就是Who is ...?),避免連線到不安全的伺服器。在開發Rust程式的時候,也可以利用WHOIS來做對外連線的檢查。



WHOIS Rust

「WHOIS Rust」是筆者開發的套件,受到whois這個Node.JS套件的啟發,採用了servers.json作為WHOIS的伺服器查詢清單,可以針對IP或是不同的網域名稱自動或是手動選擇要查詢的WHOIS伺服器,並且也支援WHOIS伺服器的轉介(referral)。

Crates.io

Cargo.toml

whois-rust = "*"

使用方法

建立servers.json

以下是一個簡單的servers.json範例:

{
    "magiclen.org": "whois.magiclen.org",
    "org": "whois.pir.org",
    "": "whois.ripe.net",
    "_": {
        "ip": {
            "host": "whois.arin.net",
            "query": "n + $addr\r\n"
        }
    }
}

當查詢的字串是IP的時候,套件會自動選擇whois.arin.net這個WHOIS伺服器來查詢。當查詢的字串結尾是magiclen.org時,套件會自動選擇whois.magiclen.org這個WHOIS伺服器來查詢。當查詢的字串結尾是org時,套件會自動選擇whois.pir.org這個WHOIS伺服器來查詢。當查詢的字串結尾沒有明確地被列在servers.json中時,就會用whois.ripe.net這個WHOIS伺服器來查詢。

完整標準的servers.jsonWHOIS伺服器清單,可以從「whois」這個Node.JS套件的Github Repository中取得:

servers.json中,WHOIS伺服器的值可以是一個字串,也可以是一個JSON物件。如果是字串的話,預設的查詢字串為$addr\r\n$addr為查詢時目標位址會被代入的變數。如果是JSON物件的話,就可以利用query欄位來修改查詢字串的格式。WHOIS伺服器預設的連接埠為43,如果要修改的話,直接在WHOIS伺服器的Host字串中使用域名或IP:連接埠的格式即可。

讀取servers.json

建立好servers.json,可以利用whois_rust這個crate所提供的WhoIs結構體的from_path或是from_string關聯函數來讀取,並建立出WhoIs結構實體。

from_path可以從檔案讀取servers.json的資料,例如:

use whois_rust::WhoIs;

let whois = WhoIs::from_path("/path/to/servers.json").unwrap();

from_string可以從記憶體讀取servers.json的資料,建議搭配include_str巨集一同使用,例如:

use whois_rust::WhoIs;

let whois = WhoIs::from_string(include_str!("/path/to/servers.json")).unwrap();
查詢

whois_rust這個crate中有一個WhoIsLookupOptions結構體,要進行WHOIS查詢前,必須要建立出WhoIsLookupOptions的結構實體。WhoIsLookupOptions結構體提供了from_domainfrom_ipv4from_ipv6from_string關聯函數,可以快速建立出已包含查詢目標的WhoIsLookupOptions結構實體。

一般來說,WhoIsLookupOptions結構實體一旦建立出來就可以被使用了,但是如果您有特殊需求,想要手動指定查詢時使用的WHOIS伺服器的話,可以修改其server欄位。如果要修改(預設是2)WHOIS伺服器的轉介次數,可以修改其follow欄位。如果要修改(預設是60000毫秒,也就是一分鐘)WHOIS伺服器的逾時時間,可以修改其timeout欄位。

使用WhoIs結構實體提供的lookup方法,搭配建立好的WhoIsLookupOptions結構實體,即可進行查詢,舉例來說:

use whois_rust::{WhoIs, WhoIsLookupOptions};

let whois = WhoIs::from_path("/path/to/servers.json").unwrap();

let result: String = whois.lookup(WhoIsLookupOptions::from_string("magiclen.org").unwrap()).unwrap();

因為WHOIS是直接給人類使用,進行查詢與查看結果的服務,因此查詢結果並沒有規範太多的格式,以致於沒有一個通用的方法將結果轉成特定的資料結構來儲存。因此WhoIs結構實體提供的lookup方法,會原封不動地拿到WHOIS伺服器的回傳結果。