Nginx流代理与HTTP代理用于SSL终止

我正在运行一个HTTP服务,并希望在SSL终止前面放置nginx。这可以通过两种方式实现;要么作为一个流代理。
stream {
    server {
        listen               443 ssl;
        ssl_certificate      /certs/fullchain.pem;
        ssl_certificate_key  /certs/privkey.pem;
        proxy_pass           ip-for-backend-service:80;
    }
}
或者作为一个HTTP代理
http {
    server {
        listen 443 ssl;
        ssl_certificate      /certs/fullchain.pem;
        ssl_certificate_key  /certs/privkey.pem;

        location / {
            proxy_pass       http://ip-for-backend-service:80;
            proxy_set_header ...;
        }
    }
}
从一瞥之下,似乎stream代理的配置要简单得多,因为您不需要添加大量额外的头部信息(如proxy_set_header等)和其他配置。 我正在尝试了解这两种方法之间的利弊,并且特别有以下几个问题: 1. 任何一种方法会泄露更多关于后端服务的信息吗?例如,ip-for-backend-service是否可见? 2. 任何一种方法能更好地防御攻击吗?我猜如果后端服务存在漏洞,那么通过这两种选项都是可见/可利用的? 3. 哪个选项更高效?我认为stream选项可能更快,因为它只是路由流量,中间没有HTTP服务器。

流不会终止SSL,所以实际上没有选择。 - Alexey Ten
1这并不是真的,你可以通过流配置来终止SSL连接,例如参考https://www.nginx.com/blog/tcp-load-balancing-udp-load-balancing-nginx-tips-tricks/#tlsTerminate、https://stackoverflow.com/a/39421271/5087136等。 - fredrikekre
哦,不知怎么错过了那部分。 - Alexey Ten
1个回答

无论使用哪种方法,上游IP地址都将保持隐藏。 至于其他方面:
  • stream肯定更快,因为执行的代码较少。然而,两者都是编写良好的C代码,当与网络延迟进行比较时,差异可能不明显。
  • 使用stream时,上游日志将只包含一个客户端IP地址(代理服务器的地址)。这可以通过proxy_bind指令进行更改,但需要额外的网络设置。另一方面,在http设置中添加X-Forwarded-For头很简单:

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
  • 使用stream时,上游服务器需要手动配置以考虑传入连接的安全性:例如,Tomcat需要在<Connector>元素上添加scheme="https"secure="true"。使用http代理和X-Forwarded-Proto头,上游服务器可以根据每个连接决定是使用HTTP还是HTTPS

设置的安全性问题是非常基于观点的: - 使用`http`代理,您可以限制将被代理的URI路径,因此您不会向公众暴露网站的管理部分, - 另一方面,通过增加对系统的额外计算负担(与直接访问上游服务器的替代方案相比),您更容易受到DDoS攻击的威胁。