1、前言
最近服务器托管费要交了,实在是交不起了,所以考虑把服务器撤回来,放到家里的机柜中。
但是一般家庭网络是没有公网IP地址的,也同样不开放80、443等敏感端口,所以起了用公有云服务器内网转发的想法。
考虑使用IPSec VPN建立一个隧道,让路由器连接到云服务器并开放本地局域网,这样就不必一条一条添加端口映射。
写一下具体实施过程和踩到的坑留在这里。
2、环境介绍
操作系统:Ubuntu 22.04
家庭侧路由: RuiJie EG105G-P-E
对端云提供商: Aliyun
3、家庭侧准备
思路是使用IPSec VPN连接到公有云,然后公有云转发所有端口的流量到家庭侧并通过VPN隧道直接透传到目标局域网主机,以下是具体实现
3.1、配置路由器
首先需要检查下这个路由器所支持的协议,我这款路由器属于比较入门的AC一体机,也支持基础的IPSecVPN客户/服务端,首先配置一个链接,开放10.1.3.0/24网段给公有云。
对应路由器侧配置

4、配置公有云
在客户端配置完成后,需要根据客户端的IKE策略和协商策略配置服务器端,服务器端操作系统是Ubuntu 22.04,首先安装所需要的套件,这里使用 StrongSwan 来完成服务器建立, 首先安装对应套件
sudo apt update && sudo apt install strongswan strongswan-pki libcharon-extra-plugins libcharon-extauth-plugins -y由于这个路由器比较低级,不支持使用证书进行身份验证,所以我们不使用证书,转而使用预共享密钥(PSK)来进行身份认证,在StrongSwan安装完成后,编辑对应的配置 /etc/ipsec.conf
sudo nano /etc/ipsec.conf
配置文件内容
config setup
uniqueids=no # 允许多个客户端使用相同 ID 同时连接
conn %default # 指定默认配置参数,会被所有后续配置继承
ikelifetime=86400s
keylife=3600s
rekeymargin=3m
keyingtries=1
keyexchange=ikev2 # 根据路由器配置,使用IKEv2协议。
authby=psk # 根据路由器配置,使用预共享密钥(psk)
dpddelay=30s # 心跳30秒
dpdtimeout=150s
dpdaction=restart
conn tlsyserver # 服务器端配置,对应路由器配置项目
left=%defaultroute # 服务器本地网络,使用本地网卡IP地址
leftid=@vpnserver # 服务器本地身份标识
leftsubnet=0.0.0.0/0 # 服务器本地声明子网
right=%any # 对端IP地址(使用%any以允许任意IP地址链接)
rightid=@tlsyserver # 对端身份标识
rightsubnet=10.1.3.0/24,10.1.2.0/24 # 对端远程子网
ike=3des-sha1-modp1024 #第一阶段IKE算法
esp=aes128-sha1 #第二阶段ESP算法
pfs=no #不启用完美前向加密
auto=add #启动时加载配置,等待客户端链接然后,写入客户端使用的预共享密钥到/etc/ipsec.secret
nano /etc/ipsec.secret
@clientid : PSK "pskpasswordhere"配置完成后,重启IPsec服务端
ipsec restart等待客户端链接,然后使用ipsec status查看隧道建立状态,如果长时间仍未有任何客户端链接,可以使用journalctl -u strongswan-starter -f来跟踪查看链接日志,或在配置文件中启用charondebug="all"来显示更详细的日志。
链接建立后的大概输出如下:
root@vpn-hub:~# ipsec status
Security Associations (2 up, 0 connecting):
tlsyserver[7]: ESTABLISHED 7 hours ago, 172.18.0.24[vpnserver]...61.xx.xx.xx[tlsyserver]
tlsyserver{61}: INSTALLED, TUNNEL, reqid 2, ESP in UDP SPIs: c827603a_i c28697cd_o
tlsyserver{61}: 10.1.1.0/24 172.18.0.0/18 === 10.1.2.0/24 10.1.3.0/24
lj[4]: ESTABLISHED 7 hours ago, 172.18.0.24[vpnserver]...61.xx.xx.xx[lj]
lj{62}: INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c0cb8666_i c6dcece8_o
lj{62}: 10.1.2.0/24 === 10.1.1.0/24此时,链接隧道就被建立,可以尝试ping以下对端网络中的设备看是否能够成功链接
root@vpn-hub:~# ping 10.1.3.1
PING 10.1.3.1 (10.1.3.1) 56(84) bytes of data.
64 bytes from 10.1.3.1: icmp_seq=1 ttl=64 time=44.0 ms
64 bytes from 10.1.3.1: icmp_seq=2 ttl=64 time=43.8 ms
64 bytes from 10.1.3.1: icmp_seq=3 ttl=64 time=43.9 ms
64 bytes from 10.1.3.1: icmp_seq=4 ttl=64 time=43.9 ms5、配置流量转发
在链接建立成功以后,我们需要将所有访问到该服务器的流量转发到家庭侧主机,通常流量转发我会选最简单的iptables进行转发,最简单也最快捷。
5.1、避让ssh端口
为了给家庭侧主机让出22端口,需要更改公有云端口到一个不会使用的端口号中,修改/etc/ssh/sshd_config文件。
nano /etc/ssh/sshd_config
Include /etc/ssh/sshd_config.d/*.conf
#在此处取消注释并修改端口
Port 6000
systemctl restart sshd等待ssh服务重新启动,使用新的端口连接到主机,执行下一步操作
5.2、全端口流量转发
由于我不想为将来的每个端口都配置一条端口转发命令,所以在完成了对ssh端口的避让之后,就可以开始配置iptables的流量转发操作。
首先,为了能够让iptables进行流量转发,需要开启Linux的内核转发功能。
sysctl -w net.ipv4.ip_forward=1
# 永久生效(可选):
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf然后,为了避免全端口转发导致云主机ssh和ipsec服务被中断,需要排除掉以下端口和协议
| 网络栈 | 端口 | 用途 |
|---|---|---|
| TCP | 6000 | SSH服务(端口更改后) |
| UDP | 500 | 密钥协商 |
| UDP | 4500 | NAT穿越/移动端链接 |
| GRE | - | 非NAT加密传输 |
| ESP | - | 路由转发 |
之后,假设我们要转发到的家庭测目标主机IP地址为10.1.3.3/24,那么就可以使用iptables对任意来源的流量执行DNAT转发,以下是对应的命令:
# 转发 TCP 流量(排除 6000 端口)
iptables -t nat -A PREROUTING -p tcp ! --dport 6000 -j DNAT --to-destination 10.1.3.3
# 转发所有 UDP 流量,排除 6000、500、4500 端口 (IPSec 常用端口)
iptables -t nat -A PREROUTING -p udp -m multiport ! --dports 6000,500,4500 -j DNAT --to-destination 10.1.3.3
# 处理回程路由包以正确回程转发
iptables -t nat -A POSTROUTING -d 10.1.3.3 -j MASQUERADE
# 可选: 如果遇到SSH经常断开,图片加载慢,可以使用MSS钳制,限制最大传输包。
# iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# 保存iptables规则
apt update && sudo apt install iptables-persistent -y
netfilter-persistent save完成后,我们就可以通过访问云主机的任意端口并成功连接到家庭侧端口啦!
备注:本文方案为了兼容老款路由器(Ruijie EG105G-P-E),使用了 3des-sha1 这种较老算法。在 2026 年的今天,这种组合的安全性已降至临界点。如果你的设备支持,建议优先切换到 aes256-gcm 或 chacha20poly1305,以获得更高的传输性能和安全性。
参考: