我在 AWS 上遇到了 HAProxy 配置问题。
问题是当我通过 SSL 发出请求时,它会触发两种类型的错误:
- 当我访问 https 时,出现以下错误:“纯 HTTP 请求已发送到 HTTPS 端口”
- 当我执行这样的 cli 命令时,
openssl s_client -connect 127.0.0.1:443
我收到以下响应:
subject=/serialNumber=XX/OU=GT98690993/OU=See www.rapidssl.com/resources/cps (c)13/OU=Domain Control Validated - RapidSSL(R)/CN=*.dev.qmerce.com issuer=/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
--- No client certificate CA names sent
--- SSL handshake has read 3031 bytes and written 415 bytes
--- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session:
Protocol : TLSv1.1
Cipher : ECDHE-RSA-RC4-SHA
Session-ID: 76AC086D608DCB4B02918B4DEDE6CD3223D4723B849CF2A896B7FA6C94382958
Session-ID-ctx:
Master-Key: CDA7D024B220290F162D9A591503D1503049E87C3A9A38475908DD3756DB45E1107430B1B164EA1D059023125D62E61C
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - de 78 c0 f7 cf 25 47 30-fe ec 39 34 62 45 95 fb .x...%G0..94bE..
0010 - 50 cb 99 d4 28 92 44 96-17 19 2d 6d c9 7f 42 4b P...(.D...-m..BK
0020 - a2 4c b8 e5 c6 69 ba 71-c8 cf 6d 1a 94 c8 2a 89 .L...i.q..m...*.
0030 - 89 24 e5 81 d6 68 06 3a-8d 40 63 7c a4 87 c8 51 .$...h.:.@c|...Q
0040 - af 8e a1 06 a9 d0 40 9f-ae d2 fd 57 27 62 80 74 [email protected]'b.t
0050 - 96 94 ae c2 36 ee 85 20-3b 01 78 bb 20 f9 f9 34 ....6.. ;.x. ..4
0060 - b9 f5 54 18 ad 45 89 ab-39 29 e1 56 a2 e5 e5 23 ..T..E..9).V...#
0070 - 74 00 65 0b 2c 85 db f9-d5 5b 32 da 49 ea 06 20 t.e.,....[2.I..
0080 - a3 ca e4 e0 05 62 85 89-de db 20 8d 2b 8f 05 b0 .....b.... .+...
0090 - 80 05 e9 34 ab 35 93 61-4d cc c8 d0 8b b0 02 d0 ...4.5.aM.......
Start Time: 1378712486
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
--- HTTP/1.0 408 Request Time-out Cache-Control: no-cache Connection: close Content-Type: text/html
<html><body><h1>408 Request Time-out</h1> Your browser didn't send a complete request in time. </body></html>
现在 haproxy 的配置文件是这样的:
global
log /dev/log local0 info
log /dev/log local0 notice
maxconn 4096
user haproxy
group haproxy
daemon
ca-base /etc/ssl/qmerce
crt-base /etc/ssl/qmerce
defaults
log global
maxconn 4096
mode http
option httplog
option dontlognull
# Add x-forwarded-for header.
option forwardfor
option http-server-close
timeout connect 5s
timeout client 30s
timeout server 30s
contimeout 5000
clitimeout 50000
srvtimeout 50000
# Long timeout for WebSocket connections.
timeout tunnel 1h
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
frontend public
# HTTP
bind :80
# Redirect all HTTP traffic to HTTPS
reqadd X-Forwrded-Proto:\ https if { ssl_fc }
reqadd X-Forwarded-Proto:\ http if !{ ssl_fc }
redirect scheme https if !{ ssl_fc }
# Example with CA certificate bundle
# bind :443 ssl crt dev.qmerce.com.key ca-file dev.qmerce.com.crt
# Example without CA certification bunch
bind :443 ssl ca-file dev.qmerce.com.crt crt qmerce.pem ecdhe secp521r1 ciphers !kDHE:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH
#prefer-server-ciphers ciphers !kDHE:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH verify required
# The node backends - websockets will be managed automatically, given the
# right base paths to send them to the right Node.js backend.
#
# If you wanted to specifically send websocket traffic somewhere different
# you'd use an ACL like { hdr(Upgrade) -i WebSocket }. Looking at path works
# just as well, though - such as { path_beg /socket.io } or similar. Adjust your
# rules to suite your specific setup.
#use_backend node if { path_beg /served/by/node/ }
# Everything else to Nginx.
use_backend normal_nginx if !{ ssl_fc }
default_backend nginx
frontend node
bind :8000 ssl crt qmerce.pem
default_backend node
backend normal_nginx
option httpchk HEAD /favicon.ico HTTP/1.0
# Wait 500ms between checks.
option httplog
option forwardfor
option httpclose
server web1 ec2-54-243-14-214.compute-1.amazonaws.com:443 cookie LSW_WEB01 check inter 500ms
backend node
# Tell the backend that this is a secure connection,
# even though it's getting plain HTTP.
reqadd X-Forwarded-Proto:\ https
balance leastconn
# Check by hitting a page intended for this use.
option httpchk HEAD /favicon.ico HTTP/1.0
timeout check 500ms
option ssl-hello-chk
# Wait 500ms between checks.
server node1 ec2-54-243-14-214.compute-1.amazonaws.com:8000 check inter 500ms
backend nginx
# Tell the backend that this is a secure connection,
# even though it's getting plain HTTP.
reqadd X-Forwarded-Proto:\ https
balance roundrobin
# Check by hitting a page intended for this use.
option httpchk HEAD /favicon.ico HTTP/1.0
timeout check 500ms
cookie LSW_WEB insert indirect nocache
option ssl-hello-chk
option abortonclose
stats enable
stats hide-version
stats realm Haproxy\ Statistics
stats uri /?qmerce_lb_stats
stats auth admin:admin
# Wait 500ms between checks.
server web1 ec2-54-243-14-214.compute-1.amazonaws.com:443 cookie LSW_WEB01 check inter 500ms
现在我完全不知道该怎么做了。我该如何解决这个问题?
答案1
对于 #1,如果您的 normal_nginx 后端服务器正在运行 https,HAProxy 将无法正确连接;如果不进行强制,它无法理解 https 后端。您可以使用 stunnel 说服它发出 SSL 请求。
对于 #2,您必须向 openssl 传递 cafile 或 capath,以便它验证服务器的证书。错误的其余部分并不令人担忧——它实际上是说您没有足够快地询问您想要什么,因此它断开了您的连接。