【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 上的相应端口(如 80002222)。
  2. 域名解析(若使用域名):

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

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

    • 本教程未配置 SSL,生产环境建议为 HTTP 服务启用 HTTPS(使用 certbot 或自签名证书)。
    • 保护 WireGuard 私钥和 SSH 密钥,定期轮换。
相关推荐
EMTime6 小时前
Docker运行OpenWRT
运维·docker·容器
lolo大魔王7 小时前
Linux 文件系统超全面详解(原理、结构、挂载、分区、inode、日志、管理命令)
linux·运维·服务器
磊 子8 小时前
详细讲解一下epoll
linux·io·epoll·io多路复用
printfLILEI9 小时前
php中的类与对象以及反序列化
linux·开发语言·php
zyl837219 小时前
Docker 使用手册
运维·docker·容器
古月方枘Fry9 小时前
MGRE实验
运维·服务器
叠叠乐10 小时前
redmi k90 pro max 强解BL,刷海外rom, 并刷入sukisu ultra
linux
stolentime10 小时前
FreeDomain 本地开发环境快速搭建指南
运维·服务器·网络
xiaoye-duck11 小时前
《Linux系统编程》Linux 进程间通信之管道基础解析:从匿名管道原理到基于管道的进程池实现
linux