我查看了本论坛和其他论坛上的各种答案,并尝试调试我的 HAProxy 配置 - 可惜没有成功。我是 HAProxy 的新手,在让它按照我想要的方式工作方面面临挑战。以下是背景。我希望客户端浏览器能够访问 HAProxy 服务器 1.2.3.4 的 IP,并指定路径 1.2.3.4/login,这应该将连接转发到 abcd.com/login,但不会将 abcd.com 服务器暴露给最终客户端浏览器。所有流量都应通过 HAProxy 服务器。为了实现这一点,我需要构建一个系统,让最终客户端输入 https/http://1.2.3.4/login然后客户端应该会看到来自https://abcd.com/login如果他们只输入 https/http://1.2.3.4他们应该从 https//abcd.com 获取内容。这是我的配置:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
option tcplog
mode tcp
timeout connect 10s
timeout client 20s
timeout server 20s
timeout client-fin 20s
timeout tunnel 1h
resolvers mydns
nameserver dns1 1.0.0.1:53
nameserver dns2 1.1.1.1:53
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 30s
hold refused 30s
hold nx 30s
hold timeout 30s
hold valid 10s
hold obsolete 30s
frontend https
bind *:80
bind *:443
mode tcp
acl login-end-point path_beg /login
use_backend abcd_login if login-end-point default_backend bk_app
backend bk_app
option http_proxy
option httpclose
option ssl-hello-chk
mode tcp
server site www.abcd.com:443 resolvers mydns
backend abcd_login
option http_proxy
option httpclose
option ssl-hello-chk
mode tcp
server abcdpanel abcd.com:443 resolvers mydns
# Map url path as ProxyPass does
reqirep ^(GET|POST|HEAD)\ /login/(.*) \1\ /\2
# Rewrite redirects as ProxyPassReverse does
acl response-is-redirect res.hdr(Location) -m found
rspirep ^Location:\ (http|https)://abcd.com\/(.*) Location:\ \1://abcd.com/login/\2 if response-is-redirect
我检查发现 HAProxy 正在监听 80 和 443 端口
sudo netstat -tulpn | grep 443
tcp 0 0 0.0.0.0:443 0.0.0.0:* 侦听 29464/haproxy
sudo netstat -tulpn | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* 侦听 29464/haproxy
A
wget --no-check-certificatehttp://1.2.3.4 给出 --2018-11-14 06:01:26-- http://1.2.3.4/ 连接到 1.2.3.4:80... 已连接。HTTP 请求已发送,正在等待响应... 未收到数据。正在重试。
尝试使用上述 https 会导致无法建立 SSL 连接。将 /login 添加到 1.2.3.4 请求没有任何区别。
我将非常感激任何关于如何修复错误的指导。
答案1
要检查 SSL 请求,您需要终止 haproxy 的 SSL 连接。这要求您在绑定到端口 443 时使用类似以下行来指定您的证书:
bind *:443 ssl crt /etc/ssl/secure/example.pem
测试时启用状态并在浏览器中查看状态可能会显示连接失败的位置。启用刷新功能运行时将提供相对最新的数据,而无需刷新屏幕。
stats enable
stats hide-version
stats refresh 30s
stats show-node
stats auth admin:password
stats uri /haproxy?stats
当代理到外部网站时,您可能会遇到 SSL 证书问题,因为某些网站会配置 SSL 来阻止中间人代理(攻击)。对于此类网站,您需要对 SSL 进行直通,并且您将无法检查请求。
答案2
谢谢@BillThor - 我很感激。我并没有试图终止 SSL,而是进行了一次直通。
我最终使用了 Apache,结果发现它非常简单。使用类似这样的方法
<VirtualHost *:443>
ServerAdmin <scrubbed>
DocumentRoot /var/www/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine On
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
# Set the path to SSL certificate
# Usage: SSLCertificateFile /path/to/cert.pem
SSLCertificateFile /etc/ssl/certs/<scrubbed>.crt
SSLCertificateKeyFile /etc/ssl/private/<scrubbed>.key
SSLCACertificateFile /etc/ssl/certs/<scrubbed>.ca-bundle
ProxyPreserveHost Off
ProxyPass "/" "https://<scrubbed>/"
ProxyPassReverse "/" "https://<scrubbed>/"
ServerName localhost
</VirtualHost>
上面的方法非常有效,无需调试。当然,我会根据需要想出如何进行更花哨的 URL 重写。