Mir geht schon länger auf die nerven dass wir die private keys für alle unsre TLS zertifikate auf dem reverse-proxy, yxorp, liegen haben müssen. Hab mich jetzt hingesetzt und das mal gelöst:
Das problem das wir da haben ist folgendes: wir haben nur eine public IPv4 IP aber viele VMs. Das einfachste und das was wir aktuell machen ist dass auf v4 port 443 halt einfach der HTTP(s) reverse proxy horch, TLS aufmacht, und dann mit http unverschlüsselt an den internen upstream server weitergeht.
Was man jetzt machen kann ist dass der reverse proxy sich den hostnamen im TLS-SNI anschaut und dann abhängig davon den upstream server auswählt und dann aber den rohen TCP stream dorthin weiterschickt, d.h. der reverse proxy muss TLS dann garnicht aufmachen!
Das ist mit dem nginx ‘stream’ modul (docs) auch eigendlich schnell gemacht, nur hast du wieder ein problem: es kann nur ein nginx modul auf port 443 horchen. Da bin ich dann bei meinem ersten versuch an dem ganzen gescheitert weil ich ja den lokalen nginx auch weiterhin verwenden will und nur nach und nach VMs auf nativ TLS umstellen will.
Inzwischen ist mir aber die idee gekommen, man könnte doch einfach die lokalen sites einfach auf ner anderen port/IP horchen lassen. Also pro http seite immer so:
server {
listen [::1]:443 ssl;
}
und dann im nginx.conf
für den TLS-SNI stuff:
stream {
map $ssl_preread_server_name $selected_upstream {
default local_tls
}
upstream local_tls {
server [::1]:443;
}
server {
listen [2001:db8::1]:443;
proxy_pass $selected_upstream;
}
}
Das funktioniert dann soweit aber dann hat man das nächste problem: jetzt sieht es für alle server so aus als hätten die clients alle die ::1
als IP.
Nach etwas verzweifelt nginx doku lesen findet man aber dann die nette proxy_protocol
option für die http listen
direktive (docs). Damit kann man die client IP weiterreichen und die seiten sehen keinen unterschied.
Dafür dann in den site configs:
server {
listen [::1]:443 ssl proxy_protocol;
}
im globalen http {...}
oder in ner conf.d/*
config schalten wir das dann frei:
set_real_ip_from ::1/128;
real_ip_header proxy_protocol;
Das set_real_ip_from
ist ein safety feature damit nginx nicht einfach jedem unverschlüsselt dahergelaufenem plaintext PROXY header glaubt. Hier erlauben wir das einfach nur von localhost. Das real_ip_header proxy_protocol
aktiviert dann das ersetzen der nginx internen client IP mit dem was mit dem PROXY protocol daher kommt.
Zuletzt schalten wir noch in der stream modul config das senden der PROXY infos ein:
stream {
server {
proxy_protocol on;
}
}
alles andere bleibt gleich.