-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
NGINX: Correctly determine client IP. #12768
base: main
Are you sure you want to change the base?
Conversation
|
This issue is currently awaiting triage. If Ingress contributors determines this is a relevant issue, they will accept it by applying the The Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
Welcome @dmeremyanin! |
Hi @dmeremyanin. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
✅ Deploy Preview for kubernetes-ingress-nginx ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
d1dc3c6
to
9429341
Compare
I've updated the docs to reflect the changes. |
…ltiple proxies are involved
9429341
to
83b2394
Compare
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: dmeremyanin, lubervn The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Hey @Gacko @tao12345666333, is there anything I need to do to get the PR reviewed, or should I just be patient and wait? |
Hello @dmeremyanin, time. Just time. 😬 Sorry to say, but we currently are something between 2 and 3 maintainers also having a day to day job and still a lot of other maintenance work to do and PRs to merge before we can proceed to the latest ones. Kind regards |
Hello, This PR solves one of our problem here and avoid us to maintain a piece of lua code to achieve the same :) Our setup use Cloudfront in front of an NLB then ingress-nginx. We tested it in one of our cluster and works as expected. Thanks you very much. |
@dmeremyanin Thank you, we are using exact the same setup and your PR works well for us. |
What this PR does / why we need it:
This update ensures that the correct client IP address is determined in Ingress NGINX when the PROXY protocol is enabled. The logic now properly handles proxy chains by checking trusted proxy addresses and using the appropriate forwarded-for headers.
Here's an example when Cloudflare is used:
In this scenario, Cloudflare's IP address appears as the client IP. This PR ensures that the actual client IP is correctly identified, even when Cloudflare (or other proxies) are involved.
The algorithm
To ensure the correct client IP is identified, we need to enable
use-forwarded-headers
and properly configureproxy-real-ip-cidr
to trust all intermediate proxies (both within the private network and any external proxies). Caution: By default, theproxy-real-ip-cidr
is set to0.0.0.0/0
, which means all IP addresses are trusted.The process works as follows:
$proxy_protocol_addr
is trusted (i.e., whether it's in theproxy-real-ip-cidr
list).X-Forwarded-For
by default).$proxy_protocol_addr
.Once the appropriate header is determined, its value is used with the
real_ip_header
directive, allowing NGINX to correctly identify the client IP.Issues addressed by this PR:
real_ip_header
directive whenproxy_protocol
is enabled #11623In these issues, a workaround was suggested, such as adding the following annotation:
However, this approach may not work correctly in scenarios where clients can connect directly to the TCP load balancer (bypassing the trusted HTTP proxy):
proxy_protocol
should be used to correctly identify the client IP.Types of changes
It looks more like a new feature because it's now possible to use
use-proxy-protocol
withuse-forwarded-headers
configuration option to change the behavior of client IP address identifying.How Has This Been Tested?
I tested the functionality in a test environment simulating a typical production setup. The environment includes a Layer 7 proxy (Cloudflare) in front of a cloud-based TCP load balancer with the PROXY protocol enabled, and Ingress NGINX Controller within the K8S cluster. To verify the results, I exposed the whoami service using the Ingress Controller and inspected the incoming X-Real-IP and X-Forwarded-For headers reaching the service.
Here's the setup (IPs are fictional):
100.64.0.1
198.18.0.1
(passing the real client IP in the X-Forwarded-For header)10.1.1.1
(with PROXY protocol enabled)10.2.1.1
use-proxy-protocol
is enabled in Ingress NGINX ControllerTesting Scenarios
With HTTP Proxy (client → HTTP proxy → TCP LB → Ingress Controller)
Neither
use-forwarded-headers
norproxy-real-ip-cidr
are configured.Result: 🔴 HTTP proxy IP
198.18.0.1
is identified as the client IP.use-forwarded-headers
disabled,proxy-real-ip-cidr
set to198.18.0.0/24
to trust the HTTP proxy subnet.Result: 🔴 Kubernetes worker node IP
10.2.1.1
is identified as the client IP.use-forwarded-headers
disabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to the trust private network and the HTTP proxy subnet.Result: 🔴 HTTP proxy IP
198.18.0.1
is identified as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
not configured (0.0.0.0/0
by default).Result: 🟢 Correct client IP
100.64.0.1
is identified.use-forwarded-headers
enabled,proxy-real-ip-cidr
not configured, passed custom "X-Forwarded-For: 1.1.1.1" header.Result: 🔴 Spoofed IP
1.1.1.1
is used as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to198.18.0.0/24
to trust the HTTP proxy subnet.Result: 🔴 Kubernetes worker node IP
10.2.1.1
is identified as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to trust the private network and the HTTP proxy subnet.Result: 🟢 Correct client IP
100.64.0.1
is identified.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to trust the private network and the HTTP proxy subnet, passed custom "X-Forwarded-For: 1.1.1.1" header.Result: 🟢 Correct client IP
100.64.0.1
is identified.Without intermediate HTTP Proxy (client → TCP LB → Ingress Controller)
Neither
use-forwarded-headers
norproxy-real-ip-cidr
are configured.Result: 🟢 Correct client IP
100.64.0.1
is identified.use-forwarded-headers
disabled,proxy-real-ip-cidr
set to198.18.0.0/24
to trust the HTTP proxy subnet.Result: 🔴 Kubernetes worker node IP
10.2.1.1
is identified as the client IP.use-forwarded-headers
disabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to trust the private network and the HTTP proxy subnet.Result: 🟢 Correct client IP
100.64.0.1
is identified.use-forwarded-headers
enabled,proxy-real-ip-cidr
not configured (0.0.0.0/0
by default).Result: 🔴 Kubernetes worker node IP
10.2.1.1
is identified as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
not configured, passed "X-Forwarded-For: 1.1.1.1" header.Result: 🔴 Spoofed IP
1.1.1.1
is used as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to198.18.0.0/24
to trust the HTTP proxy subnet.Result: 🔴 Kubernetes worker node IP
10.2.1.1
is identified as the client IP.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to trust the private network and the HTTP proxy subnet.Result: 🟢 Correct client IP
100.64.0.1
is identified.use-forwarded-headers
enabled,proxy-real-ip-cidr
set to10.0.0.0/8,198.18.0.0/24
to trust the private network and the HTTP proxy subnet, passed custom "X-Forwarded-For: 1.1.1.1" header.Result: 🟢 Correct client IP
100.64.0.1
is identified.Conclusion and Questions
use-proxy-protocol
anduse-forwarded-headers
are enabled.proxy-real-ip-cidr
to something like10.0.0.0/8
by default? Setting this default would help prevent misconfigurations and ensure that only trusted internal IP ranges are accepted, reducing the risk of spoofed IPs.Checklist: