Configuring Envoy proxy deployments
Last updated 2023-03-29
IMPORTANT
This guide only applies to Next-Gen WAF customers with access to the Next-Gen WAF control panel. If you have access to the Next-Gen WAF product in the Fastly control panel, you can only deploy the Next-Gen WAF with the Edge WAF deployment method.
Support is available for the Envoy Proxy via builtin Envoy gRPC APIs implemented in the sigsci-agent
running as a gRPC server. Envoy v1.11.0 or later is recommended, however, Envoy v1.8.0 or later is supported with limited functionality as noted in the documentation below.
Envoy (as of v1.11) does not support a bidirectional gRPC API for inspecting traffic. There are instead two separate gRPC APIs available to inspect traffic. The External Authorization HTTP filter (envoy.ext_authz
) gRPC API allows the request to be held while waiting inbound request inspection, which allows for a request to be blocked if required. An additional gRPC AccessLog Service gRPC API can then be used to inspect the outbound request data. Using these two APIs together with the sigsci-agent
running as a gRPC server allows for inspection in both directions using only Envoy builtin APIs. This allows web application inspection without installing a module for every upstream application. In this case the sigsci-agent
is acting as the module.
Request allowed (normal) processing
This is the flow for normal requests that the sigsci-agent
allows through Envoy.
- Client request received by Envoy and routed to the Envoy
External Authorization (ext_authz)
HTTP filter where request metadata is extracted for processing via thesigsci-agent
. - Request metadata is sent to the
sigsci-agent
via gRPCext_authz
API - The
sigsci-agent
sends back an 'allow request' response allowing the request through theext_authz
HTTP filter to continue normal Envoy request processing. - Request makes it through any additional HTTP filters to the Handler, which processes the request and generates the response.
- Request/Response metadata is extracted via the Envoy
gRPC AccessLog Service (als)
asynchronously for processing via thesigsci-agent
. - In parallel, additional metadata, such as response headers and the HTTP status code, is sent to the
sigsci-agent
via gRPCals
API for further processing while the response data is sent back to the originating client.
Request blocked processing
This is the flow if the sigsci-agent
blocks a request from being processed through Envoy.
- Client request received by Envoy and routed to the Envoy
External Authorization (ext_authz)
HTTP filter where request metadata is extracted for processing via thesigsci-agent
. - Request metadata is sent to the
sigsci-agent
via gRPCext_authz
API - The
sigsci-agent
sends back a 'block request' response, disallowing the request to continue being processed by the HTTP filter chain. - This triggers the
ext_authz
filter to generate a HTTP 406 response, blocking the request from any further processing.
Next-Gen WAF agent configuration
The sigsci-agent
is normally installed as a sidecar via Kubernetes with a slightly different configuration than a normal install.
The sigsci-agent
must be configured to run with an Envoy gRPC listener instead of the normal RPC listener. To do this, configure the Envoy gRPC listener via the envoy-grpc-address
agent configuration option, which will then start instead of the default RPC listener.
Setting the configuration value in the sigsci-agent
config file:
envoy-grpc-address = "0.0.0.0:8000"
Or setting the configuration value in the sigsci-agent
environment:
SIGSCI_ENVOY_GRPC_ADDRESS=0.0.0.0:8000
Optionally, the sigsci-agent
can be configured with TLS enabled. To do this, set the certificate and key files in the sigsci-agent
configuration.
envoy-grpc-cert = "/path/to/cert.pem"envoy-grpc-key = "/path/to/key.pem"
Or
SIGSCI_ENVOY_GRPC_CERT=/path/to/cert.pemSIGSCI_ENVOY_GRPC_KEY=/path/to/key.pem
Additionally, it is recommended to enable response data processing. To do this, the sigsci-agent
must be configured to expect response data from Envoy by setting the envoy-expect-response-data
agent configuration option. By default, response data is ignored in the sigsci-agent
as this is an optional Envoy configuration option in order to better support older versions of Envoy. If you are running Envoy v1.10 or higher, then you should enable this option.
Setting the configuration value in the sigsci-agent
config file:
envoy-expect-response-data = 1
Or setting the configuration value in the sigsci-agent
environment:
SIGSCI_ENVOY_EXPECT_RESPONSE_DATA=1
Some aspects of inspection in the sigsci-agent
can be configured but generally should be left as the default. Check out inspection-*
agent configuration for more details.
Envoy configuration
Envoy must to be configured with an External Authorization HTTP filter (envoy.ext_authz
) before the main handler filter to process request data and (optionally, though recommended) a gRPC AccessLog Service to process response data. To do this, multiple configuration items must to be added to the Envoy configuration: a cluster to handle the gRPC calls via the sigsci-agent
, the envoy.ext_authz
HTTP filter before the main handler, and the envoy.http_grpc_access_log
service added to the access_log
section of the HTTP listener filter if response data is to be enabled.
Adding the Next-Gen WAF agent cluster
A cluster must be added which is configured with the Envoy gRPC address used in the sigsci-agent
configuration. Currently load balancing will not work correctly if response data is enabled as there is not a way to enable consistent hashing for gRPC services in Envoy (yet), so it is recommended not to configure load balancing at this time unless only the envoy.ext_authz
API is being used without response data inspection.
1234567891011121314151617
clusters: - name: sigsci-agent-grpc connect_timeout: 0.2s type: strict_dns #lb_policy: LEAST_REQUEST http2_protocol_options: {} #tls_context: {} ### You can also use 'hosts' below, but this is deprecated load_assignment: cluster_name: sigsci-agent-grpc endpoints: - lb_endpoints: - endpoint: address: socket_address: address: sigsci-agent port_value: 8000
The address
is a resolvable hostname or IP for the sigsci-agent
and the port_value
must match that configured in the sigsci-agent
configuration for the envoy-grpc-address
option.
NOTE
The connect_timeout
is the timeout to connect to the sigsci-agent
(but not to process the data) and can be adjusted if required. The tls_context
option must be defined if TLS is to be used. TLS can be configured in the sigsci-agent
config via envoy-grpc-cert
and envoy-grpc-key
. If TLS is configured in the sigsci-agent
, then just the empty tls_context
must be configured (e.g., `tls_context: ) to let Envoy know to connect via TLS. If certificate validation is desired, then
validation_contextmust be configured in the
tls_contextto specify a
trusted_cafilename to use for validation. As gRPC services are HTTP/2 based, the
http2_protocol_options: option is required so that traffic is sent to the
sigsci-agent` cluster as HTTP/2.
Adding the Envoy External Authorization HTTP filter
The listener must have an External Authorization HTTP filter (envoy.ext_authz
) added before the main handler which points at the sigsci-agent
cluster.
123456789101112131415161718192021222324
http_filters:- name: envoy.filters.http.ext_authz typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz transport_api_version: V3 grpc_service: envoy_grpc: cluster_name: sigsci-agent-grpc timeout: 0.2s failure_mode_allow: true with_request_body: # Maximum request body bytes buffered and sent to the sigsci-agent max_request_bytes: 8192 # NOTE: If allow_partial_message is set false, then any request over # the above max bytes will fail with an HTTP "413 Payload Too Large" # so it is recommended to set this to true. allow_partial_message: true # NOTE: By default, envoy carries the HTTP request body as a UTF-8 string # and it fills the body @ # field. To pack the request body as raw bytes, # set pack_as_bytes to true. pack_as_bytes: true- name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
NOTE
failure_mode_allow: true
is so that this will fail open, which is recommended. And timeout
allows failing with the defined failure mode (true for fail open, false for fail closed) after a given time duration. Once this is done, all HTTP requests will be first sent to the envoy.ext_authz
filter handled by the sigsci-agent
cluster. The sigsci-agent
will then process requests and deny auth with a 406 HTTP status code if the request is to be blocked or allow the request through to the next HTTP filter if it is allowed. Any additional HTTP request headers are also added to the request as they are in other modules.
Adding the Envoy gRPC AccessLog Service
NOTE
This is a recommended, but optional step. If it is configured in Envoy, then the agent must also be configured to expect response data by setting the envoy-expect-response-data
agent configuration option as noted in the Next-Gen WAF agent configuration section. The Envoy External Authorization (envoy.ext_authz
) HTTP Filter can only process request data. As the sigsci-agent
needs the response data for full functionality, a gRPC AccessLog Service must be set up to send the response data to the sigsci-agent
. To do this an access_log
section must be added to the Envoy configuration under the listener filter (typically under the envoy.http_connection_manager
filter) if it does not already exist. If it does exist, then it must be appended to.
Refer to the access_log
configuration option of the HTTP Connection Manager for more details. An envoy.http_grpc_access_log
entry must be added here (in addition to any other existing access log entries).
Recommended Configuration (see Limitations and considerations for further customizations to minimize limitations):
123456789101112131415161718192021222324
access_log:- name: envoy.http_grpc_access_log typed_config: "@type": type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig common_config: log_name: "sigsci-agent-grpc" transport_api_version: V3 grpc_service: envoy_grpc: cluster_name: sigsci-agent-grpc timeout: 0.2s additional_request_headers_to_log: # These sigsci-agent headers are required for correct processing: - "x-sigsci-request-id" - "x-sigsci-waf-response" # Optionally, additional headers can be added that should be recorded: - "accept" - "content-type" - "content-length" additional_response_headers_to_log: - "date" - "server" - "content-type" - "content-length"
Limitations and considerations
Here are the current limitations when using the sigsci-agent
with Envoy Proxy. As support for Envoy Proxy improves in the future, these limitations will be addressed and should be reduced.
No request bodies are processed by default
Prior to Envoy v1.10.0, the Envoy External Authorization did not send the request body. In all versions of Envoy, the request body is not included in the ext_authz
call by default and it will not be inspected by the sigsci-agent
unless configured.
For Envoy v1.10.0 or higher, support to include the request body is built in to the envoy.ext_authz
configuration and it is now possible to configure the with_request_body
in this section of the Envoy configuration as noted above.
For Envoy v1.11.0 or higher, support was extended to be able to detect partial bodies more accurately.
For HTTP/2 (and gRPC) support Envoy must be running a version later than v1.12.1.
In Envoy v1.10.0 - v1.12.1 Envoy is not properly sending the request body using with_request_body
.
However, it is possible to work around this Envoy limitation using Lua until an Envoy upgrade is possible. The following is an example Lua filter that can be used to pass on gRPC based bodies to the sigsci-agent
for inspection:
To do this, the Lua HTTP filter (envoy.lua
) HTTP filter can be configured before the envoy.ext_authz
filter to add an internal x-sigsci-encoded-body
header with this data.
A small snippet of Lua code must be added to extract the body and add it to the request as follows:
1234567891011121314151617181920212223242526272829303132333435363738394041
http_filters: - name: envoy.lua config: inline_code: | -- Add a special header to pass the encoded body function envoy_on_request(req) local len = 0 local reqbody -- Determine the body length local cl = req:headers():get("content-length") if cl ~= nil then len = tonumber(cl) end -- gRPC does not have a content-length header to limit the body before buffering if len == 0 and req:headers():get("content-type") == "application/grpc" then -- Triggers buffering len = req:body():length() end -- Limit body length sent to the agent (adjust as needed) if len > 0 and len <= 8192 then -- Triggers buffering reqbody = req:body():getBytes(0, len) -- Encode the body for use in a header value local enc, t = string.gsub(reqbody, "[^%w]", function(chr) return string.format("%%%02X",string.byte(chr)) end) req:headers():add("x-sigsci-encoded-body", enc) end end - name: envoy.ext_authz config: grpc_service: envoy_grpc: cluster_name: sigsci-agent-grpc timeout: 0.2s failure_mode_allow: true# with_request_body:# max_request_bytes: 8192# allow_partial_message: true - name: envoy.router config: {}
No TLS handshake metadata is extracted
There is not currently a means for the sigsci-agent
to see the TLS handshake metadata (e.g., cipher and protocol version) used in the originating request as this is not (yet) available in Envoy. Any TLS handshake metadata based signals will not be seen in the product for this site (also known as a workspace).
The following system signals are currently not supported due to this limitation:
- WEAKTLS
Only minimal request headers are recorded by default if there were only response-based signals
If the request was inspected by the envoy.ext_authz
filter and no signals were issued, then the response will be processed by the envoy.http_grpc_access_log
service. If a signal is found in the response data, then only minimal request headers will be recorded with the signal due to the API not being sent all request headers by default. However, if additional request headers are desired to be recorded, then these should be added via the additional_request_headers_to_log
option of the access_log
configuration in Envoy.
Currently these headers will automatically be added:
Host
User-Agent
Referer
X-Forwarded-For
Two sigsci-agent
specific headers must be added. Additionally any additional request headers can be added explicitly via additional_request_headers_to_log
:
123456789
additional_request_headers_to_log:# These sigsci-agent headers are required for correct processing:- "x-sigsci-request-id"- "x-sigsci-waf-response"# Optionally, additional headers can be added that should be recorded:- "accept"- "content-type"- "content-length"- "x-real-ip"
No response headers are processed by default
Similar to above with minimal request headers not being processed by the envoy.http_grpc_access_log
service, there are no response headers sent to this API by default. Any headers that are desired to be recorded must be explicitly listed in the additional_response_headers_to_log
option of the access_log
configuration in Envoy as there is not currently any means to wildcard this. The following are recommended.
12345
additional_response_headers_to_log:- "date"- "server"- "content-type"- "content-length"
Next steps
Verify the agent and module installation and explore module options.
Do not use this form to send sensitive information. If you need assistance, contact support. This form is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.