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_method <method> health_status <status> health_request_body <body> 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 network address。有效示例:
localhost:4000127.0.0.1:4000[::1]:4000http://localhost:4000https://example.comh2c://127.0.0.1example.comunix//var/php.sockunix+h2c//var/grpc.socklocalhost:8001-8006[fe80::ea9f:80ff:fe46:cbfd%eth0]:443
默认情况下,通过纯文本 HTTP 与上游建立连接。使用 URL 形式时,可以使用方案来设置一些transport默认值作为简写。
-
使用
https://作为方案将使用http传输并启用tls。此外,您可能需要覆盖
Host标头,使其与 TLS SNI 值匹配,服务器使用该值进行路由和证书选择。请参阅下面的HTTPS部分了解更多详细信息。 -
使用
http://作为方案与省略该方案相同,因为 HTTP 已经是默认值。包含此语法是为了与其他方案快捷方式对称。
方案不能混合,因为它们修改公共传输配置(启用 TLS 的传输不能同时承载 HTTPS 和纯文本 HTTP)。任何显式传输配置都不会被覆盖,并且省略方案或使用其他端口将不会假定特定的传输。
当将 IPv6 与区域(例如,具有特定网络接口的链接本地地址)一起使用时,方案 cannot 用作快捷方式,因为%将导致 URL 解析错误;相反,显式配置传输。
当使用network address形式时,网络类型被指定为上游地址的前缀。这不能与 URL 方案结合使用。作为特殊情况,支持unix+h2c/作为unix/网络的快捷方式,并具有与h2c://方案相同的效果。支持端口范围作为快捷方式,可扩展到具有同一主机的多个上游。
上游地址cannot包含路径或查询字符串,因为这意味着在代理时同时重写请求,而这种行为未定义或支持。如果需要,您可以使用rewrite指令。
如果地址不是 URL(即没有方案),则可以使用placeholders,但这会使上游“动态静态”,这意味着在健康检查和负载均衡方面,可能有许多不同的后端充当单个静态上游。如果可能的话,我们建议使用动态上游模块。使用占位符时,必须包含端口(通过占位符替换或作为地址的静态后缀)。
动态上游
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 是全名的协议组件。
tcp或udp。 - name 是名称组成部分。或者,如果
service和proto为空,则查询完整域名。 - 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。对于涉及哈希的策略,highest-random-weight (HRW)算法用于确保具有相同哈希键的客户端或请求映射到相同的上游,即使上游列表发生变化。
某些策略支持回退作为选项(如果注明),在这种情况下,它们采用block和
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全局选项搭配使用,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_uri或health_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_method是用于主动健康检查的 HTTP 方法。默认:
GET。 -
health_status是健康后端期望的 HTTP 状态代码。可以是 3 位状态代码,或以
xx结尾的状态代码类。例如:200(默认)或2xx。 -
health_request_body是一个字符串,表示与主动健康检查一起发送的请求正文。
-
health_body是匹配主动健康检查的响应正文的子字符串或正则表达式。如果后端没有返回匹配的body,则会被标记为down。
-
health_follow_redirects将导致健康检查遵循上游提供的重定向。默认情况下,重定向响应将导致运行状况检查失败。
-
health_headers允许指定要在活动健康检查请求上设置的标头。如果您需要更改
Host标头,或者需要向后端提供一些身份验证作为健康检查的一部分,这非常有用。
被动健康检查
被动健康检查与实际代理请求一致发生。要启用此功能,需要fail_duration。
-
fail_duration是一个持续时间值,定义了记住失败请求的时间。持续时间 >
0启用被动健康检查;默认为0(关闭)。一个合理的起点可能是30s,以便在将不健康的上游恢复在线时平衡错误率和响应能力;但请随意尝试,为您的用例找到合适的平衡点。 -
max_fails是在考虑后端关闭之前
fail_duration内所需的最大失败请求数;必须 >=1;默认是1。 -
unhealthy_status 如果响应返回时带有这些状态代码之一,则将请求视为失败。可以是 3 位状态代码或以
xx结尾的状态代码类,例如:404或5xx。 -
unhealthy_latency是一个持续时间值,如果需要这么长时间才能获得响应,则将请求视为失败。
-
unhealthy_request_count是在将后端标记为关闭之前允许的并发请求数。换句话说,如果某个特定后端当前正在处理这么多请求,则它被视为“过载”,并且将优先选择其他后端。
这应该是一个相当大的数字;配置此意味着代理将有
unhealthy_request_count × upstreams_count并发请求总数的限制,并且该点之后的任何请求都将由于没有可用的上游而导致错误。
活动
当上游从健康状态转变为不健康状态(反之亦然)时,会发出an event。这些事件可用于触发其他操作,例如发送通知或记录消息。活动详情如下:
- 当上游之前不健康但被标记为健康时,会发出
healthy - 当上游之前健康但被标记为不健康时,会发出
unhealthy
在这两种情况下,host作为元数据包含在事件中,以标识更改状态的上游。例如,它可以用作{event.data.host}和exec事件处理程序的占位符。
流媒体
默认情况下,代理会部分缓冲响应以提高线路效率。
该代理还支持 WebSocket 连接,执行 HTTP 升级请求,然后将连接转换为双向隧道。
-
flush_interval是一个持续时间值,用于调整 Caddy 刷新客户端响应缓冲区的频率。默认情况下,不进行定期刷新。负值(通常为 -1)表示“低延迟模式”,该模式完全禁用响应缓冲并在每次写入客户端后立即刷新,并且即使客户端提前断开连接也不会取消对后端的请求。如果响应满足以下条件之一,则忽略此选项,并且响应会立即刷新到客户端:
Content-Type: text/event-stream-Content-Length未知- 代理双方HTTP/2,
Content-Length未知,Accept-Encoding要么未设置,要么是“身份”
-
request_buffers将导致代理在向上游发送请求正文之前将最多
<size>数量的字节读取到缓冲区中。这是非常低效的,只有在上游需要立即读取请求主体时才应该这样做(这是上游应用程序应该修复的问题)。这接受go-humanize支持的所有大小格式。 -
response_buffers将导致代理从响应正文中读取最多
<size>数量的字节,然后将其读入缓冲区,然后再返回给客户端。出于性能原因,应尽可能避免这种情况,但如果后端具有更严格的内存限制,则这可能很有用。这接受go-humanize支持的所有大小格式。 -
stream_timeout是持续时间值,之后 WebSocket 等流式请求将在超时结束时被强制关闭。如果连接保持打开时间过长,这实际上会取消连接。一个合理的起点可能是
24h来剔除超过一天的连接。默认:无超时。 -
stream_close_delay是一个持续时间值,它会延迟配置卸载时强制关闭 WebSocket 等流式请求;相反,流将保持打开状态,直到延迟完成。换句话说,启用此功能可以防止流在重新加载 Caddy 的配置时立即关闭。启用此功能可能是一个好主意,可以避免大量重新连接因之前的配置关闭而关闭连接的客户端。一个合理的起点可能是像
5m这样的东西,允许用户在配置重新加载后有 5 分钟的时间自然离开页面。默认:无延迟。
标头
代理可以manipulate headers:
-
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-*
要删除_all_请求标头,以便能够单独添加您想要的标头(不推荐):
header_up -*
要对请求标头执行正则表达式替换:
header_up Some-Header "^prefix-([A-Za-z0-9]*)$" "replaced-$1-suffix"
使用的正则表达式语言是 RE2,包含在 Go 中。请参阅RE2 语法参考和Go regexp 语法概述。替换字符串是展开,允许使用捕获的值,例如$1是第一个捕获组。
默认值
默认情况下,Caddy 不加修改地将传入标头(包括Host)传递到后端,但有以下三个例外:
- 它设置或扩充
X-Forwarded-For标头字段。 - 它设置
X-Forwarded-Proto标头字段。 - 它设置
X-Forwarded-Host标头字段。
对于这些X-Forwarded-*标头,默认情况下,代理将忽略传入请求中的值,以防止欺骗。
如果 Caddy 不是您的客户端连接到的第一个服务器(例如,当 CDN 位于 Caddy 前面时),您可以使用 IP 范围 (CIDR) 列表配置trusted_proxies,相信传入请求已为这些标头发送了正确的值。
强烈建议您通过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} }
从 Caddy v2.11.0 开始,这是自动完成的,因此在代理到 HTTPS 时不再需要显式覆盖Host标头。如果您希望退出此行为,您可以将Host标头设置为其原始值(但这很少有意义):
reverse_proxy https://example.com { header_up Host {hostport} }
X-Forwarded-Host标头仍然传递默认情况下,因此如果上游需要知道原始Host标头值,则仍可以使用该标头。
这同样适用于在 caddy 中终止 TLS 并通过 HTTP 进行代理(无论是端口还是 unix 套接字)。事实上,当 caddy 是reverse_proxy的目标时,它本身必须接收正确的 Host。在 unix 套接字情况下,upstream_hostport将是套接字路径,并且必须显式设置主机。
重写
默认情况下,Caddy 使用与传入请求相同的 HTTP 方法和 URI 执行上游请求,除非在到达reverse_proxy之前在中间件链中执行了重写。
在代理之前,请求被克隆;这确保了处理程序期间对请求所做的任何修改都不会泄漏到其他处理程序。这在需要在代理之后继续处理的情况下非常有用。
除了标头操作之外,请求的方法和 URI 在发送到上游之前还可以更改:
- method更改克隆请求的 HTTP 方法。如果该方法更改为
GET或HEAD,则传入请求的正文将不会由此处理程序发送到上游。如果您希望允许不同的处理程序使用请求正文,这非常有用。 - rewrite更改克隆请求的 URI(路径和查询)。这与
rewrite指令类似,只是它不会将重写保留到此处理程序的范围之外。
这些重写通常对于“预检查请求”之类的模式很有用,其中请求被发送到另一台服务器以帮助决定如何继续处理当前请求。
例如,请求可以发送到身份验证网关,以确定该请求是否来自经过身份验证的用户(例如,该请求具有会话 cookie)并应该继续,或者应该重定向到登录页面。对于这种模式,Caddy 提供了一个快捷指令forward_auth来跳过大部分配置样板。
交通
Caddy 的代理 transport 是可插拔的:
- 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> network_proxy <module> }
-
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全局选项配对。支持v1和v2版本。仅当您知道上游服务器能够解析 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://方案指定后端,或者配置了以下任何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 持续时间超过上游服务器的 keepalive 超时,则对 HTTP/1.1 上游的请求可能会因“对等方重置连接”错误而失败。幂等请求将由 Go 的 HTTP 传输重试,但在其他情况下 Caddy 将以状态代码 502 进行响应。
-
keepalive_interval是活跃探针之间的持续时间。默认:
30s。 -
keepalive_idle_conns定义保持活动的最大连接数。默认:无限制。
-
keepalive_idle_conns_per_host如果非零,则控制保持每个主机的最大空闲(保持活动)连接。默认:
32。 -
versions允许自定义支持哪些版本的 HTTP。
有效选项有:
1.1、2、h2c、3。默认:
1.1 2,或者如果上游的 scheme是h2c://,则默认为h2c 2。h2c支持与上游的明文 HTTP/2 连接。这是一个非标准功能,不使用 Go 的默认 HTTP 传输,因此它排除了其他功能。3启用与上游的 HTTP/3 连接。 ⚠️ 这是一项实验性功能,可能会发生变化。 -
compression可用于通过将其设置为
off来禁用对后端的压缩。 -
max_conns_per_host可选择限制每个主机的连接总数,包括处于拨号、活动和空闲状态的连接。默认:无限制。
-
network_proxy指定用于向上游服务器发出请求的网络代理模块的名称。如果未明确配置,Caddy 会按照Go 标准库尊重通过环境变量配置的代理,即
HTTP_PROXY、HTTPS_PROXY和NO_PROXY。当为此参数提供值时,请求将按以下顺序流经反向代理:客户端(用户)→reverse_proxy→network_proxy→ 上游。内置模块有: -none,用于忽略HTTP_PROXY、HTTPS_PROXY、NO_PROXY的环境设置。 -url <url>,用于指定覆盖环境配置的单个 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是连接到上游套接字时等待的时间。接受持续时间值。默认:
3s。 -
read_timeout是从 FastCGI 服务器读取时等待的时间。接受持续时间值。默认:无超时。
-
write_timeout是发送到FastCGI 服务器时等待的时间。接受持续时间值。默认:无超时。
-
capture_stderr可以捕获并记录上游 fastcgi 服务器在
stderr上发送的任何消息。默认情况下,日志记录在WARN级别完成。如果响应具有4xx或5xx状态,则将使用ERROR级别。默认情况下,stderr被忽略。
拦截响应
反向代理可以配置为拦截来自后端的响应。为了实现这一点,可以定义响应匹配器(类似于请求匹配器的语法),并且将调用第一个匹配的handle_response路由。
当调用响应处理程序时,来自后端的响应不会写入客户端,而是会执行配置的handle_response路由,并由该路由来写入响应。如果路由确实_不_写入响应,则请求处理将继续使用排序在其后此reverse_proxy的任何处理程序。
-
@name 是响应匹配器的名称。只要每个响应匹配器都有唯一的名称,就可以定义多个匹配器。响应可以根据状态代码和响应标头的存在或值进行匹配。
-
replace_status在与给定匹配器匹配时仅更改响应的状态代码。
-
handle_response定义当与给定匹配器匹配时执行的路由(或者,如果省略匹配器,则所有响应)。将应用第一个匹配块。在
handle_response块内,可以使用任何其他directives。
此外,在handle_response内部,可以使用两个特殊的处理程序指令:
-
copy_response将从后端收到的响应正文复制回客户端。执行此操作时,可以选择允许更改响应的状态代码。该指令是排序在
respond之前。 -
copy_response_headers将响应标头从后端复制到客户端,可选地包含 或 排除标头字段列表(不能同时指定
include和exclude)。该指令是排序在header之后。
handle_response路由中将提供三个占位符:
-{rp.status_code}后端响应的状态码。
-{rp.status_text}后端响应的状态文本。
-{rp.header.*}后端响应的标头。
虽然反向代理响应处理程序可以将从代理接收到的新响应复制回客户端,但它无法将该新响应传递给后续反向代理。每次使用reverse_proxy都会收到原始请求(或使用不同模块修改的)的正文。
示例
将所有请求反向代理到本地后端:
example.com { reverse_proxy localhost:9005 }
Load-balance所有请求between 3 backends:
example.com { reverse_proxy node1:80 node2:80 node3:80 }
相同,但仅限/api内的请求,并使用cookie policy进行粘性:
example.com { reverse_proxy /api/* node1:80 node2:80 node3:80 { lb_policy cookie api_sticky } }
使用active health checks来确定哪些后端是健康的,并在连接失败时启用retries,保留请求直到找到健康的后端:
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 upstream(从 v2.11.0 开始,Caddy 会自动设置Host标头以匹配上游主机,因此不再需要手动执行此操作):
example.com { reverse_proxy https://example.com }
反向代理到 HTTPS 上游,但⚠️ disable TLS verification。不建议这样做,因为它会禁用 HTTPS 提供的所有安全检查;如果可能的话,首选在专用网络中通过 HTTP 进行代理,因为它避免了错误的安全感:
example.com { reverse_proxy 10.0.0.1:443 { transport http { tls_insecure_skip_verify } } }
相反,您可以通过显式trusting the upstream's certificate与上游建立信任,并(可选)设置 TLS-SNI 以匹配上游证书中的主机名:
example.com { reverse_proxy 10.0.0.1:443 { transport http { tls_trust_pool file /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支持,即按请求提供静态文件,通过intercepting the response:
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 } } }
来自上游的错误的自定义错误页面,由intercepting error responses通过状态代码:
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 recordDNS 查询中获取后端dynamically:
example.com { reverse_proxy { dynamic a example.com 9000 } }
从SRV recordDNS 查询中获取后端dynamically:
example.com { reverse_proxy { dynamic srv _api._tcp.example.com } }
在创建中间服务以进行更彻底的健康检查时,使用active health checks和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} } } }