We have several virtual (Ubuntu) servers running in our company. Each has its network connection bridged, so it gets its own IP address from the router (DHCP-reserved). We need to run several websites with their own subdomains.
We have our top domain (let's say example.com)
Then we have sub1.example.com, sub2.example.com, and sub3.example.com
The simplest way to do this seemed was to run a reverse-proxy (so that in the future we could move some to cloud and use load balancing).
I've set up a new VM with Ubuntu 20.04 LTS running NGINX and had it configured as reverse-proxy.
I currently have 3 configurations:
redirect_https:
server {
listen 80;
listen [::]:80;
server_name *.example.com;
return 301 https://$host$request_uri;
}
ssl-proxy:
server {
listen 443 ssl;
server_name example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass https://10.10.x.y;
proxy_http_version 1.1;
}
ssl_certificate /etc/<path_to_cert>/fullchain.pem;
ssl_certificate_key /etc/<path_to_cert>/privkey.pem;
}
ssl-proxy-subdomains:
server {
listen 443 ssl;
server_name sub1.example.com sub2.example.com sub3.example.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded_Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
proxy_pass https://10.10.x.y;
proxy_http_version 1.1;
}
ssl_certificate /etc/<path_to_cert>/fullchain.pem;
ssl_certificate_key /etc/<path_to_cert>/privkey.pem;
}
This all works fine.
In order to be able to edit our sites from home, I wanted to configure the proxy to pass SSH traffic as well, that's where I get confused.
I have read a number of posts here, on other sites, NGINX documentation, I don't seem to figure this out.
I followed the example right out of documentation: https://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html
Seems pretty straightforward.
My config is virtually identical (only changed parts relevant to my company, like IP addresses, etc.)
For the sake of completeness, the example I used is titled Selecting an upstream based on server name
My config (modified):
map $ssl_preread_server_name $name {
example.com backend_main;
sub1.example.com backend_1;
sub2.example.com backend_2;
sub3.example.com backend_3;
default backend_proxy;
}
upstream backend_main { server 10.10.x.y:22; }
upstream backend_1 { server 10.10.x.y:22; }
upstream backend_2 { server 10.10.x.y:22; }
upstream backend_3 { server 10.10.x.y:22; }
upstream backend_proxy { server 10.10.x.y:22; }
server {
listen 2222;
proxy_pass $name;
ssl_preread on;
}
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log /var/log/nginx/proxy-access.log proxy;
error_log /var/log/nginx/proxy-error.log;
The above chunk of code lies within stream {...} block in /etc/nginx/nginx.conf after the html {...} block (right before the commented mail {...} block).
The router takes external port 22 and forwards it to internal port 2222 of the reverse proxy.
The problem I'm facing is that map always selects the default option. If I remove/comment the default, I can't connect at all. If I change the IP address on the default, it connects me to that server, but again, only whatever "default" is.
The end goal is to be able to ssh directly into one of the subdomains (e.g. ssh user@sub1.example.com). At the moment I have to ssh into one server to which I gave myself external access, then ssh an internal one from there.
The only thing that comes to mind is that this may not run well with the existing HTTPS proxy, but perhaps stream module should be able to handle those as well (and if it does, will I be able to set headers? otherwise the backends only see the requests coming from the reverse proxy).
I have a suspicion that this is a simple issue and that I overlooked something, but after spending 8 hours of reading and trying different things, I feel it's time to ask for help...
streamblock ofNGINXcould help me. And it does (no weird certificate errors...), but as others have stated below, SSH does not use SNI, so the host name is not passed along with the request, which explains why thedefaulthost was always selected. When I commented out thedefault, in the error log I could see something likehost "-" not found. That should've been a sign to me that the host name is not being sent... – nurchi Jul 03 '20 at 15:54