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(router) allow TLS passthrough in stream router #6757
Conversation
I love it when such features can be implemented with a small patch. |
@hbagdi Having them on the same port is not likely something Nginx support directly, but can be hacked by configuration. If one configures two "layers" of proxy, the first layer doesn't do TLS termination and when it matches certain SNI, it forward it a local port, which is a TLS port. Then theoritically you can have the port in the first layer accepts both type of traffic. |
That sounds like an uncomfortable and a risky hack to me that we should best avoid. |
It's actually not that terrible as it looks 😄 and it will be transparent to client. By configuration I was referring to two Routes in Kong, the nginx configuration doesn't need to be changed. Though it's indeed not a common case to use Kong itself as a upstream, but it's a common pattern in Nginx as I heard of. |
@hbagdi In reality proxying to itself does not impact performance that much. The bulk of the overhead is always inside the TLS termination which has to run expensive cryptography operations. Proxy to self, in reality is just few I very much feel that we need to support mixing terminated and non-terminated connections on the same port, otherwise the usefulness of Kong TLS proxy will become very limited. |
I do too. But it has to be transparent to the user, meaning, a user shouldn't need to create two routes in Kong.
it should just work. |
1534716
to
2b74669
Compare
Seems like we need to add more lines in this PR : ) Turning on https://github.com/Kong/kong/blob/master/spec/02-integration/05-proxy/22-reports_spec.lua#L41 is an example for this use case. So I'm proposing to make |
Discussed with @fffonion, the following design are proposed:
The advantage of this method is:
Note that we do not want to support mixing TLS and cleartext traffic on the same port, for reasons @fffonion already mentioned above. It will inevitable break a lot of cleartext protocol if we enable |
+1 to that. |
@hbagdi there will be two server blocks, since currently we can't control ssl termination dynamically in Lua
|
So if I'm understanding correctly, weather to terminate TLS or not will be
based on the protocol of Service? That seems odd. Routing decisions should
be based on routes only, isn't it?
…On Wed, Jan 27, 2021, 4:01 PM Wangchong Zhou ***@***.***> wrote:
@hbagdi <https://github.com/hbagdi> there will be two server blocks,
since currently we can't control ssl termination dynamically in Lua
match route based on SNI --- Service is tls --> unix domain socket -> local server block with tls termination -> Upstream
\ ___ Service is tcp -> Upstream
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#6757 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABD2EOKGLUI7BVWM52C636TS37TPHANCNFSM4WMPNRKA>
.
|
@hbagdi That has similar pattern in http subsystem, Service will determine how Kong "treat" the request. |
AFAIK, that error is generated at the time of route/service creation and not at runtime.
This doesn't seem correct. In HTTP sub-system, the certificate presented to downstream has nothing to do with Service resource because the route is not known during TLS (and hence Service is not known). I think the stream sub-system works similarly but I don't have enough experience with it to be sure. In Routes, we have the protocol - tcp or tls, SNI and port. I think what is missing is a field which dictates whether to terminate TLS or not. |
Hi, How are you? Haroldo |
Any updates on this PR? |
@haroldoproenca @mayocream We will revisit this PR in the near future releases, please hold for updates! |
Any updates on this PR? Thanks |
673c96e
to
c998e72
Compare
I was waiting for this moment that this PR have new commits! |
7ee8101
to
d705c3d
Compare
@@ -131,6 +139,71 @@ server { | |||
} | |||
} | |||
|
|||
> if stream_proxy_ssl_enabled 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.
normal request -> first server block -> upstream
tls passthrough request -> second server blocke - proxy_protocol -> third server block -> upstream
tls termination request -> second server block - proxy_protocol -> first server block -> upstream
ideally, when doing tls passthrough, we can directly go from second server block to upstream
but currently we can't turn proxy_protocol on/off from lua side, so there's an extra third
server block to offload the proxy_protocol. we can have something like .kong.tls.disable_proxy_protocol to make this better.
70b90d6
to
52507a2
Compare
}, | ||
entity_checks = { | ||
{ conditional_at_least_one_of = { if_field = "protocols", | ||
if_match = { elements = { type = "string", one_of = { "tcp", "tls", "udp", } } }, | ||
then_at_least_one_of = { "sources", "destinations", "snis" }, | ||
then_err = "must set one of %s when 'protocols' is 'tcp', 'tls' or 'udp'", | ||
then_err = "must set one of %s when 'protocols' is 'tcp', 'tls', 'tls_passthrough' or 'udp'", |
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.
Add tls_pasthrough
to the if_match statement (line 34)
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.
need to add some test in schema unit test as well
df018d3
to
bdec9c2
Compare
kong/runloop/handler.lua
Outdated
local protocols = route.protocols | ||
if protocols and protocols.tls then | ||
log(DEBUG, "TLS termination required, return to second layer proxying") | ||
var.kong_tls_preread_block_upstream = "unix:" .. kong.configuration.prefix .. "/stream_tls_terminate.sock" |
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.
This seems to be something we can cache once at load and no need to create new strings for each connection.
kong/init.lua
Outdated
@@ -742,6 +742,12 @@ function Kong.preread() | |||
|
|||
runloop.preread.before(ctx) | |||
|
|||
-- if proxying to a second layer TLS terminator is required | |||
-- abort further execution and return back to Nginx | |||
if ctx.stream_proxy_preread_terminate 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.
Instead of checking the flag, if we add a return value for runloop.preread.before
does that makes more sense? Flags are slower but more important it makes the control flow less clear :)
Summary
Adds the ability in route TLS traffic based on SNI without terminating the connection.
To let Kong does normal TLS termination
To let Kong does TLS passthrough
Full changelog
Issues resolved
Fix #5902 #6694
TODO: