0. 缘由
WhatsApp是常见的端到端加密通讯软件,但是在国内无法很好地进行连接,一个方案是使用代理服务器来连接,如果使用全局代理或者分流方案的话,很多时候WhatsApp仍然会报告“连接中”,即便打开了全局代理也是一样。
好在WhatApp官方提供了代理功能,在软件的“存储空间和数据”菜单中,可以找到“代理“选项,该代理需要使用WhatApps官方的代理脚本,github仓库见:https://github.com/WhatsApp/proxy ,本质上是通过Haproxy软件对相关端口进行转发来达成,同时使用docker进行部署。
本文通过分析WhatsApp Proxy 仓库的 Docker 配置文件 proxy_config.cfg
推导出适合直接运行 HAProxy 的配置文件。同时,我们将首先说明如何生成所需的 SSL 证书,包括生成 openssl.cnf
配置文件的详细步骤,因为直接运行环境需要明确的证书路径和格式。
这样就不再需要部署一个Docker,同时可以直接使用Haproxy命令运行该配置文件来提供WhatsApp代理功能。
本文分为如下三个部分
- 通过openssl生成证书,加密客户端与代理间的通讯
- 分析官方Haproxy配置,生成直接使用的版本
- 运行Haproxy
1. 通过openssl生成证书,加密客户端与代理间的通讯
1.1 生成 openssl.cnf
在生成 SSL 证书的过程中,官方脚本会自动创建一个 openssl.cnf
文件,用于配置证书的扩展属性,例如密钥用途以及 Subject Alternative Names (SANs,备用名称)。以下是 openssl.cnf
文件的生成方式及其详细说明。
1.2 openssl.cnf
的生成逻辑
脚本会首先创建基础配置内容,包括以下部分:
- [req]:定义请求的扩展配置和名称。
- [v3_req]:定义证书的扩展属性,包括密钥用途和扩展密钥用途。
官方仓库当中使用proxy/src/generate-certs.sh当中的下面部分生成,摘录内容如下:
cat > openssl.cnf <<EOM
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
EOM
1.3 包含 SAN 的完整配置示例
假设 SSL_DNS=example.com,www.example.com
和 SSL_IP=192.168.1.1,10.0.0.1
,生成的文件如下:
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = 8.8.8.8
IP.1 = <你的公网IP地址>
通过这样的配置,证书可以支持多个域名和 IP 地址,请注意IP.1应当是你部署Haproxy的服务器的公网IP,而不能是私有IP。
1.4. 生成证书
WhatsApp Proxy 仓库提供了一个脚本 generate-certs.sh
,用户可以利用该脚本生成 HAProxy 所需的 SSL 证书。
下面简化该脚本,得以直接运行并生成相关证书,脚本逻辑和原仓库一致。以下是脚本的主要步骤及操作说明。
1.5 脚本内容
以下是自己的新 generate-certs.sh
脚本的完整内容,注意要在同目录下放置openssl.cnf文件:
# 生成 CA 私钥
openssl genrsa -out ca-key.pem 4096
# 生成 CA 证书
openssl req -x509 -new -nodes -key ca-key.pem -days 36500 -out ca.pem -subj "/CN=RandomCAValue"
# 生成 SSL 私钥
openssl genrsa -out key.pem 4096
# 生成 SSL CSR(证书签名请求)
openssl req -new -key key.pem -out key.csr -subj "/CN=RandomSSLValue.net" -config openssl.cnf
# 使用 CA 签署 CSR,生成 SSL 证书
openssl x509 -req -in key.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -days 3650 -extensions v3_req -extfile openssl.cnf
# 合并生成的 SSL 证书和密钥到一个文件
cat key.pem > proxy.whatsapp.net.pem
cat cert.pem >> proxy.whatsapp.net.pem
最终我们生成一个名为proxy.whatsapp.net.pem的证书文件,包含公钥和私钥
2. 分析官方Haproxy配置,生成直接使用的版本
2.1 官方代理仓库中Docker 配置文件的特点
Docker 配置文件 proxy_config.cfg
是为容器化环境设计的,其特点包括:
- 文件路径:依赖容器内部路径(如
/etc/haproxy/ssl/
)。 - 端口绑定:通常绑定标准端口(如 HTTP 的 80,HTTPS 的 443)。
- 默认设置:适配容器化环境的高可用性和灵活性。
在非容器化环境中直接运行时,需要对路径和端口等进行调整,以适配实际运行环境。
2.2 推导直接运行的 HAProxy 配置文件
以下是推导后的 HAProxy 配置文件,适合在非容器化环境中部署。
2.2.1 全局配置
全局配置保持不变,用于定义缓冲区大小、最大连接数和健康检查的间隔:
global
tune.bufsize 4096
maxconn 27500
spread-checks 5
ssl-server-verify none
2.2.2 默认设置
默认设置直接沿用,定义了连接和会话的超时时间,以及后端健康检查策略:
defaults
mode tcp
timeout client-fin 1s
timeout server-fin 1s
timeout connect 5s
timeout client 200s
timeout server 200s
default-server inter 10s fastinter 1s downinter 3s error-limit 50
2.2.3 监听配置(Prometheus 监控)
以下配置提供 Prometheus 的监控指标导出:
listen stats
bind :::8199
mode http
http-request use-service prometheus-exporter if { path /metrics }
stats uri /
2.2.4 前端配置
根据需求调整端口绑定和路径:
- HTTP 前端:仅绑定端口 8080。
- HTTPS 前端:绑定到 8443 端口,并使用生成的
/root/whatsapp_proxy/cert/proxy.whatsapp.net.pem
证书。 - XMPP 前端:仅保留备用端口 8222。
- WhatsApp.net 前端:保持不变,绑定到 587 和 7777 端口。
以下是前端配置:
# HTTP 前端配置
frontend haproxy_v4_http
maxconn 27495
bind ipv4@*:8080
default_backend wa_http
# HTTPS 前端配置
frontend haproxy_v4_https
maxconn 27495
bind ipv4@*:8443 ssl crt /root/whatsapp_proxy/cert/proxy.whatsapp.net.pem accept-proxy
default_backend wa
# XMPP 前端配置
frontend haproxy_v4_xmpp
maxconn 27495
bind ipv4@*:8222 accept-proxy
default_backend wa
# WhatsApp.net 前端配置
frontend haproxy_v4_whatsapp_net
maxconn 27495
bind ipv4@*:587
bind ipv4@*:7777
default_backend wa_whatsapp_net
2.2.5 后端配置
后端配置保持不变,用于转发流量到目标服务器:
# WhatsApp.net 后端服务
backend wa_whatsapp_net
default-server check inter 60000 observe layer4
server whatsapp_net_443 whatsapp.net:443
# 默认 HTTPS 和 XMPP 的后端服务
backend wa
default-server check inter 60000 observe layer4 send-proxy
server g_whatsapp_net_5222 g.whatsapp.net:5222
# 默认 HTTP 的后端服务
backend wa_http
default-server check inter 60000 observe layer4 send-proxy
server g_whatsapp_net_80 g.whatsapp.net:80
2.2.6 完整配置文件
以下是最终的完整配置:
global
tune.bufsize 4096
maxconn 27500
spread-checks 5
ssl-server-verify none
defaults
mode tcp
timeout client-fin 1s
timeout server-fin 1s
timeout connect 5s
timeout client 200s
timeout server 200s
default-server inter 10s fastinter 1s downinter 3s error-limit 50
listen stats
bind :::8199
mode http
http-request use-service prometheus-exporter if { path /metrics }
stats uri /
# HTTP 前端配置
frontend haproxy_v4_http
maxconn 27495
bind ipv4@*:8080
default_backend wa_http
# HTTPS 前端配置
frontend haproxy_v4_https
maxconn 27495
bind ipv4@*:8443 ssl crt /root/whatsapp_proxy/cert/proxy.whatsapp.net.pem accept-proxy
default_backend wa
# XMPP 前端配置
frontend haproxy_v4_xmpp
maxconn 27495
bind ipv4@*:8222 accept-proxy
default_backend wa
# WhatsApp.net 前端配置
frontend haproxy_v4_whatsapp_net
maxconn 27495
bind ipv4@*:587
bind ipv4@*:7777
default_backend wa_whatsapp_net
# WhatsApp.net 后端服务
backend wa_whatsapp_net
default-server check inter 60000 observe layer4
server whatsapp_net_443 whatsapp.net:443
# 默认 HTTPS 和 XMPP 的后端服务
backend wa
default-server check inter 60000 observe layer4 send-proxy
server g_whatsapp_net_5222 g.whatsapp.net:5222
# 默认 HTTP 的后端服务
backend wa_http
default-server check inter 60000 observe layer4 send-proxy
server g_whatsapp_net_80 g.whatsapp.net:80
3. 运行Haproxy
在任意公网服务器安装Haproxy后,使用如下命令运行,然后即可在WhatsApp当中连接
对话端口设定为:8443,保证客户端与代理间进行加密通讯
媒体端口设定为:587,保持默认即可。
haproxy -f ./proxy_config.cfg -V