文件
一個 專案

reverse_proxy

將請求代理到一個或多個後端,並具有可配置的傳輸、負載平衡、健康檢查、請求操作和緩衝選項。

語法

reverse_proxy [<matcher>] [<upstreams...>] {
	# backends
	to      <upstreams...>
	dynamic <module> ...

	# load balancing
	lb_policy       <name> [<options...>]
	lb_retries      <retries>
	lb_try_duration <duration>
	lb_try_interval <interval>
	lb_retry_match  <request-matcher>

	# active health checking
	health_uri      <uri>
	health_upstream <ip:port>
	health_port     <port>
	health_interval <interval>
	health_passes   <num>
	health_fails	<num>
	health_timeout  <duration>
	health_status   <status>
	health_body     <regexp>
	health_follow_redirects
	health_headers {
		<field> [<values...>]
	}

	# passive health checking
	fail_duration     <duration>
	max_fails         <num>
	unhealthy_status  <status>
	unhealthy_latency <duration>
	unhealthy_request_count <num>

	# streaming
	flush_interval     <duration>
	request_buffers    <size>
	response_buffers   <size>
	stream_timeout     <duration>
	stream_close_delay <duration>

	# request/header manipulation
	trusted_proxies [private_ranges] <ranges...>
	header_up   [+|-]<field> [<value|regexp> [<replacement>]]
	header_down [+|-]<field> [<value|regexp> [<replacement>]]
	method <method>
	rewrite <to>

	# round trip
	transport <name> {
		...
	}

	# optionally intercept responses from upstream
	@name {
		status <code...>
		header <field> [<value>]
	}
	replace_status [<matcher>] <status_code>
	handle_response [<matcher>] {
		<directives...>

		# special directives only available in handle_response
		copy_response [<matcher>] [<status>] {
			status <status>
		}
		copy_response_headers [<matcher>] {
			include <fields...>
			exclude <fields...>
		}
	}
}

上游

  • <upstreams...> 是上游(後端)的列表,代理到這些上游。
  • to 是指定上游列表的另一種方式,每行一個(或多個)。
  • dynamic 配置 *動態上游* 模組。這允許為每個請求動態取得上游列表。請參閱下方的動態上游,以取得標準動態上游模組的描述。動態上游在每次代理迴圈迭代時檢索(即,如果啟用了負載平衡重試,則每個請求可能多次),並且將優先於靜態上游。如果發生錯誤,代理將退回到使用任何靜態配置的上游。

上游位址

靜態上游位址可以採用僅包含協定和主機/埠的 URL 形式,或傳統的 Caddy 網路位址。有效範例

  • localhost:4000
  • 127.0.0.1:4000
  • [::1]:4000
  • https://127.0.0.1:4000
  • https://example.com
  • h2c://127.0.0.1
  • example.com
  • unix//var/php.sock
  • unix+h2c//var/grpc.sock
  • localhost:8001-8006
  • [fe80::ea9f:80ff:fe46:cbfd%eth0]:443

預設情況下,連線是透過純文字 HTTP 連接到上游。當使用 URL 形式時,可以使用協定來設定一些transport 預設值作為簡寫。

  • 使用 https:// 作為協定將使用 http 傳輸,並啟用 tls

    此外,您可能需要覆寫 Host 標頭,使其與 TLS SNI 值匹配,伺服器使用該值進行路由和憑證選擇。有關更多詳細資訊,請參閱下方的 HTTPS 章節。

  • 使用 h2c:// 作為協定將使用 http 傳輸,並將 HTTP 版本設定為允許明文 HTTP/2 連線。

  • 使用 http:// 作為協定與省略協定相同,因為 HTTP 已經是預設值。包含此語法是為了與其他協定快捷方式對稱。

協定不能混合使用,因為它們修改了常見的傳輸配置(啟用 TLS 的傳輸不能同時承載 HTTPS 和純文字 HTTP)。任何明確的傳輸配置都不會被覆寫,並且省略協定或使用其他埠不會假定特定的傳輸。

當將 IPv6 與區域(例如,具有特定網路介面的連結本機位址)一起使用時,協定不能用作快捷方式,因為 % 將導致 URL 解析錯誤;請改為明確配置傳輸。

當使用 網路位址 形式時,網路類型被指定為上游位址的前綴。這不能與 URL 協定組合使用。作為一個特例,unix+h2c/ 作為 unix/ 網路加上與 h2c:// 協定相同的效果的快捷方式受到支援。埠範圍作為快捷方式受到支援,它會擴展到具有相同主機的多個上游。

上游位址不能包含路徑或查詢字串,因為這意味著在代理時同時重寫請求,這種行為未定義或不受支援。如果您需要這樣做,可以使用 rewrite 指令。

如果位址不是 URL(即沒有協定),則可以使用 佔位符,但這會使上游動態靜態,這意味著在健康檢查和負載平衡方面,潛在的許多不同後端充當單個靜態上游。如果可能,我們建議改用動態上游模組。當使用佔位符時,必須包含埠(透過佔位符替換或作為位址的靜態後綴)。

動態上游

Caddy 的反向代理標準配備了一些動態上游模組。請注意,使用動態上游會對負載平衡和健康檢查產生影響,具體取決於特定的策略配置:主動健康檢查不適用於動態上游;如果上游列表相對穩定且一致(尤其是使用循環調度時),則負載平衡和被動健康檢查效果最佳。理想情況下,動態上游模組僅傳回健康、可用的後端。

SRV

從 SRV DNS 記錄檢索上游。

	dynamic srv [<full_name>] {
		service   <service>
		proto     <proto>
		name      <name>
		refresh   <interval>
		resolvers <ip...>
		dial_timeout        <duration>
		dial_fallback_delay <duration>
	}
  • <full_name> 是要查找的記錄的完整網域名稱(即 _service._proto.name)。
  • service 是完整名稱的服務元件。
  • proto 是完整名稱的協定元件。可以是 tcpudp
  • name 是名稱元件。或者,如果 serviceproto 為空,則為要查詢的完整網域名稱。
  • refresh 是刷新快取結果的頻率。預設值:1m
  • resolvers 是要覆寫系統解析器的 DNS 解析器列表。
  • dial_timeout 是撥號查詢的逾時時間。
  • dial_fallback_delay 是在產生 RFC 6555 快速回退連線之前要等待多長時間。預設值:300ms

A/AAAA

從 A/AAAA DNS 記錄檢索上游。

	dynamic a [<name> <port>] {
		name      <name>
		port      <port>
		refresh   <interval>
		resolvers <ip...>
		dial_timeout        <duration>
		dial_fallback_delay <duration>
		versions ipv4|ipv6
	}
  • name 是要查詢的網域名稱。
  • port 是要用於後端的埠。
  • refresh 是刷新快取結果的頻率。預設值:1m
  • resolvers 是要覆寫系統解析器的 DNS 解析器列表。
  • dial_timeout 是撥號查詢的逾時時間。
  • dial_fallback_delay 是在產生 RFC 6555 快速回退連線之前要等待多長時間。預設值:300ms
  • versions 是要解析的 IP 版本列表。預設值:ipv4 ipv6,分別對應於 A 和 AAAA 記錄。

多個

附加多個動態上游模組的結果。如果您想要冗餘的上游來源,例如:由次要 SRV 叢集備份的主要 SRV 叢集,則此功能很有用。

	dynamic multi {
		<source> [...]
	}
  • <source> 是動態上游模組的名稱,後跟其配置。可以指定多個。

負載平衡

負載平衡通常用於在多個上游之間分配流量。透過啟用重試,它也可以與一個或多個上游一起使用,以保留請求,直到可以選擇健康的上游為止(例如,在重新啟動或重新部署上游時等待並減輕錯誤)。

預設情況下啟用此功能,並採用 random 策略。預設情況下禁用重試。

  • lb_policy 是負載平衡策略的名稱,以及任何選項。預設值:random

    對於涉及雜湊的策略,使用最高隨機權重 (HRW) 演算法,以確保具有相同雜湊金鑰的用戶端或請求映射到相同的上游,即使上游列表發生變更。

    如果註明,某些策略支援作為選項的回退,在這種情況下,它們採用一個具有 fallback <policy>區塊,該區塊採用另一個負載平衡策略。對於這些策略,預設回退是 random。配置回退允許在主要策略未選擇策略時使用次要策略,從而實現強大的組合。如果需要,回退可以巢狀多次。

    例如,header 可以用作主要策略,以允許開發人員選擇特定的上游,並為所有其他連線提供 first 的回退,以實現主/次要故障轉移。

    lb_policy header X-Upstream {
    	fallback first
    }
    
    • random 隨機選擇一個上游

    • random_choose <n> 隨機選擇兩個或多個上游,然後選擇負載最輕的一個(n 通常為 2)

    • first 從配置中定義的順序中選擇第一個可用的上游,從而允許主/次要故障轉移;請記住同時啟用健康檢查,否則不會發生故障轉移

    • round_robin 依序迭代每個上游

    • weighted_round_robin <weights...> 依序迭代每個上游,並尊重提供的權重。權重引數的數量應與配置的上游數量相符。權重應為非負整數。例如,對於兩個上游和權重 5 1,第一個上游將連續選擇 5 次,然後選擇第二個上游一次,然後循環重複。如果使用零作為權重,則將禁用為新請求選擇上游。

    • least_conn 選擇目前請求數最少的上游;如果有多個主機的請求數最少,則隨機選擇其中一個主機

    • ip_hash 將遠端 IP(直接對等方)映射到黏性上游

    • client_ip_hash 將用戶端 IP 映射到黏性上游;這最好與 servers > trusted_proxies 全域選項配對,該選項啟用真實用戶端 IP 解析,否則其行為與 ip_hash 相同

    • uri_hash 將請求 URI(路徑和查詢)映射到黏性上游

    • query [key] 透過雜湊查詢值將請求查詢映射到黏性上游;如果指定的金鑰不存在,則將使用回退策略來選擇上游(random 預設值)

    • header [field] 透過雜湊標頭值將請求標頭映射到黏性上游;如果指定的標頭欄位不存在,則將使用回退策略來選擇上游(random 預設值)

    • cookie [<name> [<secret>]] 在來自用戶端的第一個請求(當沒有 Cookie 時),將使用回退策略來選擇上游(random 預設值),並將 Set-Cookie 標頭新增到回應(如果未指定,預設 Cookie 名稱為 lb)。Cookie 值是所選上游的上游撥號位址,使用 HMAC-SHA256 雜湊(使用 <secret> 作為共用密碼,如果未指定則為空字串)。

      在後續請求中,如果 Cookie 存在,則 Cookie 值將映射到相同的上游(如果可用);如果不可用或未找到,則使用回退策略選擇新的上游,並將 Cookie 新增到回應。

      如果您希望將特定上游用於偵錯目的,則可以使用密碼雜湊上游位址,並在 HTTP 用戶端(瀏覽器或其他)中設定 Cookie。例如,對於 PHP,您可以執行以下命令來計算 Cookie 值,其中 10.1.0.10:8080 是其中一個上游的位址,而 secret 是您配置的密碼。

      echo hash_hmac('sha256', '10.1.0.10:8080', 'secret');
      // cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf
      

      您可以透過 Javascript 主控台在瀏覽器中設定 Cookie,例如設定名為 lb 的 Cookie

      document.cookie = "lb=cdd96966817dd14a99f47ee17451464f29998da170814a16b483e4c1ff4c48cf";
      
  • lb_retries 是在下一個可用主機關閉時,為每個請求重試選擇可用後端的次數。預設情況下,禁用重試(零)。

    如果 lb_try_duration 也配置了,則重試可能會在達到持續時間時提前停止。換句話說,重試持續時間優先於重試次數。

  • lb_try_duration 是一個持續時間值,用於定義在下一個可用主機關閉時,為每個請求嘗試選擇可用後端的時間長度。預設情況下,禁用重試(零持續時間)。

    在負載平衡器嘗試尋找可用的上游主機時,用戶端最多將等待這麼長時間。一個合理的起點可能是 5s,因為 HTTP 傳輸的預設撥號逾時時間為 3s,因此如果無法連線到第一個選定的上游,則應至少允許一次重試;但請隨時試驗以找到適合您用例的正確平衡。

  • lb_try_interval 是一個持續時間值,用於定義從池中選擇下一個主機之間要等待多長時間。預設值為 250ms。僅在對上游主機的請求失敗時相關。請注意,如果所有後端都關閉且延遲非常低,則將此值設定為 0 並使用非零 lb_try_duration 可能會導致 CPU 旋轉。

  • lb_retry_match 限制允許重試的請求。如果到上游的連線成功,但後續往返失敗,則請求必須符合此條件才能重試。如果到上游的連線失敗,則始終允許重試。預設情況下,僅重試 GET 請求。

    此選項的語法與具名請求匹配器的語法相同,但沒有 @name。如果只需要單個匹配器,則可以在同一行上配置它。對於多個匹配器,則需要一個區塊。

主動健康檢查

主動健康檢查在計時器上於背景執行健康檢查。要啟用此功能,需要 health_urihealth_port

  • health_uri 是主動健康檢查的 URI 路徑(和選用查詢)。

  • health_upstream 是用於主動健康檢查的 ip:port,如果與上游不同。這應與 health_header{http.reverse_proxy.active.target_upstream} 結合使用。

  • health_port 是用於主動健康檢查的埠,如果與上游的埠不同。如果使用 health_upstream,則忽略此埠。

  • health_interval 是一個持續時間值,用於定義執行主動健康檢查的頻率。預設值:30s

  • health_passes 是將後端再次標記為健康狀態之前所需的連續健康檢查次數。預設值:1

  • health_fails 是將後端標記為不健康狀態之前所需的連續健康檢查次數。預設值:1

  • health_timeout 是一個持續時間值,用於定義在將後端標記為關閉之前要等待回覆的時間長度。預設值:5s

  • health_status 是要從健康後端預期的 HTTP 狀態碼。可以是 3 位數的狀態碼,或以 xx 結尾的狀態碼類別。例如:200(預設值)或 2xx

  • health_body 是要在主動健康檢查的回應本文中匹配的子字串或正則表達式。如果後端未傳回匹配的本文,則會將其標記為關閉。

  • health_follow_redirects 將導致健康檢查跟隨上游提供的重新導向。預設情況下,重新導向回應將導致健康檢查計為失敗。

  • health_headers 允許指定要在主動健康檢查請求上設定的標頭。如果您需要變更 Host 標頭,或者如果您需要為後端提供一些身分驗證作為健康檢查的一部分,則此功能很有用。

被動健康檢查

被動健康檢查與實際代理的請求內聯發生。要啟用此功能,需要 fail_duration

  • fail_duration 是一個持續時間值,用於定義要記住失敗請求的時間長度。持續時間 > 0 會啟用被動健康檢查;預設值為 0(關閉)。一個合理的起點可能是 30s,以平衡錯誤率與在將不健康的上游恢復線上時的回應能力;但請隨時試驗以找到適合您用例的正確平衡。

  • max_fails 是在 fail_duration 內需要失敗請求的最大次數,然後才能將後端視為關閉;必須 >= 1;預設值為 1

  • unhealthy_status 在回應傳回以下其中一個狀態碼時,將請求計為失敗。可以是 3 位數的狀態碼或以 xx 結尾的狀態碼類別,例如:4045xx

  • unhealthy_latency 是一個持續時間值,如果請求花費這麼長時間才能獲得回應,則將請求計為失敗。

  • unhealthy_request_count 是在將後端標記為關閉之前允許的同時請求後端的數量。換句話說,如果特定後端目前正在處理這麼多請求,則會將其視為「過載」,並且將優先使用其他後端。

    這應該是一個相當大的數字;配置此數字意味著代理將限制為 unhealthy_request_count × upstreams_count 個總同時請求,並且該點之後的任何請求都會因沒有可用的上游而導致錯誤。

事件

當上游從健康狀態轉換為不健康狀態或反之亦然時,事件會發出。這些事件可用於觸發其他操作,例如發送通知或記錄訊息。事件如下

  • healthy 在上游從先前的不健康狀態標記為健康狀態時發出
  • unhealthy 在上游從先前的健康狀態標記為不健康狀態時發出

在這兩種情況下,host 都作為事件中的元數據包含在內,以識別已變更狀態的上游。它可以與 exec 事件處理程序一起用作 {event.data.host} 的佔位符,例如。

串流

預設情況下,代理會部分緩衝回應以提高線路效率。

代理也支援 WebSocket 連線,執行 HTTP 升級請求,然後將連線轉換為雙向通道。

  • flush_interval 是一個持續時間值,用於調整 Caddy 應多久將回應緩衝區刷新到用戶端。預設情況下,不執行定期刷新。負值(通常為 -1)表示「低延遲模式」,該模式會完全禁用回應緩衝,並在每次寫入用戶端後立即刷新,即使用戶端提前斷開連線,也不會取消對後端的請求。如果回應符合以下條件之一,則會忽略此選項,並立即將回應刷新到用戶端:

    • Content-Type: text/event-stream
    • Content-Length 未知
    • 代理兩側的 HTTP/2,Content-Length 未知,且 Accept-Encoding 未設定或為「identity」
  • request_buffers 將導致代理從請求本文中讀取最多 <size> 位元組數量的資料到緩衝區,然後再將其發送到上游。這非常低效,僅當上游需要無延遲地讀取請求本文時才應執行此操作(上游應用程式應修正此問題)。這接受 go-humanize 支援的所有大小格式。

  • response_buffers 將導致代理從回應本文中讀取最多 <size> 位元組數量的資料,以讀取到緩衝區,然後再傳回給用戶端。出於效能原因,應盡可能避免這樣做,但如果後端的記憶體限制更嚴格,則可能會很有用。這接受 go-humanize 支援的所有大小格式。

  • stream_timeout 是一個持續時間值,在此時間之後,串流請求(例如 WebSocket)將在逾時結束時被強制關閉。如果連線保持開啟時間過長,這實際上會取消連線。一個合理的起點可能是 24h,以剔除超過一天的連線。預設值:無逾時。

  • stream_close_delay 是一個持續時間值,用於延遲在卸載配置時強制關閉串流請求(例如 WebSocket);相反,串流將保持開啟狀態,直到延遲完成。換句話說,啟用此功能可防止在重新載入 Caddy 的配置時立即關閉串流。啟用此功能可能是避免重新連線用戶端的雷鳴般蜂擁而至的好方法,這些用戶端的連線已由先前的配置關閉關閉。一個合理的起點可能是 5m 左右,以允許用戶在重新載入配置後有 5 分鐘的時間自然離開頁面。預設值:無延遲。

標頭

代理可以操作標頭自身與後端之間

  • header_up 設定、新增(帶 + 前綴)、刪除(帶 - 前綴)或在傳輸到後端的請求標頭中執行替換(透過使用兩個引數:搜尋和替換)。

  • header_down 設定、新增(帶 + 前綴)、刪除(帶 - 前綴)或在從後端傳輸的回應標頭中執行替換(透過使用兩個引數:搜尋和替換)。

例如,設定請求標頭,覆寫任何現有值

header_up Some-Header "the value"

新增回應標頭;請注意,標頭欄位可以有多個值

header_down +Some-Header "first value"
header_down +Some-Header "second value"

刪除請求標頭,防止其到達後端

header_up -Some-Header

刪除所有匹配的請求標頭,使用後綴匹配

header_up -Some-*

刪除所有請求標頭,以便能夠單獨新增您想要的標頭(不建議)

header_up -*

對請求標頭執行正則表達式替換

header_up Some-Header "^prefix-([A-Za-z0-9]*)$" "replaced-$1-suffix"

使用的正則表達式語言是 RE2,包含在 Go 中。請參閱 RE2 語法參考Go regexp 語法概述。替換字串已擴展,允許使用捕獲的值,例如 $1 是第一個捕獲群組。

預設值

預設情況下,Caddy 會將傳入的標頭(包括 Host)傳遞到後端,而不會進行修改,但有三個例外

對於這些 X-Forwarded-* 標頭,預設情況下,代理將忽略來自傳入請求的值,以防止詐騙。

如果 Caddy 不是用戶端連線的第一個伺服器(例如,當 CDN 位於 Caddy 前面時),您可以將 trusted_proxies 配置為 IP 範圍 (CIDR) 列表,傳入的請求從這些範圍信任已為這些標頭發送了良好的值。

強烈建議您透過 servers > trusted_proxies 全域選項而不是在代理中配置此選項,以便此選項適用於伺服器中的所有代理處理程序,並且這具有啟用用戶端 IP 解析的優點。

此外,當使用 http 傳輸時,如果用戶端請求中缺少 Accept-Encoding: gzip 標頭,則會設定該標頭。如果上游可以,這允許上游提供壓縮內容。可以使用傳輸上的 compression off 禁用此行為。

HTTPS

由於(大多數)標頭在被代理時會保留其原始值,因此在代理到 HTTPS 時,通常需要使用配置的上游位址覆寫 Host 標頭,以使 Host 標頭與 TLS ServerName 值匹配

reverse_proxy https://example.com {
	header_up Host {upstream_hostport}
}

X-Forwarded-Host 標頭預設情況下仍然會傳遞,因此如果上游需要知道原始 Host 標頭值,則仍然可以使用該標頭。

重寫

預設情況下,Caddy 使用與傳入請求相同的 HTTP 方法和 URI 執行上游請求,除非在到達 reverse_proxy 之前的中介軟體鏈中執行了重寫。

在代理之前,請求會被複製;這確保在處理程序期間對請求所做的任何修改不會洩漏到其他處理程序。這在需要在代理之後繼續處理的情況下很有用。

除了標頭操作之外,請求的方法和 URI 可能會在發送到上游之前變更

  • method 變更複製請求的 HTTP 方法。如果將方法變更為 GETHEAD,則此處理程序不會將傳入請求的本文發送到上游。如果您希望允許不同的處理程序使用請求本文,這很有用。
  • rewrite 變更複製請求的 URI(路徑和查詢)。這與 rewrite 指令類似,不同之處在於它不會將重寫保留在此處理程序的範圍之外。

這些重寫通常適用於「預先檢查請求」之類的模式,在這種模式下,請求會發送到另一個伺服器,以協助決定如何繼續處理當前請求。

例如,可以將請求發送到身分驗證閘道,以決定請求是否來自已驗證的使用者(例如,請求具有會話 Cookie)並且應繼續,還是應重新導向到登入頁面。對於此模式,Caddy 提供了一個快捷指令 forward_auth,以跳過大多數配置樣板。

傳輸

Caddy 的代理傳輸是可插拔的

  • transport 定義如何與後端通訊。預設值為 http

`http` 傳輸

transport http {
	read_buffer             <size>
	write_buffer            <size>
	max_response_header     <size>
	proxy_protocol          v1|v2
	dial_timeout            <duration>
	dial_fallback_delay     <duration>
	response_header_timeout <duration>
	expect_continue_timeout <duration>
	resolvers <ip...>
	tls
	tls_client_auth <automate_name> | <cert_file> <key_file>
	tls_insecure_skip_verify
	tls_curves <curves...>
	tls_timeout <duration>
	tls_trust_pool <module>
	tls_server_name <server_name>
	tls_renegotiation <level>
	tls_except_ports <ports...>
	keepalive [off|<duration>]
	keepalive_interval <interval>
	keepalive_idle_conns <max_count>
	keepalive_idle_conns_per_host <count>
	versions <versions...>
	compression off
	max_conns_per_host <count>
	forward_proxy_url <url>
}
  • read_buffer 是讀取緩衝區的大小(以位元組為單位)。它接受 go-humanize 支援的所有格式。預設值:4KiB

  • write_buffer 是寫入緩衝區的大小(以位元組為單位)。它接受 go-humanize 支援的所有格式。預設值:4KiB

  • max_response_header 是要從回應標頭讀取的最大位元組數。它接受 go-humanize 支援的所有格式。預設值:10MiB

  • proxy_protocol 在與上游的連線上啟用 PROXY 協定(由 HAProxy 推廣),並在前面加上真實用戶端 IP 資料。如果 Caddy 位於另一個代理後面,則最好與 servers > trusted_proxies 全域選項配對。支援 v1v2 版本。僅當您知道上游伺服器能夠解析 PROXY 協定時才應使用此選項。預設情況下,此選項已禁用。

  • dial_timeout 是連線到上游套接字時要等待的最大持續時間。預設值:3s

  • dial_fallback_delay 是在產生 RFC 6555 快速回退連線之前要等待的最大持續時間。負值會禁用此功能。預設值:300ms

  • response_header_timeout 是要等待從上游讀取回應標頭的最大持續時間。預設值:無逾時。

  • expect_continue_timeout 是在完全寫入請求標頭後,如果請求具有標頭 Expect: 100-continue,則要等待上游的第一個回應標頭的最大持續時間。預設值:無逾時。

  • read_timeout 是要等待從後端進行下一次讀取的最大持續時間。預設值:無逾時。

  • write_timeout 是要等待下一次寫入後端的最大持續時間。預設值:無逾時。

  • resolvers 是要覆寫系統解析器的 DNS 解析器列表。

  • tls 將 HTTPS 與後端一起使用。如果您使用 https:// 協定或埠 :443 指定後端,或者如果配置了以下任何 tls_* 選項,則將自動啟用此功能。

  • tls_client_auth 啟用 TLS 用戶端驗證,有兩種方式:(1) 指定 Caddy 應取得憑證並保持續訂的網域名稱,或 (2) 指定憑證和金鑰檔案,以便與後端進行 TLS 用戶端驗證。

  • tls_insecure_skip_verify 關閉 TLS 握手驗證,使連線變得不安全,容易受到中間人攻擊。請勿在生產環境中使用。

  • tls_curves 是用於上游連線的橢圓曲線支援列表。Caddy 的預設設定是現代且安全的,因此只有在您有特定需求時才需要設定此選項。

  • tls_timeout 是等待 TLS 握手完成的最長持續時間。預設值:無逾時。

  • tls_trust_pool 設定信任憑證授權單位的來源,類似於 tls 指令文件中描述的 trust_pool 子指令。標準 Caddy 安裝中可用的信任池來源列表,請參閱此處

  • tls_server_name 設定在驗證 TLS 握手中收到的憑證時使用的伺服器名稱。預設情況下,這將使用上游位址的主機部分。

    只有在上游位址與上游可能使用的憑證不符時,才需要覆寫此設定。例如,如果上游位址是 IP 位址,則您需要將此設定為上游伺服器正在服務的主機名稱。

    可以使用請求佔位符。在這種情況下,每個請求都會使用 HTTP 傳輸配置的副本,這可能會導致效能損失。

  • tls_renegotiation 設定 TLS 重新協商層級。TLS 重新協商是指在第一次握手之後執行後續握手的行為。層級可以是以下之一:

    • never (預設值) 停用重新協商。
    • once 允許遠端伺服器每個連線請求重新協商一次。
    • freely 允許遠端伺服器重複請求重新協商。
  • tls_except_ports 當 TLS 啟用時,如果上游目標使用給定的其中一個埠,則這些連線將停用 TLS。當設定動態上游時,這可能很有用,因為某些上游預期 HTTP 請求,而其他上游預期 HTTPS 請求。

  • keepalive 可以是 off持續時間值,用於指定保持連線開啟的時間(逾時)。預設值:2m

  • keepalive_interval 是活動探測之間的持續時間。預設值:30s

  • keepalive_idle_conns 定義要保持活動連線的最大數量。預設值:無限制。

  • keepalive_idle_conns_per_host 如果為非零值,則控制每個主機要保持的最大閒置(保持活動)連線數。預設值:32

  • versions 允許自訂要支援的 HTTP 版本。

    有效選項為:1.12h2c3

    預設值:1.1 2,或者如果上游的 schemeh2c://,則預設值為 h2c 2

    h2c 啟用與上游的明文 HTTP/2 連線。這是一個非標準功能,不使用 Go 的預設 HTTP 傳輸,因此與其他功能互斥。

    3 啟用與上游的 HTTP/3 連線。⚠️ 這是一個實驗性功能,可能會有所變更。

  • compression 可以用於停用與後端的壓縮,方法是將其設定為 off

  • max_conns_per_host 可選地限制每個主機的連線總數,包括撥號中、活動中和閒置狀態的連線。預設值:無限制。

  • forward_proxy_url 指定伺服器的 URL,HTTP 傳輸將使用該伺服器將請求代理到上游伺服器。預設情況下,Caddy 會遵循透過環境變數設定的代理,如 Go stdlibHTTP_PROXY 的設定。當為此參數提供值時,請求將按以下順序流經反向代理:

    • 用戶端(使用者)🡒 reverse_proxy 🡒 forward_proxy_url 🡒 上游

`fastcgi` 傳輸

transport fastcgi {
	root  <path>
	split <at>
	env   <key> <value>
	resolve_root_symlink
	dial_timeout  <duration>
	read_timeout  <duration>
	write_timeout <duration>
	capture_stderr
}
  • root 是站點的根目錄。預設值:{http.vars.root} 或當前工作目錄。

  • split 是分割路徑以在 URI 結尾取得 PATH_INFO 的位置。

  • env 將額外的環境變數設定為給定的值。可以多次指定以設定多個環境變數。

  • resolve_root_symlink 啟用透過評估符號連結(如果存在)將 root 目錄解析為其實際值。

  • dial_timeout 是連線到上游 socket 時的等待時間。接受持續時間值。預設值:3s

  • read_timeout 是從 FastCGI 伺服器讀取時的等待時間。接受持續時間值。預設值:無逾時。

  • write_timeout 是傳送到 FastCGI 伺服器時的等待時間。接受持續時間值。預設值:無逾時。

  • capture_stderr 啟用捕獲和記錄上游 fastcgi 伺服器在 stderr 上傳送的任何訊息。預設情況下,記錄在 WARN 層級完成。如果回應具有 4xx5xx 狀態,則將改為使用 ERROR 層級。預設情況下,stderr 會被忽略。

攔截回應

可以將反向代理設定為攔截來自後端的回應。為了方便起見,可以定義回應匹配器(類似於請求匹配器的語法),並且將調用第一個匹配的 handle_response 路由。

當調用回應處理常式時,來自後端的回應不會寫入用戶端,而是會執行設定的 handle_response 路由,並且由該路由來寫入回應。如果路由沒有寫入回應,則請求處理將繼續執行任何 在此 reverse_proxy 之後排序的處理常式。

  • @name回應匹配器的名稱。只要每個回應匹配器都有唯一的名稱,就可以定義多個匹配器。可以根據狀態碼和回應標頭的存在或值來匹配回應。

  • replace_status 僅僅在給定的匹配器匹配時變更回應的狀態碼。

  • handle_response 定義在給定的匹配器匹配時(或者,如果省略匹配器,則為所有回應)要執行的路由。將套用第一個匹配的區塊。在 handle_response 區塊內,可以使用任何其他 指令

此外,在 handle_response 內,可以使用兩個特殊的處理常式指令

  • copy_response 將從後端收到的回應正文複製回用戶端。可選地允許在執行此操作時變更回應的狀態碼。此指令的排序在 respond 之前

  • copy_response_headers 將回應標頭從後端複製到用戶端,可選地包含排除標頭欄位列表(不能同時指定 includeexclude)。此指令的排序在 header 之後

將在 handle_response 路由中提供三個佔位符

  • {rp.status_code} 來自後端回應的狀態碼。

  • {rp.status_text} 來自後端回應的狀態文字。

  • {rp.header.*} 來自後端回應的標頭。

範例

將所有請求反向代理到本地後端

example.com {
	reverse_proxy localhost:9005
}

負載平衡所有請求在 3 個後端之間

example.com {
	reverse_proxy node1:80 node2:80 node3:80
}

相同,但僅限於 /api 內的請求,並使用 cookie 策略保持黏性

example.com {
	reverse_proxy /api/* node1:80 node2:80 node3:80 {
		lb_policy cookie api_sticky
	}
}

使用主動健康檢查來確定哪些後端是健康的,並啟用重試失敗的連線,將請求保留到找到健康的後端為止

example.com {
	reverse_proxy node1:80 node2:80 node3:80 {
		health_uri /healthz
		lb_try_duration 5s
	}
}

設定一些傳輸選項

example.com {
	reverse_proxy localhost:8080 {
		transport http {
			dial_timeout 2s
			response_header_timeout 30s
		}
	}
}

反向代理到 HTTPS 上游

example.com {
	reverse_proxy https://example.com {
		header_up Host {upstream_hostport}
	}
}

反向代理到 HTTPS 上游,但 ⚠️ 停用 TLS 驗證。不建議這樣做,因為它會停用 HTTPS 提供的所有安全檢查;如果可能,最好在私有網路中透過 HTTP 代理,因為它可以避免錯誤的安全感

example.com {
	reverse_proxy 10.0.0.1:443 {
		transport http {
			tls_insecure_skip_verify
		}
	}
}

相反,您可以透過顯式信任上游的憑證來建立與上游的信任,並且(可選)設定 TLS-SNI 以匹配上游憑證中的主機名稱

example.com {
	reverse_proxy 10.0.0.1:443 {
		transport http {
			tls_trusted_ca_certs /path/to/cert.pem
			tls_server_name app.example.com
		}
	}
}

剝離路徑前綴,然後進行代理;但請注意子資料夾問題

example.com {
	handle_path /prefix/* {
		reverse_proxy localhost:9000
	}
}

使用 rewrite 在代理之前替換路徑前綴

example.com {
	handle_path /old-prefix/* {
		rewrite * /new-prefix{path}
		reverse_proxy localhost:9000
	}
}

X-Accel-Redirect 支援,即透過攔截回應來提供請求的靜態檔案

example.com {
	reverse_proxy localhost:8080 {
		@accel header X-Accel-Redirect *
		handle_response @accel {
			root    * /path/to/private/files
			rewrite * {rp.header.X-Accel-Redirect}
			method  * GET
			file_server
		}
	}
}

來自上游的錯誤的自訂錯誤頁面,透過按狀態碼攔截錯誤回應

example.com {
	reverse_proxy localhost:8080 {
		@error status 500 503
		handle_response @error {
			root    * /path/to/error/pages
			rewrite * /{rp.status_code}.html
			file_server
		}
	}
}

A/AAAA 記錄 DNS 查詢中動態取得後端

example.com {
	reverse_proxy {
		dynamic a example.com 9000
	}
}

SRV 記錄 DNS 查詢中動態取得後端

example.com {
	reverse_proxy {
		dynamic srv _api._tcp.example.com
	}
}

在建立中間服務以執行更徹底的健康檢查時,使用主動健康檢查health_upstream 可能很有幫助。然後,可以使用 {http.reverse_proxy.active.target_upstream} 作為標頭,將原始上游提供給健康檢查服務。

example.com {
	reverse_proxy node1:80 node2:80 node3:80 {
		health_uri /health
		health_upstream 127.0.0.1:53336
		health_headers {
			Full-Upstream {http.reverse_proxy.active.target_upstream}
		}
	}
}