描述
重寫對客戶端是不可見的。有簡單的重寫(速度快)和複雜的重寫(速度較慢),但它們的功能足夠強大,可以適應大多數動態後端應用程式。
語法
rewrite 的簡化/易於理解的語法是...
rewrite [continue|stop] FIELD [TYPE] [(FROM TO)|TTL] [OPTIONS]
-
FIELD 指示正在重寫的請求/回應的哪個部分。
type
- 請求的類型欄位將被重寫。FROM/TO 必須是 DNS 記錄類型 (A
、MX
等);例如,要將 ANY 查詢重寫為 HINFO,請使用rewrite type ANY HINFO
。name
- 請求中的查詢名稱將被重寫;預設情況下,這是名稱的完整匹配,例如,rewrite name example.net example.org
。其他匹配類型也支援,請參閱下面的名稱欄位重寫章節。class
- 訊息的類別將被重寫。FROM/TO 必須是 DNS 類別類型 (IN
、CH
或HS
);例如,要將 CH 查詢重寫為 IN,請使用rewrite class CH IN
。edns0
- 可以將 EDNS0 選項附加到請求,如下面的 EDNS0 選項章節所述。ttl
- 回應中的 TTL 值將被重寫。cname
- 如果回應有 CNAME 記錄,則為 CNAME 目標。
-
TYPE 此選用元素可以針對
name
或ttl
欄位指定。如果未給定,將假定類型為exact
。如果要指定選項,則必須給定類型。 -
FROM 是要匹配的名稱(精確、後綴、前綴、子字串或正規表示式)或類型。
-
TO 是要重寫成的目標名稱或類型。
-
TTL 是將 TTL 值設定為的秒數(僅適用於欄位
ttl
)。 -
選項
對於欄位
name
,可以進一步控制回應重寫。所有名稱匹配類型都支援以下選項answer auto
- 以盡力而為的方式重寫回應中的名稱。answer name FROM TO
- 重寫回應中的查詢名稱,使其符合 from 正規表示式模式。answer value FROM TO
- 重寫回應中的名稱,使其符合 from 正規表示式模式。
有關詳細資訊,請參閱下面的回應重寫章節。
如果您指定多個規則,且傳入的查詢符合多個規則,則重寫的行為如下
continue
將繼續應用規則清單中的下一個規則。stop
將目前規則視為最後一個規則,並且不會繼續。預設行為是stop
。
範例
名稱欄位重寫
rewrite
外掛程式可以匹配 DNS 請求問題區段中的名稱。匹配可以是精確匹配、子字串匹配,或基於前綴、後綴或正規表示式。如果新使用的名稱不是合法的網域名稱,則外掛程式會向用戶端傳回錯誤。
名稱重寫的語法如下
rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING [OPTIONS]
匹配類型,例如 exact
、substring
等,會觸發重寫。
- exact(預設):在精確匹配請求問題區段中的名稱時。
- substring:在部分匹配請求問題區段中的名稱時。
- prefix:當名稱以匹配的字串開頭時。
- suffix:當名稱以匹配的字串結尾時。
- regex:當請求問題區段中的名稱與正規表示式匹配時。
如果省略匹配類型,則會假定為 exact
匹配類型。如果給定選項,則必須指定類型。
以下指令允許重寫查詢中包含子字串 service.us-west-1.example.org
的名稱。
rewrite name substring service.us-west-1.example.org service.us-west-1.consul
因此
- 傳入的請求名稱:
ftp.service.us-west-1.example.org
- 重寫的請求名稱:
ftp.service.us-west-1.consul
以下指令使用正規表示式。與正規表示式 (.*)-(us-west-1)\.example\.org
相符的請求中的名稱將被替換為 {1}.service.{2}.consul
,其中 {1}
和 {2}
是正規表示式匹配群組。
rewrite name regex (.*)-(us-west-1)\.example\.org {1}.service.{2}.consul
因此
- 傳入的請求名稱:
ftp-us-west-1.example.org
- 重寫的請求名稱:
ftp.service.us-west-1.consul
以下範例將 schmoogle.com
後綴重寫為 google.com
。
rewrite name suffix .schmoogle.com. .google.com.
回應重寫
當重寫傳入的 DNS 請求名稱(欄位 name
)時,CoreDNS 會重寫請求的 QUESTION SECTION
區段。可能需要重寫請求的 ANSWER SECTION
,因為某些 DNS 解析器會將 QUESTION SECTION
和 ANSWER SECTION
之間的不匹配視為中間人攻擊 (MITM)。
例如,使用者嘗試解析 ftp-us-west-1.coredns.rocks
。CoreDNS 設定檔具有以下規則
rewrite name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul
CoreDNS 將請求從 ftp-us-west-1.coredns.rocks
重寫為 ftp.service.us-west-1.consul
,並最終解析為 3 條記錄。以下 ANSWER SECTION
中已解析的記錄不是來自 coredns.rocks
,而是來自 service.us-west-1.consul
。
$ dig @10.1.1.1 ftp-us-west-1.coredns.rocks
;; QUESTION SECTION:
;ftp-us-west-1.coredns.rocks. IN A
;; ANSWER SECTION:
ftp.service.us-west-1.consul. 0 IN A 10.10.10.10
ftp.service.us-west-1.consul. 0 IN A 10.20.20.20
ftp.service.us-west-1.consul. 0 IN A 10.30.30.30
以上是所詢問的問題與提供的答案之間的不匹配。
有三種可能性可以指定答案重寫
- 重寫可以請求盡力而為的答案重寫,方法是新增選項
answer auto
。 - 重寫可以使用
answer name FROM TO
選項指定專用的基於正規表示式的回應名稱重寫。 - 可以使用
answer value FROM TO
選項請求對記錄值(例如CNAME
、SRV
等)的基於正規表示式的重寫。
此處 FROM/TO 遵循 regex
名稱重寫語法的規則。
自動回應名稱重寫
以下設定程式碼片段允許根據 QUESTION SECTION
的重寫來重寫 ANSWER SECTION
rewrite stop {
name suffix .coredns.rocks .service.consul answer auto
}
答案中任何出現的重寫問題都會被對應回重寫之前的原始值。
請注意,類型為 exact
的重寫答案始終會被重寫。對於 suffix
名稱規則,auto
會導致反向後綴回應重寫,交換重寫請求中的 FROM 和 TO。
明確回應名稱重寫
以下設定程式碼片段允許重寫 ANSWER SECTION
,前提是 QUESTION SECTION
已被重寫
rewrite stop {
name regex (.*)-(us-west-1)\.coredns\.rocks {1}.service.{2}.consul
answer name (.*)\.service\.(us-west-1)\.consul {1}-{2}.coredns.rocks
}
現在,ANSWER SECTION
與 QUESTION SECTION
相符
$ dig @10.1.1.1 ftp-us-west-1.coredns.rocks
;; QUESTION SECTION:
;ftp-us-west-1.coredns.rocks. IN A
;; ANSWER SECTION:
ftp-us-west-1.coredns.rocks. 0 IN A 10.10.10.10
ftp-us-west-1.coredns.rocks. 0 IN A 10.20.20.20
ftp-us-west-1.coredns.rocks. 0 IN A 10.30.30.30
重寫其他回應值
也可以重寫 DNS 回應記錄中傳回的其他值(例如,在 SRV
和 MX
記錄中傳回的伺服器名稱)。可以透過將 answer value FROM TO
選項新增至如下所示的名稱規則來啟用此功能。answer value
採用正規表示式和重寫名稱作為參數,其運作方式與 answer name
規則相同。
請注意,AUTHORITY SECTION
和 ADDITIONAL SECTION
中的名稱也會按照指定的規則重寫。如果指定了 answer value
規則,則會重寫以下記錄類型傳回的名稱:CNAME
、DNAME
、SOA
、SRV
、MX
、NAPTR
、NS
、PTR
。
DNS 請求和回應的重寫語法如下
rewrite [continue|stop] {
name regex STRING STRING
answer name STRING STRING
[answer value STRING STRING]
}
請注意,以上語法很嚴格。對於回應重寫,只允許 name
規則符合問題區段。答案重寫必須在名稱之後,如語法範例中所示。
範例:PTR 回應值重寫
原始回應包含 ANSWER SECTION
的 VALUE
部分中的網域 service.consul.
$ dig @10.1.1.1 30.30.30.10.in-addr.arpa PTR
;; QUESTION SECTION:
;30.30.30.10.in-addr.arpa. IN PTR
;; ANSWER SECTION:
30.30.30.10.in-addr.arpa. 60 IN PTR ftp-us-west-1.service.consul.
以下設定程式碼片段允許重寫 ANSWER SECTION
中的值
rewrite stop {
name suffix .arpa .arpa
answer name auto
answer value (.*)\.service\.consul\. {1}.coredns.rocks.
}
現在,ANSWER SECTION
中的 VALUE
已在網域部分被覆寫
$ dig @10.1.1.1 30.30.30.10.in-addr.arpa PTR
;; QUESTION SECTION:
;30.30.30.10.in-addr.arpa. IN PTR
;; ANSWER SECTION:
30.30.30.10.in-addr.arpa. 60 IN PTR ftp-us-west-1.coredns.rocks.
多個回應重寫
可以透過附加多個答案重寫選項來串連 name
和 value
重寫。對於除第一個之外的所有出現,可能會省略關鍵字 answer
。
answer (auto | (name|value FROM TO)) { [answer] (auto | (name|value FROM TO)) }
例如
rewrite [continue|stop] name regex FROM TO answer name FROM TO [answer] value FROM TO
使用 exact
名稱重寫規則時,答案會自動重寫,因此不需要定義 answer name auto
。但仍然可以定義其他 answer value
和 answer value
選項。
以下規則將請求中的名稱從 RED
重寫為 BLUE
,然後將對應回應中的名稱從 BLUE
重寫為 RED
。請求中的用戶端將只會看到 RED
,而不會看到 BLUE
。
rewrite [continue|stop] name exact RED BLUE
TTL 欄位重寫
有時,可能需要重寫 TTL 值。例如,DNS 伺服器可能不會快取 TTL 為零 (0
) 的記錄。管理員可能希望增加 TTL,以確保快取它,例如,將其增加到 15 秒。
在以下範例中,coredns.rocks
網域的答案中的 TTL 設定為 15
rewrite continue {
ttl regex (.*)\.coredns\.rocks 15
}
同樣地,管理員可以使用此功能,方法是將 TTL 值設定為非常低,以防止或限制快取。
TTL 重寫規則的語法如下。exact|prefix|suffix|substring|regex
的含義與名稱重寫規則相同。省略的類型預設為 exact
。
rewrite [continue|stop] ttl [exact|prefix|suffix|substring|regex] STRING [SECONDS|MIN-MAX]
可以在 SECONDS
參數中提供 TTL 值的範圍,而不是單一值。如果提供範圍,則如果 TTL 值低於該值,則設定為 MIN
,如果高於該值,則設定為 MAX
。如果 TTL 值已在提供的範圍內,則保持不變。範圍可以在任一側無界限。
帶有範圍的 TTL 範例
# rewrite TTL to be between 30s and 300s
rewrite ttl example.com. 30-300
# cap TTL at 30s
rewrite ttl example.com. -30 # equivalent to rewrite ttl example.com. 0-30
# increase TTL to a minimum of 30s
rewrite ttl example.com. 30-
# set TTL to 30s
rewrite ttl example.com. 30 # equivalent to rewrite ttl example.com. 30-30
EDNS0 選項
使用 FIELD edns0,您可以在請求中設定、附加或取代特定的 EDNS0 選項。
replace
會使用指定的選項修改任何「匹配」的選項。 「匹配」的標準會根據 EDNS0 類型而有所不同。append
僅在沒有匹配選項時才會新增選項set
會修改匹配的選項,如果沒有找到則新增一個
目前支援 EDNS0_LOCAL
、EDNS0_NSID
和 EDNS0_SUBNET
。
EDNS0_LOCAL
此選項有兩個欄位,代碼 (code) 和數據 (data)。 匹配的定義是具有相同的代碼。數據可以是字串或變數。
- 如果字串數據以
0x
開頭,則會被視為十六進制。範例:
. {
rewrite edns0 local set 0xffee 0x61626364
whoami
}
會將第一個代碼為 0xffee 的本機選項改寫,並將數據設定為 "abcd"。這等同於:
. {
rewrite edns0 local set 0xffee abcd
}
-
變數數據會使用一對大括號
{}
指定。以下是支援的變數:{qname}、{qtype}、{client_ip}、{client_port}、{protocol}、{server_ip}、{server_port}。 -
如果已啟用 metadata 外掛程式,則如果標籤出現在大括號內,則這些標籤也支援作為變數。變數數據將會被替換為與該標籤相關聯的值。如果未提供該標籤,則該變數將會被靜默地替換為空字串。
範例
rewrite edns0 local set 0xffee {client_ip}
以下範例使用 metadata 和一個假設的 "some-plugin",該外掛程式會提供 "some-label" 作為 metadata 資訊。
metadata
some-plugin
rewrite edns0 local set 0xffee {some-plugin/some-label}
EDNS0_NSID
此選項沒有欄位;它會為 NSID 新增一個 NSID 選項,並以空字串作為 NSID 的值。如果該選項已存在,且操作為 replace
或 set
,則選項中的 NSID 將會設定為空字串。
EDNS0_SUBNET
此選項有兩個欄位,IPv4 位元遮罩長度和 IPv6 位元遮罩長度。位元遮罩長度用於從查詢中的來源 IP 位址擷取用戶端子網路。
範例:
rewrite edns0 subnet set 24 56
- 如果查詢的來源 IP 位址是 IPv4 位址,則 IP 中的前 24 個位元將會是網路子網路。
- 如果查詢的來源 IP 位址是 IPv6 位址,則 IP 中的前 56 個位元將會是網路子網路。
CNAME 欄位改寫
在某些情況下,您可能希望改寫回應的 CNAME
目標。您可以使用 CNAME
欄位改寫來實現此目的。這將會根據新的 CNAME
目標產生新的答案記錄。
CNAME 改寫規則的語法如下所示。 exact|prefix|suffix|substring|regex
的含義與名稱改寫規則相同。省略的類型預設為 exact
。
rewrite [continue|stop] cname [exact|prefix|suffix|substring|regex] FROM TO
考慮以下使用 regex 類型的 CNAME
改寫規則。
rewrite cname regex (.*).cdn.example.net. {1}.other.cdn.com.
如果您在沒有上述規則的情況下傳送以下 DNS 請求,則範例回應將會是:
$ dig @10.1.1.1 my-app.com
;; QUESTION SECTION:
;my-app.com. IN A
;; ANSWER SECTION:
my-app.com. 200 IN CNAME my-app.com.cdn.example.net.
my-app.com.cdn.example.net. 300 IN A 20.2.0.1
my-app.com.cdn.example.net. 300 IN A 20.2.0.2
如果您在設定上述規則的情況下傳送相同的 DNS 請求,則範例回應將會是:
$ dig @10.1.1.1 my-app.com
;; QUESTION SECTION:
;my-app.com. IN A
;; ANSWER SECTION:
my-app.com. 200 IN CNAME my-app.com.other.cdn.com.
my-app.com.other.cdn.com. 100 IN A 30.3.1.2
請注意,在改寫 CNAME
目標之後,答案將會包含一組完全不同的答案記錄。