Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds configuration to retain client IP information #2284

Merged
merged 20 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions apis/v1alpha1/nginxproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ type NginxProxySpec struct {
//
// +optional
Telemetry *Telemetry `json:"telemetry,omitempty"`
// RewriteClientIP defines configuration for rewriting the client IP to the original client's IP.
// +kubebuilder:validation:XValidation:message="if mode is set, trustedAddresses is a required field",rule="!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses) == 0))"
//
// +optional
//nolint:lll
RewriteClientIP *RewriteClientIP `json:"rewriteClientIP,omitempty"`
// DisableHTTP2 defines if http2 should be disabled for all servers.
// Default is false, meaning http2 will be enabled for all servers.
//
Expand Down Expand Up @@ -114,3 +120,86 @@ type TelemetryExporter struct {
// +kubebuilder:validation:Pattern=`^(?:http?:\/\/)?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*(?::\d{1,5})?$`
Endpoint string `json:"endpoint"`
}

// RewriteClientIP specifies the configuration for rewriting the client's IP address.
kate-osborn marked this conversation as resolved.
Show resolved Hide resolved
type RewriteClientIP struct {
// Mode defines how NGINX will rewrite the client's IP address.
// There are two possible modes:
// - ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
// - XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
// Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
//
// +optional
Mode *RewriteClientIPModeType `json:"mode,omitempty"`

// SetIPRecursively configures whether recursive search is used when selecting the client's address from
// the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
sjberman marked this conversation as resolved.
Show resolved Hide resolved
// If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
// to start of array and select the first untrusted IP.
// For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
// and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
// If disabled, NGINX will select the IP at the end of the array.
// In the previous example, 55.55.55.1 would be selected.
// Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
//
// +optional
SetIPRecursively *bool `json:"setIPRecursively,omitempty"`

// TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
salonichf5 marked this conversation as resolved.
Show resolved Hide resolved
// If a request comes from a trusted address, NGINX will rewrite the client IP information,
// and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
salonichf5 marked this conversation as resolved.
Show resolved Hide resolved
// If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
// TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
// To trust all addresses (not recommended for production), set to 0.0.0.0/0.
// If no addresses are provided, NGINX will not rewrite the client IP information.
// Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
// This field is required if mode is set.
// +kubebuilder:validation:MaxItems=16
// +listType=map
// +listMapKey=type
//
salonichf5 marked this conversation as resolved.
Show resolved Hide resolved
// +optional
TrustedAddresses []Address `json:"trustedAddresses,omitempty"`
}

// RewriteClientIPModeType defines how NGINX Gateway Fabric will determine the client's original IP address.
// +kubebuilder:validation:Enum=ProxyProtocol;XForwardedFor
type RewriteClientIPModeType string

const (
// RewriteClientIPModeProxyProtocol configures NGINX to accept PROXY protocol and
// set the client's IP address to the IP address in the PROXY protocol header.
// Sets the proxy_protocol parameter on the listen directive of all servers and sets real_ip_header
// to proxy_protocol: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header.
RewriteClientIPModeProxyProtocol RewriteClientIPModeType = "ProxyProtocol"

// RewriteClientIPModeXForwardedFor configures NGINX to set the client's IP address to the
// IP address in the X-Forwarded-For HTTP header.
// https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header.
RewriteClientIPModeXForwardedFor RewriteClientIPModeType = "XForwardedFor"
)

// Address is a struct that specifies address type and value.
type Address struct {
// Type specifies the type of address.
// Default is "cidr" which specifies that the address is a CIDR block.
//
// +optional
// +kubebuilder:default:=cidr
Type AddressType `json:"type,omitempty"`

// Value specifies the address value.
//
// +optional
Value string `json:"value,omitempty"`
}

// AddressType specifies the type of address.
// +kubebuilder:validation:Enum=cidr
type AddressType string

const (
// AddressTypeCIDR specifies that the address is a CIDR block.
// kubebuilder:validation:Pattern=`^[\.a-zA-Z0-9:]*(\/([0-9]?[0-9]?[0-9]))$`
AddressTypeCIDR AddressType = "cidr"
)
50 changes: 50 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions charts/nginx-gateway-fabric/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ nginx:
{}
# disableHTTP2: false
# ipFamily: dual
# rewriteClientIP:
# mode: "ProxyProtocol"
# # -- The trusted addresses field needs to be replaced with the load balancer's address and type.
# trustedAddresses: [
# {
# # -- The CIDR block of the load balancer(s).
# value: "",
# type: "cidr",
# }
# ]
# setIPRecursively: true
salonichf5 marked this conversation as resolved.
Show resolved Hide resolved
# telemetry:
# exporter:
# endpoint: otel-collector.default.svc:4317
Expand Down
64 changes: 64 additions & 0 deletions config/crd/bases/gateway.nginx.org_nginxproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,70 @@ spec:
- ipv4
- ipv6
type: string
rewriteClientIP:
description: RewriteClientIP defines configuration for rewriting the
client IP to the original client's IP.
properties:
mode:
description: |-
Mode defines how NGINX will rewrite the client's IP address.
There are two possible modes:
- ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
- XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
enum:
- ProxyProtocol
- XForwardedFor
type: string
setIPRecursively:
description: |-
SetIPRecursively configures whether recursive search is used when selecting the client's address from
the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
to start of array and select the first untrusted IP.
For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
If disabled, NGINX will select the IP at the end of the array.
In the previous example, 55.55.55.1 would be selected.
Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
type: boolean
trustedAddresses:
description: |-
TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
If a request comes from a trusted address, NGINX will rewrite the client IP information,
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
If no addresses are provided, NGINX will not rewrite the client IP information.
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
This field is required if mode is set.
items:
description: Address is a struct that specifies address type
and value.
properties:
type:
default: cidr
description: |-
Type specifies the type of address.
Default is "cidr" which specifies that the address is a CIDR block.
enum:
- cidr
type: string
value:
description: Value specifies the address value.
type: string
type: object
maxItems: 16
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
type: object
x-kubernetes-validations:
- message: if mode is set, trustedAddresses is a required field
rule: '!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses)
== 0))'
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
Expand Down
64 changes: 64 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,70 @@ spec:
- ipv4
- ipv6
type: string
rewriteClientIP:
description: RewriteClientIP defines configuration for rewriting the
client IP to the original client's IP.
properties:
mode:
description: |-
Mode defines how NGINX will rewrite the client's IP address.
There are two possible modes:
- ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
- XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
enum:
- ProxyProtocol
- XForwardedFor
type: string
setIPRecursively:
description: |-
SetIPRecursively configures whether recursive search is used when selecting the client's address from
the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
to start of array and select the first untrusted IP.
For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
If disabled, NGINX will select the IP at the end of the array.
In the previous example, 55.55.55.1 would be selected.
Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
type: boolean
trustedAddresses:
description: |-
TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
If a request comes from a trusted address, NGINX will rewrite the client IP information,
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
If no addresses are provided, NGINX will not rewrite the client IP information.
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
This field is required if mode is set.
items:
description: Address is a struct that specifies address type
and value.
properties:
type:
default: cidr
description: |-
Type specifies the type of address.
Default is "cidr" which specifies that the address is a CIDR block.
enum:
- cidr
type: string
value:
description: Value specifies the address value.
type: string
type: object
maxItems: 16
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
type: object
x-kubernetes-validations:
- message: if mode is set, trustedAddresses is a required field
rule: '!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses)
== 0))'
telemetry:
description: Telemetry specifies the OpenTelemetry configuration.
properties:
Expand Down
12 changes: 8 additions & 4 deletions internal/mode/static/nginx/config/http/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package http

import "github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/shared"

const InternalRoutePathPrefix = "/_ngf-internal"
const (
InternalRoutePathPrefix = "/_ngf-internal"
HTTPSScheme = "https"
)

// Server holds all configuration for an HTTP server.
type Server struct {
Expand Down Expand Up @@ -109,9 +112,10 @@ type ProxySSLVerify struct {

// ServerConfig holds configuration for an HTTP server and IP family to be used by NGINX.
type ServerConfig struct {
Servers []Server
IPFamily shared.IPFamily
Plus bool
Servers []Server
RewriteClientIP shared.RewriteClientIPSettings
IPFamily shared.IPFamily
Plus bool
}

// Include defines a file that's included via the include directive.
Expand Down
Loading
Loading