【Linux】HAProxy:结合 WG 实现内网 TCP 反代

本教程指导您通过 WireGuard 建立 VPN 隧道,并使用 HAProxy 在公网服务器上实现 TCP 反向代理,将公网请求转发到内网服务。教程目标是简单、直接、易于部署。

🧰 场景说明

角色 说明
公网服务器 公网 IP:1.2.3.4
内网服务器 无公网 IP,但可访问外网
WireGuard IP 公网服务器:10.0.0.1 内网服务器:10.0.0.2
示例域名 files.example.com(可选,非必须)

目标:

  • 通过公网服务器的 1.2.3.4:80 访问内网 HTTP 服务(如文件服务器)。
  • 通过公网服务器的 1.2.3.4:2222 访问内网 SSH 服务。

一、安装 WireGuard

在 公网服务器 和 内网服务器 上执行以下命令安装 WireGuard:

bash 复制代码
sudo apt update
sudo apt install wireguard -y

二、配置 WireGuard

1. 生成密钥对

在 公网服务器 和 内网服务器 上分别生成 WireGuard 密钥对(密钥和私钥是唯一对应的):

bash 复制代码
# 生成私钥并保存到 /etc/wireguard/private.key,生成对应的公钥保存到 /etc/wireguard/public.key
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
# 查看私钥内容(仅限本机使用,不可泄露)
cat /etc/wireguard/private.key
# 查看公钥内容(可提供给对端配置)
cat /etc/wireguard/public.key

记录两台服务器的私钥(private.key)和公钥(public.key)。

2. 配置公网服务器

在公网服务器上创建 /etc/wireguard/wg0.conf:

ini 复制代码
# 公网服务器的本地接口配置
[Interface]
PrivateKey = <公网服务器私钥>       # 本机私钥(只在本地使用,严禁泄露)
Address = 10.0.0.1/24               # 虚拟局域网内的 IP 地址
ListenPort = 51820                  # 监听的 UDP 端口(客户端通过此端口连接)

# 定义内网服务器为一个 Peer
[Peer]
PublicKey = <内网服务器公钥>        # 对端(内网服务器)的公钥
AllowedIPs = 10.0.0.2/32            # 允许从该 IP 发来的数据包进入 WireGuard 网络

3. 配置内网服务器

在内网服务器上创建 /etc/wireguard/wg0.conf:

ini 复制代码
# 内网服务器的本地接口配置
[Interface]
PrivateKey = <内网服务器私钥>       # 本机私钥(只在本地使用,严禁泄露)
Address = 10.0.0.2/24               # 虚拟局域网内的 IP 地址

# 定义公网服务器为一个 Peer
[Peer]
PublicKey = <公网服务器公钥>        # 对端(公网服务器)的公钥
Endpoint = 1.2.3.4:51820            # 公网服务器的 IP 和监听端口
AllowedIPs = 10.0.0.0/24            # 允许通过 VPN 访问的地址范围(这里是整个虚拟网段)
PersistentKeepalive = 25            # 防止 NAT 断连,每 25 秒发送一次心跳包(适合内网)

4. 启动 WireGuard

在两台服务器上启动 WireGuard:

bash 复制代码
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

5. 验证连通性

在任意服务器上测试 VPN 连接:

bash 复制代码
ping 10.0.0.1
ping 10.0.0.2

若能相互 ping 通,说明 WireGuard 配置成功。


三、通过公网服务器 SSH 访问内网服务器

1. 直接使用 ProxyJump

使用 OpenSSH 7.3+ 的 ProxyJump 选项,从本地机器通过公网服务器 SSH 登录内网服务器:

bash 复制代码
ssh -J user_public@1.2.3.4 user_internal@10.0.0.2
  • user_public:公网服务器的用户名
  • user_internal:内网服务器的用户名

2. 使用 SSH 配置文件

为简化操作,可编辑本地机器的 ~/.ssh/config:

text 复制代码
Host public-server
    HostName 1.2.3.4
    User user_public

Host internal-server
    HostName 10.0.0.2
    User user_internal
    ProxyJump public-server

保存后,直接运行:

bash 复制代码
ssh internal-server

即可自动通过公网服务器跳转登录内网服务器。


四、内网服务器运行服务

以下为内网服务器运行服务的示例,服务监听 WireGuard IP(10.0.0.2)。

1. 运行 Python HTTP 文件服务器

在内网服务器上创建共享目录并启动 HTTP 服务:

bash 复制代码
mkdir -p ~/shared_files
echo "Hello World" > ~/shared_files/hello.txt
cd ~/shared_files
python3 -m http.server 8000 --bind 10.0.0.2

2. 运行 SSH 服务(可选)

修改内网服务器的 SSH 配置,监听 WireGuard IP 和自定义端口:

bash 复制代码
sudo vi /etc/ssh/sshd_config

添加或修改以下内容:

text 复制代码
ListenAddress 10.0.0.2
Port 2222

重启 SSH 服务:

bash 复制代码
sudo systemctl restart ssh

五、公网服务器配置 HAProxy

1. 安装 HAProxy

在公网服务器上安装 HAProxy:

bash 复制代码
sudo apt install haproxy -y

2. 配置 HAProxy

编辑 /etc/haproxy/haproxy.cfg,替换为以下内容:

haproxy 复制代码
# 全局配置:控制haproxy进程整体行为
global
    daemon                # 以守护进程方式运行
    maxconn 256           # 最大并发连接数限制,防止资源过载

# 默认配置:为所有proxy设置通用选项
defaults
    mode tcp              # 工作模式为TCP(适合SSH、非HTTP协议)
    timeout connect 5s    # 连接后端服务器超时时间,避免长时间挂起
    timeout client 30s    # 客户端连接超时,超过则断开
    timeout server 30s    # 后端服务器响应超时,超过则断开

# HTTP代理监听配置(监听80端口)
listen http_proxy
    bind *:80             # 监听所有网卡80端口,确保端口未被占用
    server s1 10.0.0.2:8000  # 后端HTTP服务器地址及端口

# SSH代理监听配置(监听2222端口)
listen ssh_proxy
    bind *:2222           # 监听所有网卡2222端口,方便外部SSH连接
    server s2 10.0.0.2:22  # 后端SSH服务器地址及端口
  • http_proxy:将公网服务器的 1.2.3.4:80 转发到内网服务器的 10.0.0.2:8000(HTTP 服务)。
  • ssh_proxy:将公网服务器的 1.2.3.4:2222 转发到内网服务器的 10.0.0.2:2222(SSH 服务)。

3. 重启 HAProxy

bash 复制代码
sudo systemctl restart haproxy

✅ 测试访问

从公网测试访问内网服务:

  1. 访问 HTTP 服务:

    • 打开浏览器,访问 http://1.2.3.4/,应看到内网 Python 文件服务器的内容(如 hello.txt)。
  2. 访问 SSH 服务:

    • 使用 SSH 客户端连接:

      bash 复制代码
      ssh -p 2222 user_internal@1.2.3.4

若访问成功,说明配置正确。


六、清空配置

为了避免 HAProxy 或 WireGuard 的配置残留影响后续操作,或在调试时需要重置环境,可以按照以下步骤清空相关配置。

1. 清空 WireGuard 配置(公网服务器和内网服务器)

  1. 停止 WireGuard 服务

在两台服务器上停止并禁用 WireGuard:

bash 复制代码
sudo systemctl stop wg-quick@wg0
sudo systemctl disable wg-quick@wg0
  1. 删除 WireGuard 配置文件

移除 WireGuard 配置文件和密钥:

bash 复制代码
sudo rm /etc/wireguard/wg0.conf
sudo rm /etc/wireguard/private.key
sudo rm /etc/wireguard/public.key
  1. (可选)卸载 WireGuard

如果不再需要 WireGuard,可以完全卸载:

bash 复制代码
sudo apt remove wireguard -y
sudo apt autoremove -y

2. 清空 HAProxy 配置

公网服务器
  1. 停止 HAProxy 服务
bash 复制代码
sudo systemctl stop haproxy
sudo systemctl disable haproxy
  1. 备份并清空 HAProxy 配置

备份现有配置文件(以防需要恢复):

bash 复制代码
sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak

创建空的默认配置文件:

bash 复制代码
sudo bash -c 'cat > /etc/haproxy/haproxy.cfg << EOL
global
    daemon
    maxconn 256

defaults
    mode http
    timeout connect 5s
    timeout client 30s
    timeout server 30s
EOL'
  1. (可选)卸载 HAProxy

如果不再需要 HAProxy,可以卸载:

bash 复制代码
sudo apt remove haproxy -y
sudo apt autoremove -y

七、拓展配置(可选)

1. 基于域名的 HTTP 转发

若需根据域名转发 HTTP 请求,修改 /etc/haproxy/haproxy.cfg 中的 http_proxy 部分:

haproxy 复制代码
listen http_proxy
    bind *:80
    mode http
    acl host_file hdr(host) -i files.example.com
    acl host_api hdr(host) -i api.example.com
    use-server file1 if host_file
    use-server api1 if host_api
    server file1 10.0.0.2:8000 check
    server api1 10.0.0.3:8080 check
  • acl:根据请求的 Host 头匹配域名。
  • use-server:将匹配的请求转发到对应内网服务器。

2. 负载均衡

若有多个内网服务器提供相同服务,可配置 HAProxy 实现负载均衡:

haproxy 复制代码
listen http_balancer
    bind *:80
    mode http
    server web1 10.0.0.2:8000 check
    server web2 10.0.0.3:8000 check

HAProxy 默认使用轮询(round-robin)算法分配请求。


注意事项

  1. 防火墙设置:

    • 确保公网服务器的 51820/UDP(WireGuard)、80/TCP(HTTP)、2222/TCP(SSH)端口已开放。
    • 内网服务器需允许 10.0.0.2 上的相应端口(如 8000、2222)。
  2. 域名解析(若使用域名):

    • 将域名(如 files.example.com)解析到公网服务器的 IP 1.2.3.4。
  3. 服务监听:

    • 内网服务必须监听 WireGuard IP(10.0.0.2),否则 HAProxy 无法转发。
  4. 安全性:

    • 本教程未配置 SSL,生产环境建议为 HTTP 服务启用 HTTPS(使用 certbot 或自签名证书)。
    • 保护 WireGuard 私钥和 SSH 密钥,定期轮换。
相关推荐
IMPYLH11 分钟前
Linux 运维基础:从入门到实战的完整指南
linux·运维·php
前端 贾公子18 分钟前
LangGraph == 图的状态(State)管理 (下)
运维·服务器·数据库
Lsetea20 分钟前
curl走HTTPS代理报SSL证书错误:proxy-cacert与cacert双层信任排查
linux·https·ssl证书·curl·代理服务器
星恒随风22 分钟前
Linux进程间通信(二):深入理解System V共享内存、消息队列、信号量与内核IPC资源管理
linux·运维·服务器·笔记·学习·状态模式
yunwei3728 分钟前
eBPF 实例教程:BPF Arena 零拷贝共享内存
linux·后端·性能优化
yangmu320331 分钟前
PLC 设备介绍:工业自动化的“控制大脑”
运维·自动化
IMPYLH37 分钟前
Linux 文件检索:find、locate、grep 与 which 实战指南
linux·运维·服务器
腾讯蓝鲸智云44 分钟前
【运维自动化-监控平台】如何配置进程监控之基于进程名规则匹配
运维·自动化·云计算·sass·paas
优化Henry1 小时前
LTE基站传输割接后S1连接失败排查实录
运维·网络·笔记·学习·信息与通信
流烟默1 小时前
ClickHouse Part 机制与写入优化实践指南
大数据·运维·clickhouse