-
Notifications
You must be signed in to change notification settings - Fork 3k
SSL Passthrough #853
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
Comments
I have to say this would be a big feature. This would make dealing with cooler larger projects a breeze. Matrix/synapse comes to mind which is a pain to setup behind a separate proxy. It would be nice if you could just forward a specific domain 80 and 443 traffic to a service on a separate machine that does the ssl stuff. |
After spending a lot of time getting this to work in NGINX itself - I realize this request may not fulfill everyone's needs even if it was implemented according to what NGINX supports. NGINX can do SSL passthru, but it can't do it on the same ports being serviced for normal NGINX services. You can do only one or the other. For example, let's say you have some sites on 443 using normal NGINX SSL. You cannot then also use NGINX to perform passthrough to a VM that has its own certificates. You would have to use a different port, such as 8443 or a custom port. The only other alternative would be another box and another public IP. I finally resolved my issue by switching back to pure NGINX and implementing passthru on 8443 and the rest of our sites on 443. NPM is a great tool but it has its limitations - perhaps someday I will revisit it and I will still recommend it to those who have less complex setups than I. |
for ssl pasthrough you need to use stream (npm now support it), but i think you can't use stream and http on the same port. |
SSL passthrough in nginx is complicated. So the only way to have ssl passthrough is by using a stream host. But in a stream host nginx has no idea what protocol is used by the data. Nginx can assume it is HTTP, but since it is HTTPS the data is encrypted, so even if nginx knows it is HTTP, he still does not now where to send this packet, as the target domain is encrypted as well. But there is a relatively new feature in nginx, which leverages Server Name Indication in TLS, where the domain is sent unencrypted in the HTTPS request. But this means the requesting client also has to send this SNI. But most modern browsers do, so let's just assume it is sent. Here's the next problem: nginx cant run a stream on the same port as other proxies. It's one stream per port, and a port with a stream attached can't have any other proxies attached. We can work around this by routing all HTTPS traffic through this single stream, which in turn forwards it either to the ssl passthrough server or back to nginx itself on a different port, which can now handle all normal proxies. As you can imagine this will come with a performance penalty of all other proxies being proxied twice, and it might become a bottleneck. That's why I have implemented it in this specific way: SSL Passthough is a new type of host which is strictly opt-in. Once you have opted in, all traffic is routed through the single stream as described above, but you will be able to add ssl passthrough hosts for a specific domain. Remeber: Enabling SSL passthrough might slow down other proxied services and might break access for devices / browsers which do not send the SNI information! |
I was looking for this feature as well. Since the above PR #1479 doesn't seem to have been merged, I baked my own quick fix. It's not pretty but seems to do the trick (not tested thoroughly yet). Sharing here as it might help others. Note that this approach makes designates an new port as the main input port for your NPM https traffic! This worked for me because I am behind NAT and could simply adjust the port forwarding for the public 443 port to a new port, and leave all the remaining NPM configuratio untouched. You might have to find another way if your NPM is directly listening on a public IP. So here goes: Add the following to your custom
This is more or less a straight copy from the nginx docs example (https://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html) with the addition of the npm -> localhost:443 default backend. You might still need http proxy hosts on port 80 to make letsencrypt challenges work to those passed-through hosts. |
Issue is now considered stale. If you want to keep it open, please comment 👍 |
Does this work for anyone else? I made these changes, got rid of backend2 (I only have one host I need to do SNI passthrough for) but all it did was break all my existing hosts and it never started listening on 12346. |
Still working for me with 2.11.1. But I noticed a rather severe caveat for security: This extra layer of proxying breaks access list functionality as for the npm backend now all requests appear to come from the localhost, such that IP filtering is not possible! |
Issue is now considered stale. If you want to keep it open, please comment 👍 |
Hi @gabuzi, thanks for sharing the solution. But I couldn't get this solution working for me. Like many others, I need to pass 443 to a VM which expects its own SSL service for a domain, NPM takes SSL service for other domains. With your solution, I add the script to stream.conf in Custom folder and update it with my own information accordingly. I can confirm the stream.conf has been read by nginx, but it doesn't pass 443. I mean if I request HTTPS to the domain, it responds "can't reach this page". HTTP works well to this domain which I pass HTTP with normal NPM forwarding configuration. Did I miss any configuration requirement in addition to the "stream.conf" file? What is the "12346" port? As per your note - "Note that this approach makes designates an new port as the main input port for your NPM https traffic!", is this the port 12346 you referred to? Do I need to open this port or forward it from the firewall? or any recommended configuration? Thanks in advance. |
Is your feature request related to a problem? Please describe.
Unable to pass through encrypted SSL connections to a server that doesn't need SSL encryption
Describe the solution you'd like
A clear option or configuration to enable SSL passthrough via stream or similar method.
Describe alternatives you've considered
Attempted to add code from links under additional context, host simply goes offline.
Additional context
This has been discussed in some other unclosed issues linked at the bottom, but this should be possible with modern NGINX using the stream function. I see that NPM has "Stream" but it only allows you to capture an entire port instead of a specified domain for forwarding to another internal host.
https://serversforhackers.com/c/tcp-load-balancing-with-nginx-ssl-pass-thru
https://stackoverflow.com/questions/38371840/ssl-pass-through-in-nginx-reverse-proxy
#235
#461
The text was updated successfully, but these errors were encountered: