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

Enable Proxy Protocol #1406

Closed
1 of 2 tasks
mpstefan opened this issue Dec 18, 2023 · 2 comments · Fixed by #2284
Closed
1 of 2 tasks

Enable Proxy Protocol #1406

mpstefan opened this issue Dec 18, 2023 · 2 comments · Fixed by #2284
Assignees
Labels
area/nginx-configuration Relates to nginx configuration refined Requirements are refined and the issue is ready to be implemented. size/medium Estimated to be completed within a week
Milestone

Comments

@mpstefan
Copy link
Collaborator

mpstefan commented Dec 18, 2023

As a user of NGF
I want to enable proxy protocol for my application's endpoints
So that the client's IP address is preserved as the traffic is forwarded to my application.

Acceptance

  • The user can enable proxy protocol for all Gateway listeners associated with the GatewayClass the NginxProxy parametersRef is attached to.
  • When proxy protocol is enabled, gRPC and HTTP Routes will forward the client IP to the upstream service.
  • API Reference documentation is updated to demonstrate how proxy protocol may be enabled.

Tasks

  1. kate-osborn
Copy link
Contributor

github-actions bot commented Feb 6, 2024

This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the stale Pull requests/issues with no activity label Feb 6, 2024
@sjberman sjberman removed the stale Pull requests/issues with no activity label Feb 6, 2024
@mpstefan mpstefan modified the milestones: v1.2.0, v2.0.0 Feb 7, 2024
@mpstefan mpstefan modified the milestones: v1.3.0, v1.4.0 May 1, 2024
@mpstefan mpstefan added refined Requirements are refined and the issue is ready to be implemented. size/medium Estimated to be completed within a week labels Jun 17, 2024
@salonichf5 salonichf5 self-assigned this Jul 16, 2024
@sindhushiv sindhushiv moved this from 🆕 New to 🏗 In Progress in NGINX Gateway Fabric Jul 18, 2024
@kate-osborn kate-osborn self-assigned this Jul 29, 2024
@kate-osborn
Copy link
Contributor

kate-osborn commented Jul 29, 2024

Questions

  1. Would a user want to configure the directives in the real ip module to preserve client IP without enabling proxy protocol?

    Yes. A user can leverage the directives in the real ip module to replace the $remote_addr and $remote_port variables with the original client IP address and port. For example, a user can configure NGINX to replace the $remote_addr and $remote_port variables using the value of the X-Forwarded-For header. This may be useful when the proxy fronting NGF doesn't implement PROXY protocol or isn't configured to accept & send PROXY protocol.

  2. If proxy_protocol is enabled but do not specify directives from realIP module , would that preserve any information of client's?

    Yes. Enabling proxy_protocol on the listener configures NGINX to accept the PROXY protocol. NGINX will also set the $proxy_protocol_addr and $proxy_protocol_port variables to the original client address and port. A user can then pass those values to the backend via headers, log the values, or configure rate limiting based on the values.

  3. If proxy_protocol is disabled, how will NGINX use set_real_ip_from directive, if set to CIDR/ Address.

    There are two important points to consider here. First, the default value for real_ip_header is X-Real-IP. Second, the default value for set_real_ip_from is empty string. This means that by default NGINX will not replace the $remote_addr and $remote_port variables because it does not trust any addresses. However, if a user sets the set_real_ip_from header to say "92.23.12.22", then NGINX will replace the $remote_addr and $remote_port variables to the value of the X-Real-IP header IF that header is sent by 92.23.12.22. So this is a valid use case even when proxy_protocol is disabled.

Methods for preserving client IP addresses

  • X-Forwarded-For: a multi-valued header. Each proxy server should append the IP address of the host from which it received the request. Resulting header should look like `X-Forwarded-For: client, proxy1, proxy2". Other headers for passing port, host, and proto information: X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Proto.
  • Forwarded: multi-value header of key-value pairs separated by semicolons. `Forwarded: for=client;port=80;proto=https, for=proxy;port=80;proto=https".
  • X-Real-IP: a single value header that contains just the client IP address.
  • PROXY protocol: allows TCP proxies to inject data about original source and dest addresses to their upstream servers without knowledge of underlying protocol. Can operate at L4, instead of L7.
    Image
  • Custom header: determine the client IP address for a request based on
    a trusted custom HTTP header.

Choosing a method will depend on how the Load Balancer fronting NGF preserves the client IP address, and what the user wants to do with the client IP. If passing the client IP to the backend, then it's important to consider how the backend expects to receive this information.

Directive Behavior

proxy_protocol listen param

The proxy_protocol listen parameter configures NGINX server to accept the PROXY protocol. NGINX will also set the $proxy_protocol_addr and $proxy_protocol_port variables to the original client address and port.

real ip module

The real-ip module rewrites the values in the $remote_addr and $remote_port variables to the client IP address and port. Without this module, the $remote_addr and $remote_port variables are set to the IP address and port of the load balancer.

How the real-ip modules determines the client IP address and port depends on how you configure it.

set_real_ip_from

The set_real_ip_from directive tells NGINX to only trust replacement IPs from these addresses.

If not provided, the $remote_addr and $remote_port variables will never be replaced.

To trust all addresses, set to 0.0.0.0/0.

This directive is also used by the real_ip_recursive directive.

real_ip_header

By default NGINX will use the value of the X-Real-IP header. This directive can be set to X-Forwarded-To, proxy_protocol, or any other header name. If set to proxy_protocol, proxy_protocol must be enabled on the server.

real_ip_recursive

Only makes sense when the header specified in real_ip_header is a multi-value header (e.g. contains a list of addresses). Commonly used with X-Forwarded-For. For example:

Say you have the following setup:

[USER: 11.11.11.11] → [PROXY: 22.22.22.22] → [LB: 55.55.55.1] → [NGF: 77.77.77.77]

and the following NGINX config:

 set_real_ip_from 55.55.55.1;
 real_ip_header X-Forwarded-For;
 real_ip_recursive on;

Once the request hits NGF, the X-Forwarded-For header contains three IP addresses: X-Forwarded-For: [11.11.11.11, 22.22.22.22, 55.55.55.1]

Because real_ip_recursive is on, NGINX will set $remote_addr to 22.22.22.22. This is because it recurses on the values in X-Forwarded-Header from end of array to start of array and selects the first untrusted ip. If you wanted to set $remote_addr to the user's IP address instead, and you trust the Proxy, you could achieve that by also specifying the Proxy's IP using set_real_ip_from:

 set_real_ip_from 55.55.55.1;
 set_real_ip_from 22.22.22.22;
 real_ip_header X-Forwarded-For;
 real_ip_recursive on;

If real_ip_recursive is off, NGINX will set $remote_addr to 55.55.55.1 because it will select the rightmost address.

@kate-osborn kate-osborn removed their assignment Aug 7, 2024
@github-project-automation github-project-automation bot moved this from 👀 In Review to ✅ Done in NGINX Gateway Fabric Sep 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/nginx-configuration Relates to nginx configuration refined Requirements are refined and the issue is ready to be implemented. size/medium Estimated to be completed within a week
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants