Configure > Proxy Directives
Proxy module is the proxy implementation for H2O - it implements a reverse HTTP proxy and a CONNECT proxy.
A reverse HTTP proxy is setup using the proxy.reverse.url
directive.
A CONNECT proxy is setup using the proxy.connect
directive.
When acting as a reverse HTTP proxy, following request headers are added and forwarded to the backend server:
By default, all requests to the backend server are sent using HTTP/1.1.
Use of HTTP/2 and HTTP/3 to backend servers is considered experimental; their use can be controlled via directives proxy.http2.ratio
and proxy.http3.ratio
.
Following sections describe the configuration directives defined for the module.
-
proxy.reverse.url
-
proxy.connect
-
proxy.connect.emit-proxy-status
-
proxy.emit-x-forwarded-headers
-
proxy.emit-via-header
-
proxy.emit-missing-date-header
-
proxy.forward.close-connection
-
proxy.happy-eyeballs.connection-attempt-delay
-
proxy.happy-eyeballs.name-resolution-delay
-
proxy.header.add
-
proxy.header.append
-
proxy.header.merge
-
proxy.header.set
-
proxy.header.setifempty
-
proxy.header.unset
-
proxy.header.unsetunless
-
proxy.header.cookie.unset
-
proxy.header.cookie.unsetunless
-
proxy.http2.force-cleartext
-
proxy.http2.max-concurrent-streams
-
proxy.http2.ratio
-
proxy.http3.ratio
-
proxy.max-buffer-size
-
proxy.preserve-host
-
proxy.preserve-x-forwarded-proto
-
proxy.proxy-protocol
-
proxy.proxy-status.identity
-
proxy.ssl.cafile
-
proxy.ssl.session-cache
-
proxy.ssl.verify-peer
-
proxy.timeout.connect
-
proxy.timeout.first_byte
-
proxy.timeout.io
-
proxy.timeout.keepalive
-
proxy.tunnel
-
proxy.zerocopy
- Description:
-
Forwards the requests to the specified backends, and proxies the response.
proxy.reverse.url: "http://127.0.0.1:8080/"
proxy.reverse.url: - http://10.0.0.1:8080/ - url: http://10.0.0.2:8080/different-path weight: 2
proxy.reverse.url: backends: - http://10.0.0.1:8080/ - http://10.0.0.2:8080/ balancer: least-conn
When more than one backend is declared, the load is distributed among the backends using the strategy specified by the
balancer
property. Currently we supportround-robin
(the default) andleast-conn
as the value of the property. The strategies are applied when establishing a new connection becomes necessary (i.e. when no pooled connections exist).weight
can be assigned to each backend as an integer between 1 and 256. The default value is 1.For the
round-robin
balancer,weight
is respected in this way: each backend would be selected exactlyweight
times before next backend would be selected, except when the backend is not accessable.For
least-conn
balancer,weight
is respected in this way: the selected backend should have the minimum value of (request count) / (weight
).H2O will try to reconnect to different backends (in the order determined by the load balancing strategy) until it successfully establishes a connection. It returns an error when it fails to connect to all of the backends.
In addition to TCP/IP over IPv4 and IPv6, the proxy handler can also connect to an HTTP server listening to a Unix socket. Path to the unix socket should be surrounded by square brackets, and prefixed with
unix:
(e.g.http://[unix:/path/to/socket]/path
). - Level:
- path
"proxy.connect"
- Description:
-
Setup a CONNECT proxy, taking an access control list as the argument.
Each element of the access control list starts with either
+
or-
followed by an wildcard (*
) or an IP address with an optional netmask and an optional port number.When a CONNECT request is received and the name resolution of the connect target is complete, the access control list is searched from top to bottom. If the first entry that contains a matching address (and optionally the port number) starts with a
+
, the request is accepted and a tunnel is established. If the entry starts with a-
, the request is rejected.If none of the entries match, the request is also rejected.
proxy.connect: - "-192.168.0.0/24" # reject any attempts to local network - "+*:443" # accept attempts to port 443 of any host
Note: The precise syntax of the access control list element is
address:port/netmask
. This is because the URL parser is reused. - Level:
- path
- Description:
-
A boolean flag (
ON
orOFF
) designating if a proxy-status response header should be sent. - Level:
- global, host, path, extension
- Default:
proxy.connect.emit-proxy-status: OFF
- See also:
proxy.proxy-status.identity
"proxy.emit-x-forwarded-headers"
- Description:
-
A boolean flag(
ON
orOFF
) indicating if the server will append or add thex-forwarded-proto
andx-forwarded-for
request headers.By default, when forwarding an HTTP request H2O sends its own
x-forwarded-proto
andx-forwarded-for
request headers (or might append its value in thex-forwarded-proto
case, seeproxy.preserve-x-forwarded-proto
). This might not be always desirable. Please keep in mind security implications when setting this ofOFF
, since it might allow an attacker to spoof the originator or the protocol of a request. - Level:
- global
- Default:
proxy.emit-x-forwarded-headers: ON
- See also:
proxy.emit-via-header
"proxy.emit-via-header"
- Description:
-
A boolean flag (
ON
orOFF
) indicating if the server adds or appends an entry to thevia
request header. - Level:
- global
- Default:
proxy.emit-via-header: ON
- See also:
proxy.emit-x-forwarded-headers
"proxy.emit-missing-date-header"
- Description:
-
A boolean flag (
ON
orOFF
) indicating if H2O should add adate
header to the response, if that header is missing from the upstream response. - Level:
- global
- Default:
proxy.emit-missing-date-header: ON
- Description:
-
A boolean flag indicating if closure of the backend connection should trigger the closure of the frontend HTTP/1.1 connection.
- Level:
- global, host, path, extension
- Default:
proxy.forward.close-connection: OFF
- Description:
-
Connection Attempt Delay
parameter of Happy Eyeballs v2.When trying to establish a connection to the CONNECT target, H2O uses Happy Eyeballs v2 (RFC 8305). This parameter controls the
Connection Attempt Delay
parameter of Happy Eyeballs v2 in the unit of milliseconds.At the moment, Happy Eyeballs is used only when acting as a CONNECT proxy. It is not used when running as an HTTP reverse proxy.
- Level:
- global, host, path, extension
- Default:
proxy.happy-eyeballs.connection-attempt-delay: 250
- Description:
-
Name Resolution Delay
parameter of Happy Eyeballs v2.For detail, see proxy.happy-eyeballs.connection-attempt-delay.
- Level:
- global, host, path, extension
- Default:
proxy.happy-eyeballs.name-resolution-delay: 50
"proxy.header.add"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.add
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.append"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.append
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.merge"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.merge
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.set"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.set
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.setifempty"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.setifempty
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.unset"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.unset
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
"proxy.header.unsetunless"
- Description:
-
Modifies the request headers sent to the application server.
The behavior is identical to
header.unsetunless
except for the fact that it affects the request headers sent to the application server rather than the response headers sent to the client. Please refer to the documentation of the headers handler to see how the directives can be used to mangle the headers. - Level:
- global, host, path, extension
- Description:
-
Removes cookies in the requests with given name.
- Level:
- global, host, path, extension
- See also:
header.unset
/a>
- Description:
-
Removes all cookies in the requests but those with given names.
- Level:
- global, host, path, extension
- See also:
header.unsetunless
- Description:
-
See
proxy.http2.ratio
. - Level:
- global, host, path, extension
- Default:
proxy.http2.force-cleartext: OFF
- Description:
-
Maxium number of concurrent requests issuable on one HTTP/2 connection to the backend server.
Actual number of maximum requests inflight will be capped to the minimum of this setting and the value advertised in the HTTP/2 SETTINGS frame of the bakend server.
- Level:
- global, host, path, extension
- Default:
proxy.http2.max-concurrent-streams: 100
- See also:
proxy.http2.ratio
"proxy.http2.ratio"
- Description:
-
Ratio of forwarded HTTP requests with which use of HTTP/2 should be attempted.
When the backend protocol is HTTPS, for given ratio of HTTP requests, h2o will either attempt to create or reuse an existing HTTP/2 connection. Connection attempts to use HTTP/2 will be indicated to the server via ALPN, with fallback to HTTP/1.1.
When the backend protocol is cleartext HTTP, this directive has impact only when the ratio is set to
100
withproxy.http2.force-cleartext
set toON
. In such case, all backend connection will use HTTP/2 without negotiation. - Level:
- global, host, path, extension
- Default:
proxy.http2.ratio: 0
"proxy.http3.ratio"
- Description:
-
Ratio of forwarded HTTP requests with which use of HTTP/3 should be attempted.
When the backend protocol is HTTPS, for given ratio of HTTP requests, h2o will either attempt to create or reuse an existing HTTP/3 connection.
When the backend protocol is cleartext HTTP, this directive has no impact.
- Level:
- global, host, path, extension
- Default:
proxy.http3.ratio: 0
- Description:
-
This setting specifies the maximum amount of userspace memory / disk space used for buffering each HTTP response being forwarded, in the unit of bytes.
By default, h2o buffers unlimited amount of data being sent from backend servers. The intention behind this approach is to free up backend connections as soon as possible, under the assumption that the backend server might have lower concurrency limits than h2o. But if the backend server has enough concurrency,
proxy.max-buffer-size
can be used to restrict the memory / disk pressure caused by h2o at the cost of having more connections to the backend server. - Level:
- global, host, path, extension
- See also:
temp-buffer-threshold
- Description:
-
A boolean flag (
ON
orOFF
) designating whether or not to passHost
header from incoming request to upstream. - Level:
- global, host, path, extension
- Default:
proxy.preserve-host: OFF
"proxy.preserve-x-forwarded-proto"
- Description:
-
A boolean flag(
ON
orOFF
) indicating if the server preserve the receivedx-forwarded-proto
request header.By default, when transmitting a HTTP request to an upstream HTTP server, H2O removes the received
x-forwarded-proto
request header and sends its own, as a precaution measure to prevent an attacker connecting through HTTP to lie that they are connected via HTTPS. However in case H2O is run behind a trusted HTTPS proxy, such protection might not be desirable, and this configuration directive can be used to modify the behaviour. - Level:
- global
- Default:
proxy.preserve-x-forwarded-proto: OFF
"proxy.proxy-protocol"
- Description:
-
A boolean flag (
ON
orOFF
) indicating if PROXY protocol should be used when connecting to the application server.When using the PROXY protocol, connections to the application server cannot be persistent (i.e.
proxy.timeout.keepalive
must be set to zero). - Level:
- global, host, path, extension
- Default:
proxy.proxy-protocol: OFF
- See also:
proxy.timeout.keepalive
- Description:
-
Specifies the name of the server to be emitted as part of the
proxy-status
header field. - Level:
- global, host, path, extension
- See also:
proxy.connect.proxy-status
"proxy.ssl.cafile"
- Description:
-
Specifies the file storing the list of trusted root certificates.
By default, H2O uses
share/h2o/ca-bundle.crt
. The file contains a set of trusted root certificates maintained by Mozilla, downloaded and converted using mk-ca-bundle.pl. - Level:
- global, host, path, extension
- See also:
proxy.ssl.verify-peer
"proxy.ssl.session-cache"
- Description:
-
Specifies whether if and how a session cache should be used for TLS connections to the application server.
Since version 2.1, result of the TLS handshakes to the application server is memoized and later used to resume the connection, unless set to
OFF
using this directive. If the value is a mapping, then the following two attributes must be specified:- lifetime:
- validity of session cache entries in seconds
- capacity:
- maxmum number of entries to be kept in the session cache
ON
,lifetime
andcapacity
will be set to 86,400 (one day) and 4,096. - Level:
- global, host, path, extension
- Default:
proxy.ssl.session-cache: ON
"proxy.ssl.verify-peer"
- Description:
-
A boolean flag (
ON
orOFF
) indicating if the server certificate and hostname should be verified.If set to
ON
, the HTTP client implementation of H2O verifies the peer's certificate using the list of trusted certificates as well as compares the hostname presented in the certificate against the connecting hostname. - Level:
- global, host, path, extension
- Default:
proxy.ssl.verify-peer: ON
- See also:
proxy.ssl.cafile
"proxy.timeout.connect"
- Description:
-
Sets the timeout before establishing the upstream in milliseconds.
When connecting to a TLS upstream, this timeout will run until the end of the SSL handshake.
- Level:
- global, host, path, extension
- Default:
proxy.timeout.connect: 30000
"proxy.timeout.first_byte"
- Description:
-
Sets the timeout before receiving the first byte from upstream.
This sets the maxium time we will wait for the first byte from upstream, after the establishment of the connection.
- Level:
- global, host, path, extension
- Default:
proxy.timeout.first_byte: 30000
- Description:
-
Sets the upstream I/O timeout in milliseconds.
This value will be used for
proxy.timeout.connect
andproxy.timeout.first_byte
as well, unless these parameters are explicitely set. - Level:
- global, host, path, extension
- Default:
proxy.timeout.io: 30000
- Description:
-
Sets the upstream timeout for idle connections in milliseconds.
Upstream connection becomes non-persistent if the value is set to zero. The value should be set to something smaller than that being set at the upstream server.
- Level:
- global, host, path, extension
- Default:
proxy.timeout.keepalive: 2000
"proxy.tunnel"
- Description:
-
A boolean flag (
ON
orOFF
) indicating whether or not to allow tunnelling to the backend server.When set to
ON
, CONNECT requests and WebSocket handshakes are forwarded to the backend server. Then, if the backend server accepts those requests, H2O forwards the HTTP response to the client and acts as a bi-directional tunnel.Timeouts are governed by properties
proxy.timeout.connect
andproxy.timeout.io
. - Level:
- global, host, path, extension
- Default:
proxy.tunnel: OFF
"proxy.zerocopy"
- Description:
-
Sets the use of zerocopy operations for forwarding the response body.
By default, this flag is set to
OFF
, in which case the response bytes are read from the upstream socket to an internal buffer as they arrive, then shipped to the client. Maximum size of this buffer is controlled byproxy.max-buffer-size
. The drawback of this approach is that it causes pressure on memory bandwidth.This knob provides two alternative modes to remedy the pressure:
When set to
enabled
, if zerocopy operation in supported by the downstream connection (i.e., downstream connection being cleoartext or encrypted using kernel TLS), h2o uses a pipe as an internal buffer instead of using userspace memory. Data is moved to the pipe using thesplice
system call, then shipped to the downstream connection by another call tosplice
. Pressure to memory bandwidth is eliminated, as thesplice
system call merely moves the references to kernel memory between file descriptors.When set to
always
, data from upstream is spliced into a pipe regardless of downstream connection providing support for zerocopy. When the downstream connection does not support zerocopy, data is intially moved into the pipe, then gets read and written to the socket (as well as being encrypted, if necessary) as late as it becomes possible to send the data. This approach does not reduce the total amount of bytes flowing through the CPU, but reduces the amount of userspace memory used by h2o by delaying the reads, thereby reducing cache spills. - Level:
- global
- Default:
proxy.zerocopy: OFF
- See also:
ssl-offload