leocalheirosdb1 opened a new issue, #13594:
URL: https://github.com/apache/apisix/issues/13594

   ### Description
   
   ## Question
   
   We are running APISIX behind a TCP load balancer (TLS passthrough) with 
Proxy Protocol v2. To handle proxy protocol, we use 
`proxy_protocol.listen_https_port: 9182` in our config.
   
   The problem is that APISIX sends `X-Forwarded-Port: 9182` (the internal 
listener port) to upstream services instead of `443` (the port clients actually 
connect to). This causes our upstream (Keycloak) to generate redirect URLs like:
   
   ```
   Location: https://example.com:9182/admin/master/console/
   ```
   
   **What is the recommended way to override `X-Forwarded-Port` in this setup?**
   
   ## What we understand
   
   In `ngx_tpl.lua`, the generated nginx config sets:
   
   ```nginx
   set $var_x_forwarded_port       $server_port;
   proxy_set_header   X-Forwarded-Port     $var_x_forwarded_port;
   ```
   
   Since our proxy protocol listener is on port 9182, `$server_port` resolves 
to **9182**. The `proxy_set_header` directive then forwards this value to 
upstream.
   
   We also noticed that `http_server_location_configuration_snippet` is 
injected **before** the `set $var_x_forwarded_port` line in the location block, 
so any snippet-based override gets overwritten.
   
   ## What we tried
   
   We attempted several approaches, none of which changed the 
`X-Forwarded-Port` value received by upstream:
   
   ### 1. `serverless-pre-function` (rewrite phase) writing to the nginx 
variable
   
   ```yaml
   - name: serverless-pre-function
     enable: true
     config:
       phase: rewrite
       functions:
         - |
           return function(conf, ctx)
             if ctx.var.var_x_forwarded_port == "9182" then
               ctx.var.var_x_forwarded_port = "443"
             end
           end
   ```
   
   `var_x_forwarded_port` is in the `ngx_var_names` allowlist in 
`core/ctx.lua`, so this writes directly to `ngx.var`. We expected it to persist 
since the access phase runs after rewrite-phase `set` directives. **Did not 
work.**
   
   ### 2. `ctx.var.http_x_forwarded_port = "443"`
   
   Sets the request header via `ngx.req.set_header()`, but `proxy_set_header` 
reads `$var_x_forwarded_port` (nginx variable), not `$http_x_forwarded_port`. 
The template has no `if ($http_x_forwarded_port)` block. **No effect.**
   
   ### 3. `proxy-rewrite` plugin with `headers.set.X-Forwarded-Port: "443"`
   
   Same mechanism as #2 — sets the request header, overridden by 
`proxy_set_header`. **No effect.**
   
   ### 4. `serverless-pre-function` in balancer phase
   
   Balancer runs inside the `upstream {}` block, separate from the `location 
{}` block where `proxy_set_header` lives. **No effect.**
   
   ### 5. `serverless-post-function` (header_filter) rewriting the Location 
response header
   
   ```lua
   local loc = ngx.header["Location"]
   if loc then ngx.header["Location"] = loc:gsub(":9182", "") end
   ```
   
   Fixes the initial 302 redirect header, but the response **body** (HTML, JS, 
JSON) still contains URLs with `:9182`. Partial workaround only.
   
   ### 6. `nginx_config.http_server_location_configuration_snippet`
   
   Snippet is injected before `set $var_x_forwarded_port $server_port;` in the 
template. Any `set` we add runs earlier in the rewrite phase and gets 
overridden.
   
   ## What we need help with
   
   We've exhausted the approaches we could find in the docs and issues. We'd 
appreciate guidance on:
   
   - Is there a supported way to override `X-Forwarded-Port` when using 
`proxy_protocol.listen_https_port`?
   - Is `ctx.var.var_x_forwarded_port` supposed to work for this use case? If 
so, what might prevent the write from persisting to `proxy_set_header` 
evaluation?
   - Is there a config option or plugin we're missing that handles port 
translation in proxy protocol setups?
   
   ## Minimal Reproduction
   
   1. Deploy APISIX 3.16.0 with TLS enabled and 
`proxy_protocol.listen_https_port: 9182`
   2. Place a TCP load balancer in front that sends Proxy Protocol v2 to port 
9182
   3. Configure a route to any upstream that uses `X-Forwarded-Port` for URL 
construction (e.g., Keycloak)
   4. Access the service — upstream receives `X-Forwarded-Port: 9182` and 
generates incorrect redirect URLs
   
   ```bash
   $ curl -svk https://your-domain.com/admin/ 2>&1 | grep -i "location"
   < location: https://your-domain.com:9182/admin/master/console/
   ```
   
   ## Related
   
   - #4942 — X-Forwarded-Port rewriting issues
   - #8226 — Related PR
   
   
   ### Environment
   
   - **APISIX version:** 3.16.0
   - **Helm chart:** 2.14.0
   - **Deployment:** Kubernetes (OKE) with APISIX Ingress Controller CRDs
   - **Load Balancer:** OCI Load Balancer — TCP listeners (TLS passthrough) 
with Proxy Protocol v2
   - **Architecture:** Client → LB (TCP:443, PP v2) → APISIX (TLS termination 
on port 9182) → Upstream (HTTP)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to