Nginx
如何將 nginx 中的(大多數)子域重寫為 API/代理的虛擬路徑
我有一個租戶設置,其中未知數量的公司可以創建此類帳戶
company.app.com
。後端伺服器將它們作為
: 5000/company/....
,那麼如何在 nginx 中進行重寫(不是重定向!)?這就是我所擁有的:server { listen 443 ssl http2; listen [::]:443 ssl http2; ssl on; ssl_certificate /etc/ssl/certs/cert.pem; ssl_certificate_key /etc/ssl/private/key.pem; server_name ????.app.com; <-- How? charset utf-8; location / { proxy_pass http://0.0.0.0:5000; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } }
現在的問題是我需要排除一小部分子域(www、dash、mail),那麼這是如何完成的呢?
可以將部分
Host
標頭/TLS SNI 欄位擷取到一個變數中,server_name
如下所示:server_name ~^(?<company>.+)\.app\.com;
稍後,該變數可以在
proxy_pass
目的地中使用:proxy_pass http://192.168.100.100:5000/$company/;
了解匹配規則很有用,這些規則在nginx 伺服器名稱文件中進行了說明。
我的評論會很長,請原諒。
參考 NGINX 文件:
萬用字元名稱只能在名稱的開頭或結尾包含星號,並且只能在點邊框上。名稱“www. .example.org”和“w .example.org”無效。但是,可以使用正則表達式指定這些名稱,例如“~^www..+.example.org$”和“~^w. .example.org$”。一個星號可以匹配多個名稱部分。名稱“ .example.org”不僅匹配www.example.org,還匹配www.sub.example.org。
當按名稱搜尋虛擬伺服器時,如果名稱匹配多個指定變體,例如萬用字元名稱和正則表達式匹配,則將選擇第一個匹配的變體,按以下優先順序:
- 確切名稱
- 以星號開頭的最長萬用字元名稱,例如“*.example.org”
- 以星號結尾的最長萬用字元名稱,例如“mail.*”
- 第一個匹配的正則表達式(在配置文件中的出現順序)
“.example.org”形式的特殊萬用字元名稱可用於匹配確切名稱“example.org”和萬用字元名稱“*.example.org”。
由於 NGINX 支持萬用字元,它可能像:
server { listen 443 ssl http2; listen [::]:443 ssl http2; ssl on; ssl_certificate /etc/ssl/certs/cert.pem; ssl_certificate_key /etc/ssl/private/key.pem; server_name *.app.com; charset utf-8; location / { proxy_pass http://0.0.0.0:5000; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } }
甚至:
server { listen 443 ssl http2; listen [::]:443 ssl http2; ssl on; ssl_certificate /etc/ssl/certs/cert.pem; ssl_certificate_key /etc/ssl/private/key.pem; server_name *corp.app.com; charset utf-8; location / { proxy_pass http://0.0.0.0:5000; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } }
兩者都應該工作。