Skip to content

Commit bf17bd5

Browse files
authored
Adds configuration to retain client IP information (#2284)
Problem: As a user, I want to be able to retain client IP information when a requests comes in to NGF. Solution: Introduces configuration that allows retaining client IP information using the real_ip module.
1 parent 6b9ad3a commit bf17bd5

File tree

21 files changed

+1549
-150
lines changed

21 files changed

+1549
-150
lines changed

apis/v1alpha1/nginxproxy_types.go

+89
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ type NginxProxySpec struct {
5353
//
5454
// +optional
5555
Telemetry *Telemetry `json:"telemetry,omitempty"`
56+
// RewriteClientIP defines configuration for rewriting the client IP to the original client's IP.
57+
// +kubebuilder:validation:XValidation:message="if mode is set, trustedAddresses is a required field",rule="!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses) == 0))"
58+
//
59+
// +optional
60+
//nolint:lll
61+
RewriteClientIP *RewriteClientIP `json:"rewriteClientIP,omitempty"`
5662
// DisableHTTP2 defines if http2 should be disabled for all servers.
5763
// Default is false, meaning http2 will be enabled for all servers.
5864
//
@@ -114,3 +120,86 @@ type TelemetryExporter struct {
114120
// +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})?$`
115121
Endpoint string `json:"endpoint"`
116122
}
123+
124+
// RewriteClientIP specifies the configuration for rewriting the client's IP address.
125+
type RewriteClientIP struct {
126+
// Mode defines how NGINX will rewrite the client's IP address.
127+
// There are two possible modes:
128+
// - ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
129+
// - XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
130+
// Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
131+
//
132+
// +optional
133+
Mode *RewriteClientIPModeType `json:"mode,omitempty"`
134+
135+
// SetIPRecursively configures whether recursive search is used when selecting the client's address from
136+
// the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
137+
// If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
138+
// to start of array and select the first untrusted IP.
139+
// For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
140+
// and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
141+
// If disabled, NGINX will select the IP at the end of the array.
142+
// In the previous example, 55.55.55.1 would be selected.
143+
// Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
144+
//
145+
// +optional
146+
SetIPRecursively *bool `json:"setIPRecursively,omitempty"`
147+
148+
// TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
149+
// If a request comes from a trusted address, NGINX will rewrite the client IP information,
150+
// and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
151+
// If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
152+
// TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
153+
// To trust all addresses (not recommended for production), set to 0.0.0.0/0.
154+
// If no addresses are provided, NGINX will not rewrite the client IP information.
155+
// Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
156+
// This field is required if mode is set.
157+
// +kubebuilder:validation:MaxItems=16
158+
// +listType=map
159+
// +listMapKey=type
160+
//
161+
// +optional
162+
TrustedAddresses []Address `json:"trustedAddresses,omitempty"`
163+
}
164+
165+
// RewriteClientIPModeType defines how NGINX Gateway Fabric will determine the client's original IP address.
166+
// +kubebuilder:validation:Enum=ProxyProtocol;XForwardedFor
167+
type RewriteClientIPModeType string
168+
169+
const (
170+
// RewriteClientIPModeProxyProtocol configures NGINX to accept PROXY protocol and
171+
// set the client's IP address to the IP address in the PROXY protocol header.
172+
// Sets the proxy_protocol parameter on the listen directive of all servers and sets real_ip_header
173+
// to proxy_protocol: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header.
174+
RewriteClientIPModeProxyProtocol RewriteClientIPModeType = "ProxyProtocol"
175+
176+
// RewriteClientIPModeXForwardedFor configures NGINX to set the client's IP address to the
177+
// IP address in the X-Forwarded-For HTTP header.
178+
// https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header.
179+
RewriteClientIPModeXForwardedFor RewriteClientIPModeType = "XForwardedFor"
180+
)
181+
182+
// Address is a struct that specifies address type and value.
183+
type Address struct {
184+
// Type specifies the type of address.
185+
// Default is "cidr" which specifies that the address is a CIDR block.
186+
//
187+
// +optional
188+
// +kubebuilder:default:=cidr
189+
Type AddressType `json:"type,omitempty"`
190+
191+
// Value specifies the address value.
192+
//
193+
// +optional
194+
Value string `json:"value,omitempty"`
195+
}
196+
197+
// AddressType specifies the type of address.
198+
// +kubebuilder:validation:Enum=cidr
199+
type AddressType string
200+
201+
const (
202+
// AddressTypeCIDR specifies that the address is a CIDR block.
203+
// kubebuilder:validation:Pattern=`^[\.a-zA-Z0-9:]*(\/([0-9]?[0-9]?[0-9]))$`
204+
AddressTypeCIDR AddressType = "cidr"
205+
)

apis/v1alpha1/zz_generated.deepcopy.go

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/nginx-gateway-fabric/values.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ nginx:
9393
{}
9494
# disableHTTP2: false
9595
# ipFamily: dual
96+
# rewriteClientIP:
97+
# mode: "ProxyProtocol"
98+
# # -- The trusted addresses field needs to be replaced with the load balancer's address and type.
99+
# trustedAddresses: [
100+
# {
101+
# # -- The CIDR block of the load balancer(s).
102+
# value: "",
103+
# type: "cidr",
104+
# }
105+
# ]
106+
# setIPRecursively: true
96107
# telemetry:
97108
# exporter:
98109
# endpoint: otel-collector.default.svc:4317

config/crd/bases/gateway.nginx.org_nginxproxies.yaml

+64
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,70 @@ spec:
6262
- ipv4
6363
- ipv6
6464
type: string
65+
rewriteClientIP:
66+
description: RewriteClientIP defines configuration for rewriting the
67+
client IP to the original client's IP.
68+
properties:
69+
mode:
70+
description: |-
71+
Mode defines how NGINX will rewrite the client's IP address.
72+
There are two possible modes:
73+
- ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
74+
- XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
75+
Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
76+
enum:
77+
- ProxyProtocol
78+
- XForwardedFor
79+
type: string
80+
setIPRecursively:
81+
description: |-
82+
SetIPRecursively configures whether recursive search is used when selecting the client's address from
83+
the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
84+
If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
85+
to start of array and select the first untrusted IP.
86+
For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
87+
and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
88+
If disabled, NGINX will select the IP at the end of the array.
89+
In the previous example, 55.55.55.1 would be selected.
90+
Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
91+
type: boolean
92+
trustedAddresses:
93+
description: |-
94+
TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
95+
If a request comes from a trusted address, NGINX will rewrite the client IP information,
96+
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
97+
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
98+
TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
99+
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
100+
If no addresses are provided, NGINX will not rewrite the client IP information.
101+
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
102+
This field is required if mode is set.
103+
items:
104+
description: Address is a struct that specifies address type
105+
and value.
106+
properties:
107+
type:
108+
default: cidr
109+
description: |-
110+
Type specifies the type of address.
111+
Default is "cidr" which specifies that the address is a CIDR block.
112+
enum:
113+
- cidr
114+
type: string
115+
value:
116+
description: Value specifies the address value.
117+
type: string
118+
type: object
119+
maxItems: 16
120+
type: array
121+
x-kubernetes-list-map-keys:
122+
- type
123+
x-kubernetes-list-type: map
124+
type: object
125+
x-kubernetes-validations:
126+
- message: if mode is set, trustedAddresses is a required field
127+
rule: '!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses)
128+
== 0))'
65129
telemetry:
66130
description: Telemetry specifies the OpenTelemetry configuration.
67131
properties:

deploy/crds.yaml

+64
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,70 @@ spec:
647647
- ipv4
648648
- ipv6
649649
type: string
650+
rewriteClientIP:
651+
description: RewriteClientIP defines configuration for rewriting the
652+
client IP to the original client's IP.
653+
properties:
654+
mode:
655+
description: |-
656+
Mode defines how NGINX will rewrite the client's IP address.
657+
There are two possible modes:
658+
- ProxyProtocol: NGINX will rewrite the client's IP using the PROXY protocol header.
659+
- XForwardedFor: NGINX will rewrite the client's IP using the X-Forwarded-For header.
660+
Sets NGINX directive real_ip_header: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
661+
enum:
662+
- ProxyProtocol
663+
- XForwardedFor
664+
type: string
665+
setIPRecursively:
666+
description: |-
667+
SetIPRecursively configures whether recursive search is used when selecting the client's address from
668+
the X-Forwarded-For header. It is used in conjunction with TrustedAddresses.
669+
If enabled, NGINX will recurse on the values in X-Forwarded-Header from the end of array
670+
to start of array and select the first untrusted IP.
671+
For example, if X-Forwarded-For is [11.11.11.11, 22.22.22.22, 55.55.55.1],
672+
and TrustedAddresses is set to 55.55.55.1/32, NGINX will rewrite the client IP to 22.22.22.22.
673+
If disabled, NGINX will select the IP at the end of the array.
674+
In the previous example, 55.55.55.1 would be selected.
675+
Sets NGINX directive real_ip_recursive: https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
676+
type: boolean
677+
trustedAddresses:
678+
description: |-
679+
TrustedAddresses specifies the addresses that are trusted to send correct client IP information.
680+
If a request comes from a trusted address, NGINX will rewrite the client IP information,
681+
and forward it to the backend in the X-Forwarded-For* and X-Real-IP headers.
682+
If the request does not come from a trusted address, NGINX will not rewrite the client IP information.
683+
TrustedAddresses only supports CIDR blocks: 192.33.21.1/24, fe80::1/64.
684+
To trust all addresses (not recommended for production), set to 0.0.0.0/0.
685+
If no addresses are provided, NGINX will not rewrite the client IP information.
686+
Sets NGINX directive set_real_ip_from: https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
687+
This field is required if mode is set.
688+
items:
689+
description: Address is a struct that specifies address type
690+
and value.
691+
properties:
692+
type:
693+
default: cidr
694+
description: |-
695+
Type specifies the type of address.
696+
Default is "cidr" which specifies that the address is a CIDR block.
697+
enum:
698+
- cidr
699+
type: string
700+
value:
701+
description: Value specifies the address value.
702+
type: string
703+
type: object
704+
maxItems: 16
705+
type: array
706+
x-kubernetes-list-map-keys:
707+
- type
708+
x-kubernetes-list-type: map
709+
type: object
710+
x-kubernetes-validations:
711+
- message: if mode is set, trustedAddresses is a required field
712+
rule: '!(has(self.mode) && (!has(self.trustedAddresses) || size(self.trustedAddresses)
713+
== 0))'
650714
telemetry:
651715
description: Telemetry specifies the OpenTelemetry configuration.
652716
properties:

internal/mode/static/nginx/config/http/config.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package http
22

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

5-
const InternalRoutePathPrefix = "/_ngf-internal"
5+
const (
6+
InternalRoutePathPrefix = "/_ngf-internal"
7+
HTTPSScheme = "https"
8+
)
69

710
// Server holds all configuration for an HTTP server.
811
type Server struct {
@@ -109,9 +112,10 @@ type ProxySSLVerify struct {
109112

110113
// ServerConfig holds configuration for an HTTP server and IP family to be used by NGINX.
111114
type ServerConfig struct {
112-
Servers []Server
113-
IPFamily shared.IPFamily
114-
Plus bool
115+
Servers []Server
116+
RewriteClientIP shared.RewriteClientIPSettings
117+
IPFamily shared.IPFamily
118+
Plus bool
115119
}
116120

117121
// Include defines a file that's included via the include directive.

0 commit comments

Comments
 (0)