为什么是使用haproxy作为反代,而不是nginx,或者iptables,就不细说了,因为haproxy更高效简洁,性能更优秀!这是我几个月来的使用和验证。
注意:下面的配置是针对80端口(源站,可以开启cf cdn),但是没有针对https(443),如果有需要可以问ai怎么修改配置文件。
安装haproxy
一键脚本
curl -sS -O https://raw.githubusercontent.com/woniu336/open_shell/main/haproxy-k.sh && chmod +x haproxy-k.sh && ./haproxy-k.sh
安装
apt install haproxy -y
systemctl start haproxy
systemctl enable haproxy
编辑haproxy
nano /etc/haproxy/haproxy.cfg
内容如下
参考:https://github.com/woniu336/open_shell/blob/main/haproxy.cfg
global
log /dev/log local0 warning
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
maxconn 10000
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
defaults
log global
mode http # 改为 http 模式
option dontlognull
option httplog # 启用 HTTP 日志
option http-keep-alive
option forwardfor # 传递客户端真实IP
timeout connect 5s # 连接超时增加
timeout client 30s # 客户端超时增加
timeout server 30s # 服务器超时增加
timeout http-keep-alive 15s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend http-in
bind *:80
# 如果要添加更多域名到 backend1,继续在同一行添加
acl domain1 hdr(host) -i 123.com 789.com
acl domain2 hdr(host) -i 456.com
use_backend backend1 if domain1
use_backend backend2 if domain2
# 默认后端
default_backend backend1
backend backend1
server server1 8.8.8.8:80 check
backend backend2
server server2 3.3.3.3:80 check
路由规则
如果要添加更多域名到 backend1,继续在同一行添加:
acl domain1 hdr(host) -i 123.com 789.com example.com
把 example.com 替换成你实际要添加的域名即可。
根据配置:
123.com (domain1) → backend1 → 8.8.8.8:80
456.com (domain2) → backend2 → 3.3.3.3:80
配置中的对应关系:
acl domain1 hdr(host) -i 123.com
acl domain2 hdr(host) -i 456.com
use_backend backend1 if domain1
use_backend backend2 if domain2
所以:
访问 123.com 的请求会被路由到 backend1(服务器 8.8.8.8:80)
访问 456.com 的请求会被路由到 backend2(服务器 3.3.3.3:80)
其他未配置的域名或直接IP访问会走默认后端 backend1
启动服务
修改完成后,为了避免格式报错,执行以下命令
echo "" >> /etc/haproxy/haproxy.cfg
验证
haproxy -c -f /etc/haproxy/haproxy.cfg
显示Configuration file is valid
即正确
如果没有错误,重启服务
systemctl restart haproxy
检查状态
systemctl status haproxy
获取客户端ip
既然是路由源站的80端口,那么必然要开启cdn,当然是开启大善人的cdn,
如果不做如下设置会获取不到客户端ip,没法看站点日志,
如果是宝塔面板,建议放在以下位置
mkdir -p /www/server/panel/vhost/nginx/cf_real_ip
nano /www/server/panel/vhost/nginx/cf_real_ip/cloudflare.conf
如果是 amh
mkdir -p /home/wwwroot/lnmp01/vhost/cf_real_ip
nano /home/wwwroot/lnmp01/vhost/cf_real_ip/cloudflare.conf
在 cloudflare.conf 中添加所有 Cloudflare IP
注意:需要额外添加你的 HAProxy 服务器 IP
# Cloudflare IP ranges
# HAProxy IP
set_real_ip_from 你的HAProxy服务器IP;
# Cloudflare IPv4
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
# Cloudflare IPv6
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
然后在你的网站配置文件中引用,例如宝塔面板
server
{
listen 80;
server_name 123.com;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/123.com;
include /www/server/panel/vhost/nginx/cf_real_ip/cloudflare.conf;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
...
仅添加如下内容
include /www/server/panel/vhost/nginx/cf_real_ip/cloudflare.conf;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
记得重载nginx
amh面板站点配置
include /home/wwwroot/lnmp01/vhost/cf_real_ip/cloudflare.conf;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
记得重载nginx
到此就完工了,然后域名解析到反代服务器ip(haproxy),开启cf cdn (灵活模式)
还能正常查看网站日志(在源站查看)
https配置
我建议既然是443端口,那么我们使用另外一台服务器,
对国内用户友好的线路服务器,不和上面的80配置混合在一起,避免混乱。
301可以在源站设置
新建证书目录
mkdir -p /etc/haproxy/certs
重点(源站不需要配置证书)
把域名证书的fullchain.pem和privkey.pem(不一定是这两个名称的证书),合并成一个以域名为名称的.pem文件,例如 123.com.pem
申请证书的方式很多,就不一一细说了。
意思就是把这两个文件里面的内容拷贝到一个文件中,以.pem结尾,把pem证书传到/etc/haproxy/certs目录,
如果有多个域名依次类推,HAProxy会根据客户端的SNI(Server Name Indication)自动选择对应的证书:
- 访问
123.com
→ 使用123.com.pem
- 访问
456.com
→ 使用456.com.pem
配置如下
参考:https://github.com/woniu336/open_shell/blob/main/443_haproxy.cfg
优化版参考(不推荐):https://github.com/woniu336/open_shell/blob/main/443_haproxys.cfg
推荐以下配置
global
log /dev/log local0 warning
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
maxconn 10000
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
defaults
log global
mode http # 改为 http 模式
option dontlognull
option httplog # 启用 HTTP 日志
option http-keep-alive
option forwardfor # 传递客户端真实IP
timeout connect 5s # 连接超时增加
timeout client 30s # 客户端超时增加
timeout server 30s # 服务器超时增加
timeout http-keep-alive 15s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend http-in
bind *:80
redirect scheme https code 301 # 所有HTTP流量强制跳转HTTPS
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
# 安全头
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
#http-response set-header X-Frame-Options "SAMEORIGIN"
#http-response set-header Content-Security-Policy "frame-ancestors 'self'"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
# 路由逻辑,如果要添加更多域名到 backend1,继续在同一行添加
acl domain1_https hdr(host) -i 123.com 456.com
use_backend backend1 if domain1_https
# 默认后端
#default_backend backend1
backend backend1
server server1 8.8.8.8:80 check inter 10s rise 3 fall 3
注意:如果站点有播放器,注释掉以下两项安全头
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header Content-Security-Policy "frame-ancestors 'self'"
验证
haproxy -c -f /etc/haproxy/haproxy.cfg
重载服务
systemctl restart haproxy
检查状态
systemctl status haproxy
测试证书是否匹配
for domain in 123.com 456.com; do
echo "Testing $domain:"
echo | openssl s_client -connect $domain:443 -servername $domain 2>/dev/null | openssl x509 -noout -subject
echo "---"
done
获取真实客户端ip,在源站点配置文件添加如下内容
set_real_ip_from 你的反代ip;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
如果是两台服务器做负载均衡,默认轮询模式
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
# 安全头配置
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
#http-response set-header X-Frame-Options "SAMEORIGIN"
#http-response set-header Content-Security-Policy "frame-ancestors 'self'"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header Referrer-Policy "strict-origin-when-cross-origin"
# 路由规则
acl domain1_https hdr(host) -i 123.com 456.com 789.com # 修改,添加了789.com
use_backend backend1 if domain1_https
# 默认后端
default_backend backend1
backend backend1
server server1 8.8.8.8:80 check inter 10s rise 3 fall 3
server server2 3.3.3.3:80 check inter 10s rise 3 fall 3 # 将原backend2中的server2移过来
检测
安装socat
sudo apt update
sudo apt install socat
检测
echo "show info" | sudo socat unix-connect:/run/haproxy/admin.sock - | grep -iE 'conn|session'
或者
echo "show info" | socat unix-connect:/run/haproxy/admin.sock stdio
检测ssl会话重用
echo "show info" | socat stdio /run/haproxy/admin.sock | grep -E "(SslFrontendSessionReuse|SslCache|SslFrontendKey)"
根据提供的信息,HAProxy 的状态如下:
- Maxconn 和 Hard_maxconn:都是10000,表示配置的最大并发连接数和系统支持的最大连接数上限为10000。
- CurrConns:当前活跃连接数为148,远低于最大连接数10000(使用率仅为1.48%)。
- CumConns:累计连接数已经达到11850550(约1185万),说明服务已经处理了大量连接。
- ConnRate:当前新建连接速率是19个/秒,处于较低水平。
- MaxConnRate:历史最大新建连接速率是150个/秒。
分析:
- 并发连接情况:当前活跃连接数(148)远低于最大连接数(10000),所以没有超出并发限制。
- 性能状况:系统压力很小,连接率也不高(19/秒),历史最大连接率150/秒也远未达到系统瓶颈(因为最大连接数是10000,即使每个连接持续1秒,理论上也可以支持10000/秒的连接率,但实际上连接持续时间和并发模型会影响实际能力)。
其他设置
通过以下方式来更好地处理默认后端,禁止IP访问和未配置域名的连接
参考:https://github.com/woniu336/open_shell/blob/main/haproxy_config.txt
配置地址:
- IP访问检测和拒绝
- 使用正则表达式检测Host头是否为IP地址格式
- 直接拒绝IP访问请求
- 无Host头检测
- 检测没有Host头的请求并拒绝
- 未配置域名拒绝
- 创建包含所有允许域名的ACL
- 拒绝所有不在允许列表中的域名访问