Delete X-Forwarded- Headers with Kong

Read this if you want to delete x-forwarded- headers with Kong gateway.

Delete X-Forwarded- Headers with Kong

Recently I needed to delete several x-forwarded-<whatever> headers using Kong Gateway.

At the beginning I was doing it with the request-transformer plugin which didn't work because my theory is that since Kong runs on Nginx, when Kong deleted those headers Nginx recreated them right away just before sending the request to the backend.

The solution is to configure a post-function plugin to then tell Nginx to clear those headers before sending the request to the backend. A good thing is that we can apply this behavior only to certain routes or services or globally as well without messing around with Nginx directly.

I created a dummy API that returned me the headers and body of the request I sent. That allowed me to prove that the solution worked properly.

The JSON object that represents the plugin configuration is the following:

{
	"route": {
		"id": "<replace_with_valid_route_id>"
	},
	"name": "post-function",
	"config": {
		"access": [
			"ngx.var.upstream_x_forwarded_host=nil",
			"ngx.var.upstream_x_forwarded_port=nil",
			"ngx.var.upstream_x_forwarded_prefix=nil",
			"ngx.var.upstream_x_forwarded_proto=nil",
			"ngx.var.upstream_x_forwarded_path=nil",
			"ngx.var.upstream_x_forwarded_for=nil"
		]
	},
	"enabled": true
}

It will be applied to the specified route.

The CURL should look similar to this (JSON object has been minified):

curl PUT https://127.0.0.1:8444/plugins \
--data-raw '{"name":"post-function","route":{"id":"182f4f4f-f4bd-4e69-adb0-963879529fff"},"config":{"access":["ngx.var.upstream_x_forwarded_host=nil","ngx.var.upstream_x_forwarded_port=nil","ngx.var.upstream_x_forwarded_prefix=nil","ngx.var.upstream_x_forwarded_proto=nil","ngx.var.upstream_x_forwarded_path=nil","ngx.var.upstream_x_forwarded_for=nil"]}}' \
--header 'Content-Type: application/json' \
--insecure | jq '.'

If everything went well with the CURL, Kong will return the plugin object which will be longer. It may look similar to this:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: PUT
100   944  100   602  100   342  19838  11270 --:--:-- --:--:-- --:--:-- 19838
{
  "route": {
    "id": "182f4f4f-f4bd-4e69-adb0-963879529fff"
  },
  "consumer": null,
  "protocols": [
    "grpc",
    "grpcs",
    "http",
    "https"
  ],
  "name": "post-function",
  "config": {
    "log": [],
    "functions": [],
    "header_filter": [],
    "body_filter": [],
    "certificate": [],
    "access": [
      "ngx.var.upstream_x_forwarded_host=nil",
      "ngx.var.upstream_x_forwarded_port=nil",
      "ngx.var.upstream_x_forwarded_prefix=nil",
      "ngx.var.upstream_x_forwarded_proto=nil",
      "ngx.var.upstream_x_forwarded_path=nil",
      "ngx.var.upstream_x_forwarded_for=nil"
    ],
    "rewrite": []
  },
  "service": null,
  "id": "7d2065fa-8cfc-472f-b53f-1c4adad31298",
  "created_at": 1684941171,
  "tags": null,
  "enabled": true
}

After this, I sent a request again to my dummy API and the headers were successfully removed from the request.

As of today (May 24th, 2023) this solution works perfectly.

Sources: