文档
一个 项目

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_port     <port>
	health_interval <interval>
	health_timeout  <duration>
	health_status   <status>
	health_body     <regexp>
	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
  • 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

默认情况下,连接通过明文 HTTP 建立到上游。使用 URL 形式时,可以使用方案来设置一些transport 默认值作为简写。

  • 使用https://作为方案将使用http传输并启用tls

    此外,您可能需要覆盖Host标头,使其与 TLS SNI 值匹配,该值由服务器用于路由和证书选择。有关更多详细信息,请参见下面的HTTPS部分。

  • 使用h2c://作为方案将使用http传输并将HTTP 版本设置为允许明文 HTTP/2 连接。

  • 使用http://作为方案与省略方案相同,因为 HTTP 已经是默认方案。此语法包含在内是为了与其他方案快捷方式对称。

方案不能混合使用,因为它们会修改公共传输配置(启用 TLS 的传输不能同时承载 HTTPS 和明文 HTTP)。任何显式传输配置都不会被覆盖,省略方案或使用其他端口不会假设特定的传输。

使用网络地址形式时,网络类型指定为上游地址的前缀。这不能与 URL 方案结合使用。作为特例,unix+h2c/作为unix/网络的快捷方式受支持,并具有与h2c://方案相同的效果。端口范围作为快捷方式受支持,它扩展为具有相同主机的多个上游。

上游地址不能包含路径或查询字符串,因为这将意味着在代理时同时重写请求,这种行为未定义或不受支持。如果您需要此功能,可以使用rewrite指令。

如果地址不是 URL(即没有方案),则可以使用占位符,但这会使上游动态静态,这意味着可能许多不同的后端在健康检查和负载均衡方面充当单个静态上游。我们建议尽可能使用动态上游模块。使用占位符时,必须包含端口(通过占位符替换或作为地址的静态后缀)。

动态上游

Caddy 的反向代理附带一些动态上游模块。请注意,使用动态上游会对负载均衡和健康检查产生影响,具体取决于特定策略配置:动态上游不会运行主动健康检查;负载均衡和被动健康检查最好在 upstream 列表相对稳定且一致的情况下使用(尤其是使用轮询)。理想情况下,动态上游模块只返回健康、可用的后端。

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 是名称组件。或者,如果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。仅在对上游主机的请求失败时才相关。请注意,如果所有后端都关闭并且延迟非常低,将此设置为 0lb_try_duration 不为零会导致 CPU 旋转。

  • lb_retry_match 限制了允许重试哪些请求。请求必须匹配此条件才能在连接到上游成功但后续往返失败的情况下重试。如果连接到上游失败,则始终允许重试。默认情况下,仅重试 GET 请求。

    此选项的语法与 命名请求匹配器 相同,但没有 @name。如果您只需要一个匹配器,则可以在同一行上配置它。对于多个匹配器,需要一个块。

主动健康检查

主动健康检查在计时器上后台执行健康检查。要启用此功能,需要 health_urihealth_port

  • health_uri 是主动健康检查的 URI 路径(和可选查询)。

  • health_port 是主动健康检查要使用的端口,如果与上游的端口不同。

  • health_interval 是一个 持续时间值,它定义了执行主动健康检查的频率。默认值:30s

  • health_timeout 是一个 持续时间值,它定义了在将后端标记为关闭之前等待回复的时间。默认值:5s

  • health_status 是期望从健康后端获得的 HTTP 状态代码。可以是 3 位状态代码,也可以是状态代码类,以 xx 结尾。例如:200(这是默认值)或 2xx

  • health_body 是要在主动健康检查的响应正文中匹配的子字符串或正则表达式。如果后端没有返回匹配的正文,它将被标记为关闭。

  • 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 正则表达式语法概述。替换字符串是 扩展的,允许使用捕获的值,例如 $1 是第一个捕获组。

默认值

默认情况下,Caddy 会将传入的标头(包括 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}
}

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_timeout <duration>
	tls_trusted_ca_certs <pem_files...>
	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>
}
  • 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_timeout 是TLS握手完成等待的最大持续时间。默认值:无超时。

  • tls_trusted_ca_certs 是指定CA公钥的PEM文件列表,这些公钥在连接到后端时应受信任。

  • 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版本。作为特殊情况,“h2c”是一个有效值,它将启用与上游的明文HTTP/2连接(但是,这是一个非标准功能,它不使用Go的默认HTTP传输,因此它排除了其他功能;可能会更改或删除)。默认值:1.1 2,或者如果方案是h2c://,则为h2c 2

  • compression 可用于通过将其设置为off来禁用对后端的压缩。

  • max_conns_per_host 可以选择限制每个主机的连接总数,包括处于拨号、活动和空闲状态的连接。默认值:无限制。

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级别进行。如果响应具有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.*}来自后端响应的头。

响应匹配器

响应匹配器可用于根据特定条件过滤(或分类)响应。

status
status <code...>

按HTTP状态码。

  • <code...>是HTTP状态码列表。特殊情况是字符串,例如2xx3xx,它们分别与200-299300-399范围内的所有状态码匹配。

有关支持的语法,请参阅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
	}
}