家里云计划:使用wireguard和vps让家里云拥有公网IP

——并且可以看见客户端的真实IP

已知问题

  • 无法访问docker映射出的端口,因为docker会再次进行NAT操作,导致回包源IP变为docker容器内部ip而非10.0.0.2,不能被策略路由匹配
  • 由于wireguard接收的流量会进入forward链而不是input链,ufw/fail2ban在默认情况下无法封锁来自某ip的流量,可手动添加iptables规则

0.要求

  • 一台家庭服务器
  • 一台拥有公网IP的云服务器,用于流量转发

1.相比常见的其他内网穿透方案的优势

使用商业方案:

  • 又贵又慢,不如自建一根

其他自建方案:

  • Wireguard性能明显更强(包括frp、ngrok等端口映射工具,openvpn等其他l2 vpn工具)
  • 支持范围端口转发,同时转发上万个端口或全端口
  • 本文中实现的:为所有tcp/udp服务传递真实IP,无需proxy protocol,几乎还原公网体验
  • 完美支持ipv6(本文中未实现但和ipv4配置方法完全一样)(真的有人用ipv6吗)

2.通过wireguard实现内网互通:

教程参考https://varkai.com/posts/operation/use-wireguard-networking-to-achieve-intranet-penetration/ 的教程

配置云服务器内网ip为10.0.0.1,家里云ip为10.0.0.2,可互相ping通、访问服务后进行下一步

3.在云服务器上配置DNAT/SNAT转发规则

教程参考https://superuser.com/questions/1777082/using-vps-to-give-public-ip-to-on-home-network/1777106

很多转发教程会使用masquerade,这样当然非常简单,但是会导致运行在家里云上的服务无法获取访问者的真实ip,全部显示为10.0.0.1

  • ssh/rdp/web日志全部来自10.0.0.1,无法封禁爆破ip
  • 游戏服务器中所有玩家的数据包都会来自10.0.0.1,触发速率限制导致玩家掉线

使用DNAT/SNAT即可解决,规则如下:

iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -d 10.0.0.2 -m conntrack --ctstate DNAT -j ACCEPT

iptables -t nat -I PREROUTING -p tcp -d [VPS public IP] -i ens192 --dport 80 -j DNAT --to-destination 10.0.0.2:80
iptables -t nat -A POSTROUTING -o ens192 -j SNAT --to-source [VPS public IP]

其中ens192换为vps的网卡,VPS public IP不一定是服务器的公网IP,用ifconfig查看网卡IP,比如阿里云eth0的绑定IP就是172.开头的

4.在家里云上配置路由规则

ip -4 route add default dev wg0 table 4242
ip -4 rule add pref 500 from 10.0.0.2 lookup 4242

这可以确保所有来自云服务器的流量,都通过云服务器的IP来响应;不配置该规则的话,家里云将会直接使用家庭IP回包,导致数据包被客户端的防火墙丢弃

对于使用udp的服务(常见于各种游戏服务端,比如Mincraft BE、CS:GO..),绑定IP必须设置为家里云的wireguard IP(10.0.0.2),否则无法正常使用!(原因如上)

5.完整Wireguard配置,通过PostUp/PostDown实现自动化

根据实际情况修改

云服务器端:

wg0.conf

[Interface]
Address = 10.0.0.1/24
SaveConfig = true
PostUp = /etc/wireguard/post-up.sh
PostDown = /etc/wireguard/post-down.sh
ListenPort = 61820
PrivateKey = [VPS Wireguard Private Key]

[Peer]
...

post-up.sh

#!/bin/bash
# VPS WireGuard PostUp Script - NAT 端口转发配置
# 转发 1000-60000 端口的 TCP/UDP 流量到 Homelab

# 配置变量
PUBLIC_IP="172.x.x.x"  # VPS 公网 IP
PUBLIC_IFACE="eth0"         # VPS 公网接口
HOMELAB_IP="10.0.0.2"       # Homelab 内网 IP
PORT_RANGE="1000:60000"     # 转发端口范围

echo "[$(date)] Starting VPS NAT rules setup..."

# 1. 启用 IP 转发
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf

# 2. FORWARD 链规则 - 允许转发
iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -d ${HOMELAB_IP} -m conntrack --ctstate DNAT -j ACCEPT

# 3. PREROUTING NAT 规则 - DNAT 端口转发
# TCP
iptables -t nat -A PREROUTING -p tcp -d ${PUBLIC_IP} \
            -i ${PUBLIC_IFACE} --dport 222 \
                -j DNAT --to-destination ${HOMELAB_IP}:22
iptables -t nat -A PREROUTING -p tcp -d ${PUBLIC_IP} \
    -i ${PUBLIC_IFACE} --dport ${PORT_RANGE} \
    -j DNAT --to-destination ${HOMELAB_IP}

# UDP
iptables -t nat -A PREROUTING -p udp -d ${PUBLIC_IP} \
    -i ${PUBLIC_IFACE} --dport ${PORT_RANGE} \
    -j DNAT --to-destination ${HOMELAB_IP}

# 4. POSTROUTING NAT 规则 - SNAT 出站流量
iptables -t nat -A POSTROUTING -o ${PUBLIC_IFACE} \
    -j SNAT --to-source ${PUBLIC_IP}

echo "[$(date)] VPS NAT rules setup completed!"

postdown.sh

#!/bin/bash
# VPS WireGuard PostDown Script - 清理 NAT 规则

# 配置变量(与 PostUp 保持一致)
PUBLIC_IP="172.x.x.x"
PUBLIC_IFACE="eth0"
HOMELAB_IP="10.0.0.2"
PORT_RANGE="1000:60000"

echo "[$(date)] Cleaning up VPS NAT rules..."

# 清理 FORWARD 规则
iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null
iptables -D FORWARD -d ${HOMELAB_IP} -m conntrack --ctstate DNAT -j ACCEPT 2>/dev/null

# 清理 PREROUTING 规则
iptables -t nat -D PREROUTING -p tcp -d ${PUBLIC_IP} \
                    -i ${PUBLIC_IFACE} --dport 222 \
                                    -j DNAT --to-destination ${HOMELAB_IP}:22
iptables -t nat -D PREROUTING -p tcp -d ${PUBLIC_IP} \
    -i ${PUBLIC_IFACE} --dport ${PORT_RANGE} \
    -j DNAT --to-destination ${HOMELAB_IP} 2>/dev/null

iptables -t nat -D PREROUTING -p udp -d ${PUBLIC_IP} \
    -i ${PUBLIC_IFACE} --dport ${PORT_RANGE} \
    -j DNAT --to-destination ${HOMELAB_IP} 2>/dev/null

# 清理 POSTROUTING 规则
iptables -t nat -D POSTROUTING -o ${PUBLIC_IFACE} \
    -j SNAT --to-source ${PUBLIC_IP} 2>/dev/null

echo "[$(date)] VPS NAT rules cleaned up!"

家里云端

wg0.conf

[Interface]
PrivateKey = [ Homelab Wireguard Private Key]
Address = 10.0.0.2/24
Table = off
PostUp = /etc/wireguard/post-up.sh
PostDown = /etc/wireguard/post-down.sh
[Peer]
PublicKey = [ VPS Wireguard Public Key ]
Endpoint = [ VPS Reachable Public IP ] :61820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

post-up.sh

#!/bin/bash
# Homelab WireGuard PostUp Script - 策略路由配置

# 配置变量
HOMELAB_IP="10.0.0.2"
WG_IFACE="wg0"
ROUTING_TABLE="4242"

echo "[$(date)] Setting up Homelab policy routing..."

# 1. 创建自定义路由表
ip route add default dev ${WG_IFACE} table ${ROUTING_TABLE}

# 2. 添加策略路由规则 - 从 HOMELAB_IP 发出的包走 WireGuard
ip rule add from ${HOMELAB_IP} lookup ${ROUTING_TABLE} pref 100

# 3. 刷新路由缓存
ip route flush cache

# 4. 验证配置
echo "Policy routing rules:"
ip rule show | grep ${ROUTING_TABLE}
echo "Routing table ${ROUTING_TABLE}:"
ip route show table ${ROUTING_TABLE}

echo "[$(date)] Homelab policy routing setup completed!"

post-down.sh

#!/bin/bash
# Homelab WireGuard PostDown Script - 清理策略路由

# 配置变量
HOMELAB_IP="10.0.0.2"
ROUTING_TABLE="4242"

echo "[$(date)] Cleaning up Homelab policy routing..."

# 1. 删除策略路由规则
ip rule del from ${HOMELAB_IP} lookup ${ROUTING_TABLE} 2>/dev/null

# 2. 清空路由表
ip route flush table ${ROUTING_TABLE} 2>/dev/null

# 3. 刷新路由缓存
ip route flush cache

echo "[$(date)] Homelab policy routing cleaned up!"

最后

配置完成且测试通过后,可以执行systemctl enable –now wg-quick@wg0来让wireguard服务开机自启动

wg-quick up/down wg0可以控制开关

6.故障排除

在折腾的时候用到的一些故障排除/测试手段:

路由测试:ip route get 8.8.8.8 from 10.0.0.2,可以检查家里云路由是否走wireguard

检查udp conntrack情况:watch -n 1 ‘sudo conntrack -L -p udp | grep 23333’

调整conntrack超时时间:sysctl -w net.netfilter.nf_conntrack_udp_timeout=30 && sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=180

另一个方案

参考https://blog.feld.me/posts/2025/03/static-ips-from-the-cloud/

这个也是利用wireguard,但是使用了更底层的arp proxy,可以将公网ip直接绑定到家里云的虚拟网卡上,实际上和公网无异了

该方案的缺点是要求vps有两个IP,并且不能是VPC网络(单IP其实也可以用VNC访问,但是不方便管理)

Edit:目前几乎所有云服务商的VPS都在使用VPC网络,此方案可行性较低

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇