Kong / kong

🦍 The Cloud-Native API Gateway and AI Gateway.
https://konghq.com/install/#kong-community
Apache License 2.0
38.78k stars 4.77k forks source link

Kong PDK kong.service.set_target() not properly setting the "Host" header #5945

Closed jonhy-bigodes closed 4 years ago

jonhy-bigodes commented 4 years ago

Summary

While developing a plugin that changes the upstream target host/port it was noticed that the "Host" header that is set while invoking PDK function kong.service.set_target() is not setting the port subcomponent, only the host part. This is not conforming with RFC7230, Section 5.4. When a target service uses an intermediate load balancer (eg: HAProxy) and the service uses a non-standard http/https port, the service request call fails at the load balancer level since the "Host" header is missing the port information (set by kong.service.set_target()).

Steps To Reproduce

  1. Create a route and service
  2. Develop a new plugin or use serverless functions plugin "pre-function" to change both the upstream host and port (eg:10000) using PDK kong.service.set_target()
  3. Activate the plugin over step 1. route or service
  4. Setup a mock server (one-liner in Linux: while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; } | nc -4 -l 10000 -q 1; done)
  5. Hit Kong route configured in step 1 with a request. Check mock server headers input, it will miss the port subcomponent. This causes issues when load balancers are used as the service upstream address.

Additional Details & Logs

kikito commented 4 years ago

Hello, thanks for reporting this. Could you please try with a more recent version of Kong?

jonhy-bigodes commented 4 years ago

Sure, no problem. With the latest version the bug still happens. The problem is located at the PDK code https://github.com/Kong/kong/blob/master/kong/pdk/service.lua (line 99): ngx.var.upstream_host = host

This _upstreamhost variable drives the "Host" header and is missing the port subcomponent. Just changing code to ngx.var.upstream_host = host .. ":" .. port should fix it.

In the meantime, the workaround is setting the "Host" header programmatically after the _kong.service.settarget() call.