分析WhatsApp的代理模式并自建代理

/ 0评 / 0

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代理功能。

本文分为如下三个部分


1. 通过openssl生成证书,加密客户端与代理间的通讯

1.1 生成 openssl.cnf

在生成 SSL 证书的过程中,官方脚本会自动创建一个 openssl.cnf 文件,用于配置证书的扩展属性,例如密钥用途以及 Subject Alternative Names (SANs,备用名称)。以下是 openssl.cnf 文件的生成方式及其详细说明。

1.2 openssl.cnf 的生成逻辑

脚本会首先创建基础配置内容,包括以下部分:

官方仓库当中使用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.comSSL_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 是为容器化环境设计的,其特点包括:

  1. 文件路径:依赖容器内部路径(如 /etc/haproxy/ssl/)。
  2. 端口绑定:通常绑定标准端口(如 HTTP 的 80,HTTPS 的 443)。
  3. 默认设置:适配容器化环境的高可用性和灵活性。

在非容器化环境中直接运行时,需要对路径和端口等进行调整,以适配实际运行环境。

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 前端配置

根据需求调整端口绑定和路径:

  1. HTTP 前端:仅绑定端口 8080。
  2. HTTPS 前端:绑定到 8443 端口,并使用生成的 /root/whatsapp_proxy/cert/proxy.whatsapp.net.pem 证书。
  3. XMPP 前端:仅保留备用端口 8222。
  4. 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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.