【发布时间】:2021-12-24 11:53:15
【问题描述】:
更新在底部,我有点解决了,但不确定解决方案是否正确。
我在 CentOS 上运行 Apache,并使用代理到 localhost 端口 8080,我使用 Gunicorn 运行 Flask 应用程序。此设置适用于 Apache 端口 80 (HTTP),我可以使用我的域 http://example.com 和浏览器连接到它,但现在我尝试设置 SSL/HTTPS,但它不起作用。
导航到https://example.com 尝试加载页面一段时间(比如 30 秒),然后显示 502 错误页面:
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET /.
Reason: Error reading from remote server
Apache 错误日志:
[proxy_http:error] [pid 30209] (103)Software caused connection abort: [client xx.xxx.xxx.xxx:60556] AH01102: error reading status line from remote server localhost:8080
[proxy:error] [pid 30209] [client xx.xxx.xxx.xxx:60556] AH00898: Error reading from remote server returned by /
Gunicorn 错误日志(前 7 行来自 Gunicorn 启动,不知道为什么此信息在错误日志中,后 3 行是 HTTPS 请求返回 502 错误时):
[29478] [INFO] Listening at: http://127.0.0.1:8080 (29478)
[29478] [INFO] Using worker: sync
[29480] [INFO] Booting worker with pid: 29480
[29481] [INFO] Booting worker with pid: 29481
[29482] [INFO] Booting worker with pid: 29482
[29483] [INFO] Booting worker with pid: 29483
[29484] [INFO] Booting worker with pid: 29484
[29478] [CRITICAL] WORKER TIMEOUT (pid:29480)
[29480] [INFO] Worker exiting (pid: 29480)
[29554] [INFO] Booting worker with pid: 29554
适用于 HTTP (/etc/httpd/conf/httpd.conf) 的 Apache 配置:
Listen 80
#other default config values here
<VirtualHost *:80>
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
IncludeOptional conf.d/*.conf
Apache 配置不适用于 HTTPS (/etc/httpd/conf.d/ssl.conf):
Listen 443 https
#other default config values here
<VirtualHost *:443>
#other default config values here too
SSLCertificateFile /etc/pki/tls/certs/cert.pem
SSLCertificateKeyFile /etc/pki/tls/private/cert.key
SSLProxyEngine on
ProxyPass / https://localhost:8080/
ProxyPassReverse / https://localhost:8080/
</VirtualHost>
如果我删除/评论 SSLProxyEngine、ProxyPass 和 ProxyPassReverse 行并重新启动 Apache,我会得到默认的 Apache 欢迎页面,并且 HTTPS 工作得很好,那么很明显问题出在代理中?
Flask 应用程序是由 Gunicorn 启动的:
gunicorn --config gunicorn_config.py app:app
gunicorn_config.py:
workers = 5
bind = '127.0.0.1:8080'
umask = 0o007
reload = True
accesslog = 'log_gunicorn_access.txt'
errorlog = 'log_gunicorn_error.txt'
app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello world!'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080)
再一次,这在使用 HTTP 导航到我的域时有效,但在使用 HTTPS 时无效。
有什么帮助吗?
更新:
我设法得到另一个错误。现在导航到https://example.com 会立即加载并显示 500 错误页面:
Proxy Error
The proxy server could not handle the request GET /.
Reason: Error during SSL Handshake with remote server
Apache 错误日志:
[proxy:error] [pid 32385] (502)Unknown error 502: [client xx.xxx.xxx.xxx:50932] AH01084: pass request body failed to [::1]:8080 (localhost)
[proxy:error] [pid 32385] [client xx.xxx.xxx.xxx:50932] AH00898: Error during SSL Handshake with remote server returned by /
[proxy_http:error] [pid 32385] [client xx.xxx.xxx.xxx:50932] AH01097: pass request body failed to [::1]:8080 (localhost) from xx.xxx.xxx.xxx ()
Gunicorn 错误日志中不再有任何错误。
我在 gunicorn_config.py 中添加了这两行:
keyfile = '/etc/pki/tls/private/cert.key'
certfile = '/etc/pki/tls/certs/cert.pem'
并确保运行 Gunicorn 的用户可以访问这两个文件 (chmod o+r cert.key/pem)。
不知道我是否应该这样更改它,因为我认为流量应该是这样的:客户端 --https--> Apache,然后是 Apache --http--> Gunicorn。
此外,HTTP (http://example.com) 不再有效,并给出了之前的 502 错误页面,但我猜想使用证书配置运行 Gunicorn 不再允许 HTTP,需要使用不同的配置运行应用程序两次)。
更新 2:
我通过将此行添加到虚拟主机内的/etc/httpd/conf.d/ssl.conf 添加了更多 Apache 日志记录:
LogLevel info
现在我在 Apache 错误日志中获得了更多信息:
[ssl:info] [pid 3808] [remote 127.0.0.1:8080] AH02411: SSL Proxy: Peer certificate does not match for hostname localhost
然后我在虚拟主机内的/etc/httpd/conf.d/ssl.conf 中添加了新行:
SSLProxyCheckPeerName off
现在我遇到了另一个 Apache 错误:
[ssl:info] [pid 3999] [remote 127.0.0.1:8080] AH02005: SSL Proxy: Peer certificate CN mismatch: Certificate CN: example.com Requested hostname: localhost
在虚拟主机内的/etc/httpd/conf.d/ssl.conf 中添加了新行:
SSLProxyCheckPeerCN off
Aaaand 现在导航到 https://example.com 可以正常工作,我从应用程序返回“Hello world”!
现在我想我的问题也需要更新:在这种情况下使用SSLProxyCheckPeerName off 和SSLProxyCheckPeerCN off 是不好的做法、错误或不安全吗? 或者有更好的方法吗? '认为没有办法在 localhost 上订购官方 SSL 证书?
【问题讨论】:
标签: apache flask ssl gunicorn mod-proxy