使用IPSecVPN对外开放服务

笔记 · 昨天 · 4 人浏览

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网段给公有云。


对应路由器侧配置
VPN客户端配置

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 ms

5、配置流量转发

在链接建立成功以后,我们需要将所有访问到该服务器的流量转发到家庭侧主机,通常流量转发我会选最简单的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服务被中断,需要排除掉以下端口和协议

网络栈端口用途
TCP6000SSH服务(端口更改后)
UDP500密钥协商
UDP4500NAT穿越/移动端链接
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,以获得更高的传输性能和安全性。

参考:

  1. strongSwan 文档中心
  2. Linux防火墙文档
VPN 网络 运维