-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
feat(conf) add port_maps configuration option #5861
Conversation
I think I mentioned this elsewhere, but can we add a warning in the logs when Kong is started in a container, and this option is not set? |
0879676
to
81c3555
Compare
127ee2d
to
9eb3c9a
Compare
I would recommend that we start small rather than going big from the beginning. The primary motivation for this feature is to correct set I've consulted with users on stream proxy and I do know of users who map different port on different LBs to the same port on Kong and then they route based on the port on Kong. This would be a break change for such setups. These should be one-offs and rare but my point stands. |
I don't see this being starting big. It is rather small. Nothing will be broken for anyone as nobody configures this as it is a new feature. You can also configure it for some ports and not all. In general you could also have environment where pods bind to random port. In such case you cannot practically do any routing by destination port as it is not kown before pod is launched (but the published port certainly will). This is far more common scenario. Also if you are running LB we still respect forwarded headers before reverting to this. |
Two fair points.
I'm not sure if this is a common scenario. It hasn't been so in my experience. With the points made, I think it is okay to proceed with this feature. |
565ad73
to
a6a3961
Compare
This is a bit problematic.
Perhaps later we can add support for container APIs where we can get this auto-configured. |
kong.conf.default
Outdated
@@ -29,6 +29,17 @@ | |||
# Each Kong process must have a separate | |||
# working directory. | |||
|
|||
#port_map = # When running Kong behind layer 4 port mapping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/port mapping/proxy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean layer 4 proxy? I don't think port-forwarding/-mapping can be described as proxy. Or what do you mean by this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote the whole thing. Not sure if it is any better.
kong.conf.default
Outdated
@@ -29,6 +29,17 @@ | |||
# Each Kong process must have a separate | |||
# working directory. | |||
|
|||
#port_map = # When running Kong behind layer 4 port mapping | |||
# (or port-forwarding), e.g. with | |||
# `docker run -p 80:8000`, you can use this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than providing commands here, it would help to provide examples like docker, L4 LBs in the cloud
kong.conf.default
Outdated
# (or port-forwarding), e.g. with | ||
# `docker run -p 80:8000`, you can use this | ||
# parameter to let Kong know about published | ||
# port when it differs from the one Kong is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
published port is ambiguous because every port at kong or lb is published in some sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Published port is a term that docker
uses for -p
. The port that Kong listens (in that case) is not published e.g. you can only access it from container. For public it is published by docker at port x. What do you suggest instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote the whole thing. Not sure if it is any better.
kong.conf.default
Outdated
@@ -29,6 +29,17 @@ | |||
# Each Kong process must have a separate | |||
# working directory. | |||
|
|||
#port_map = # When running Kong behind layer 4 port mapping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another point, it would be better to call this setting port_maps
because it can contain an array of values (csv based).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I pluralized it. We btw. have proxy_listen
not proxy_listeners
. And word mapping
to which map
refers to is ok to use in singular even in plural contexts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. My bad.
|
||
if (host_port_num and host_port_num >= MIN_PORT and host_port_num <= MAX_PORT) | ||
and (kong_port_num and kong_port_num >= MIN_PORT and kong_port_num <= MAX_PORT) | ||
then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a check to ensure that kong is configured to listen on kong_port_num?
I'm not sure how much scope creep happens because of this. I'll leave that up to you, Aapo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hbagdi I looked at it, and it is a bit complicated (listeners are parsed later). The good side is that if the port is not the one that Kong is not listening, it will not do anything. It is just excess configuration. I will create a card about this.
9d67a28
to
dd2aad2
Compare
@hishamhm I added this to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
### Summary Layer 4 port mapping (or port forwarding) is used a lot when running Kong inside a container. Common example is exposing ports 80 and 443 externally while running Kong inside a container with internal ports 8000 and 8443. It also allows Kong to started without elevated privileges as it is quite common that you need root-access to bind processes to TCP port < 1024. As this translation is done in many cases without using layer 4 proxy_protocol or layer 7 X-Forwarded-Port HTTP header, the Kong has no knowledge about the target port that client originally connected to. This PR adds `port_maps` configuration parameter: ``` #port_maps = # With this configuration parameter you can # let the Kong to know about the port from # which the packets are forwarded to it. This # is fairly common when running Kong in a # containerized or virtualized environment. # For example `port_maps=80:8000, 443:8443` # instructs Kong that the port 80 is mapped # to 8000 (and the port 443 to 8443), where # 8000 and 8443 are the ports the Kong is # listening to. # # This parameter helps Kong to set proper # forwarded upstream HTTP request header or to # get proper forwarded port with a Kong PDK # (in case other means determining it have # failed). It changes routing by a destination # port to route by a port from which packets # are forwarded to Kong, and similarly it # changes the default plugin log serializer to # use the port according to this mapping # instead of reporting the port Kong is # listening to. ``` This gets parsed into `kong.configuration.host_ports` table. E.g. `KONG_PORT_MAP="80:8000,443:8443"` where the first number (`80`/`443`) before `:` is the host published port and the second one (`8000`/`8443`) is the port that Kong is listening translates to following `kong.configuration.host_ports`: ```lua { [8000] = 80, ["8000"] = 80, [8443] = 443, ["8443"] = 443, } ``` This PR also adds a new nginx context variable `ngx.ctx.host_port` which contains this translated port. So instead of using `ngx.var.server_port` the more correct one in many cases is `ngx.ctx.host_port`. Kong PDK is also changed to take this in account when using: ``` local port = kong.request.get_forwarded_port() ``` This commit also changes the `X-Forwarded-Port` to use this. Additionally `stream routing` by `destination port` will use this too. Basic log serializer was changed to use `ngx.var.host_port` as well. Currently it is only usable in proxy/stream, so things like `admin api` is not affected by this.
@@ -125,6 +125,29 @@ | |||
# This value can be set to `off`, thus disabling | |||
# the plugin server and Go plugin loading. | |||
|
|||
#port_maps = # With this configuration parameter you can | |||
# let the Kong to know about the port from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/the Kong to/Kong/
# is fairly common when running Kong in a | ||
# containerized or virtualized environment. | ||
# For example `port_maps=80:8000, 443:8443` | ||
# instructs Kong that the port 80 is mapped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/the port/port/
# containerized or virtualized environment. | ||
# For example `port_maps=80:8000, 443:8443` | ||
# instructs Kong that the port 80 is mapped | ||
# to 8000 (and the port 443 to 8443), where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/the port/port/
# For example `port_maps=80:8000, 443:8443` | ||
# instructs Kong that the port 80 is mapped | ||
# to 8000 (and the port 443 to 8443), where | ||
# 8000 and 8443 are the ports the Kong is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"the ports on which Kong is listening"
# 8000 and 8443 are the ports the Kong is | ||
# listening to. | ||
# | ||
# This parameter helps Kong to set proper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/to set/set the/
Summary
Layer 4 port mapping (or port forwarding) is used a lot when running Kong inside a container. Common example is exposing ports 80 and 443 externally while running Kong inside a container with internal ports 8000 and 8443. It also allows Kong to started without elevated privileges as it is quite common that you need root-access to bind processes to TCP port < 1024.
As this translation is done in many cases without using layer 4 proxy_protocol or layer 7 X-Forwarded-Port HTTP header, the Kong has no knowledge about the target port that client originally connected to.
This PR adds
port_maps
configuration parameter:This gets parsed into
kong.configuration.host_ports
table.E.g.
KONG_PORT_MAP="80:8000,443:8443"
where the first number (80
/443
) before:
is the host published port and the second one (8000
/8443
) is the port that Kong is listening translates to followingkong.configuration.host_ports
:This PR also adds a new nginx context variable
ngx.ctx.host_port
which contains this translated port. So instead of usingngx.var.server_port
the more correct one in many cases isngx.ctx.host_port
.Kong PDK is also changed to take this in account when using:
This commit also changes the
X-Forwarded-Port
to use this. Additionallystream routing
bydestination port
will use this too. Basic log serializer was changed to usengx.var.host_port
as well.Currently it is only usable in proxy/stream, so things like
admin api
is not affected by this.