TL;DR:有几种方法可以完成您在此处寻找的内容。
遵循尽可能减少attack surface 的原则,除非绝对必要,否则通常最好不要将端口暴露给公共互联网。反向代理是完成此任务的绝佳方式。通常,您希望所有后端 Web 应用程序都通过 HTTPS 在端口 443 上进行反向代理,并且您可以访问每个服务:
- 具有不同的主机名,如
app1.example.com和app2.example.com,或
- 具有不同的子目录,例如
example.com/app1和example.com/app2
根据您选择的方法,配置可能会有很大差异,前一种情况使用多个server 块,或者后者使用location 块。无论哪种情况,我们都将使用upstream 和proxy_pass 指令。我将给出这两种情况的示例。
多个主机
如果您在前端使用多个主机名(或多个端口),则需要为它们创建多个 server 块:
# Nginx reverse-proxy configuration
upstream app1 {
server 10.176.225.83:8888;
}
upstream app2 {
server 10.176.225.83:8088;
}
upstream app3 {
server 10.176.225.83:8042;
}
upstream app4 {
server 10.176.225.83:8890;
}
server {
listen 443 ssl;
server_name app1.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app1;
}
}
server {
listen 443 ssl;
server_name app2.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app2;
}
}
server {
listen 443 ssl;
server_name app3.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app3;
}
}
server {
listen 443 ssl;
server_name app4.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app4;
}
}
这里有几点需要注意:
- 所有后端都已在顶部定义,使用
upstream 指令,现在可以按名称引用。
- 如果你不想这样做,你可以省略
upstream 块,proxy_pass 行看起来像这样:proxy_pass http://10.176.225.83:8888;
- 因为每个应用程序都在不同的主机名上提供服务,所以每个应用程序都有自己的
server 块。如果它们各自在不同的端口上提供服务,也会出现这种情况。
- 如果您在证书中定义了多个SANs,则每个
server 块中的ssl_certificate 和ssl_certificate_key 可以指向不同的证书,甚至可以指向同一个证书。
- 每个应用程序都可以通过自己的主机名访问,这些主机名都指向前端服务器:
- 应用程序 1:
https://app1.example.com
- 应用 2:
https://app2.example.com
- 应用程序 3:
https://app3.example.com
- 应用程序 4:
https://app4.example.com
多个目录
对于使用单个主机和端口的配置,从子目录为后端应用程序提供服务,您将使用单个 server 块和多个 location 块:
# Nginx reverse-proxy configuration
upstream app1 {
server 10.176.225.83:8888;
}
upstream app2 {
server 10.176.225.83:8088;
}
upstream app3 {
server 10.176.225.83:8042;
}
upstream app4 {
server 10.176.225.83:8890;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location /app1 {
proxy_pass http://app1;
}
location /app2 {
proxy_pass http://app2;
}
location /app3 {
proxy_pass http://app3;
}
location /app4 {
proxy_pass http://app4;
}
}
还有几点需要注意:
- 我们仍然像以前一样定义所有四个
upstream 服务。如果您更喜欢直接路线,您仍然可以省略它们。该指令在复杂的配置中更有用。
- 由于所有应用程序都由同一个主机名提供服务,因此它们共享一个
server 块,但它们各自的子目录具有单独的 location 块。
- 由于它们都共享相同的主机名,因此在这种情况下,服务器证书不需要多个 SAN。
- 每个后端应用程序都可以从前端服务器上的子目录获得:
- 应用程序 1:
https://example.com/app1
- 应用 2:
https://example.com/app2
- 应用程序 3:
https://example.com/app3
- 应用程序 4:
https://example.com/app4
TLS 配置
在任何一种情况下,您都需要配置 SSL 证书,由公共 CA 或您的内部 PKI(如果适用)签名。如果您的应用程序要面向公众,则需要使用公共证书。然后你将他们的位置添加到上面的 Nginx 配置中。
进一步阅读
对于现实世界的示例,您可以查看我用于 Genieacs TR-069 服务器的 Nginx 配置,其中 implements SSL 和 reverse proxies 其他几个服务,尽管在它们的原始端口上,而不是 443。如果您想将它们保留在其原始端口上,这可能会很有用。
Nginx 站点也有一个关于反向代理基本配置的decent primer。