Nginx can be configured to route to a backend, based on the server's domain name, which is included in the SSL/TLS handshake (Server Name Indication, SNI).
This works for http upstream servers, but also for other protocols, that can be secured with TLS.
- at least nginx 1.15.9 to use variables in ssl_certificate and ssl_certificate_key.
- check
nginx -V
for the following:... TLS SNI support enabled ... --with-stream_ssl_module --with-stream_ssl_preread_module
It works well with the nginx:1.15.9-alpine
docker image.
Pass the TLS stream to an upstream server, based on the domain name from TLS SNI field. This does not terminate TLS.
The upstream server can serve HTTPS or other TLS secured TCP responses.
stream {
map $ssl_preread_server_name $targetBackend {
ab.mydomain.com upstream1.example.com:443;
xy.mydomain.com upstream2.example.com:443;
}
server {
listen 443;
proxy_connect_timeout 1s;
proxy_timeout 3s;
resolver 1.1.1.1;
proxy_pass $targetBackend;
ssl_preread on;
}
}
Terminate TLS and forward the plain TCP to the upstream server.
stream {
map $ssl_server_name $targetBackend {
ab.mydomain.com upstream1.example.com:443;
xy.mydomain.com upstream2.example.com:443;
}
map $ssl_server_name $targetCert {
ab.mydomain.com /certs/server-cert1.pem;
xy.mydomain.com /certs/server-cert2.pem;
}
map $ssl_server_name $targetCertKey {
ab.mydomain.com /certs/server-key1.pem;
xy.mydomain.com /certs/server-key2.pem;
}
server {
listen 443 ssl;
ssl_protocols TLSv1.2;
ssl_certificate $targetCert;
ssl_certificate_key $targetCertKey;
proxy_connect_timeout 1s;
proxy_timeout 3s;
resolver 1.1.1.1;
proxy_pass $targetBackend;
}
}
The domain name can be matched by a regex pattern, and extracted to variables. See regex_names.
This can be used to choose a backend/upstream based on the pattern of a (sub)domain. This is inspired by robszumski/k8s-service-proxy.
The following configuration extracts a subdomain into variables and uses them to create the upstream server name.
stream {
map $ssl_preread_server_name $targetBackend {
~^(?<app>.+)-(?<namespace>.+).mydomain.com$ $app-public.$namespace.example.com:8080;
}
...
}
Your Nginx should be reachable over the wildcard subdomain *.mydomain.com
.
A request to shop-staging.mydomain.com
will be forwarded to shop-public.staging.example.com:8080
.
In Kubernetes, you can use this to expose all services with a specific name pattern.
This configuration exposes all service which names end with -public
.
A request to shop-staging-9999.mydomain.com
will be forwarded to shop-public
in the namespace staging
on port 9999
.
You will also need to update the resolver, see below.
stream {
map $ssl_preread_server_name $targetBackend {
~^(?<service>.+)-(?<namespace>.+)-(?<port>.+).mydomain.com$ $service-public.$namespace.svc.cluster.local:$port;
}
server {
...
resolver kube-dns.kube-system.svc.cluster.local;
...
}
}
Hi, may some questions if this would be even possible
i have various http reverse proxy server rules running, so far so good, now, if i would like to extend it to lets say as sample rdp through reverse proxy, would that be possible in some way.
sample code in nginx.conf (not working) while nginx is running on port 80 and 443 on ip 192.168.1.83
stream {
}
so, i d like to have rdp1.mydomain.de forwarding rdp or rdp2.mydomain.de to another client, while all other http requests should end on the RP with its own http server blocks ... but i actually cant find if either its possible to use rdp through this or howto route to general RP when no map matches the rule.
what makes me wonder when i see alot of online samples, most have stream server also listening on 443 while default is also 443 ... when i do this im getting the (obvious) error 443 in use ...
for any tipps, thanks ahead.