说明:本文由 AI 辅助生成,内容基于实际技术操作过程整理。代码和命令均已在本站服务器上验证执行,如有疑问欢迎留言。
家里的网络环境有点特殊,小米路由器拨号上网后,我想让家里的设备都能通过 VPN 访问家里的服务器,顺带把 Oracle 云上跑的服务都管起来。路由器本身只支持 PPTP VPN,方案听起来简单,但实际配起来踩了一个不大不小的坑。
先说一下最终效果
- 小米路由器通过 PPTP 拨上 Oracle 云服务器
- 防火墙开着,只放了 22/80/443/1723 四个端口
- 家里设备拨号后,能正常访问家里的内网服务和服务器
配置 PPTP 服务端
服务器端用的是 pptpd,安装和配置都很直接:
sudo apt update
sudo apt install pptpd -y
然后配两个关键文件:
/etc/pptpd.conf 里加上:
localip 192.168.0.1
remoteip 192.168.0.100-200
localip:PPTP 虚拟网卡的地址remoteip:拨号成功后给客户端分配的内网 IP 段
/etc/ppp/chap-secrets 加一条账号:
vpnuser pptpd your_strong_password *
格式是:用户名 服务名 密码 允许的客户端IP,最后填 * 表示不限客户端。
配置完重启:
sudo systemctl restart pptpd
sudo systemctl enable pptpd
服务器端就算好了。
防火墙的坑
一开始我以为只要把端口放开就行,于是写了这些规则:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 1723/tcp
sudo ufw allow 47 # PPTP 用的 GRE 协议
sudo ufw enable
看着很完整,但小米路由器一拨号,就一直显示”正在拨号”,永远连不上。
排查过程
登录服务器看日志:
sudo dmesg | grep "UFW BLOCK" | tail -20
出来一堆这样的记录:
[UFW BLOCK] IN=ens3 ... PROTO=47 SRC=路由器公网IP DST=服务器IP
GRE 包(协议号 47)确实到达了服务器,但被 UFW 拦住了。
这就奇怪了,明明 ufw allow 47 已经写进去了。反复确认 UFW 状态,规则也都在:
47 ALLOW IN Anywhere # GRE (PPTP)
问题出在 UFW 对纯协议号的处理上。PPTP 的 GRE 不是一个”端口”,而是一个”协议”(protocol 47)。Ubuntu 22.04 的 UFW/nftables 在处理这类非端口的协议规则时,内部规则生成有 bug,表面上看 allow 47 写进去了,实际上并没有正确生成 ACCEPT 动作。
更关键的是,GRE 是无连接协议,不像 TCP 有三次握手,防火墙很难靠连接状态来识别哪些包是合法的。当包到达 ufw-before-input 链时,还在 conntrack 阶段就被当成”未知入站流量”丢了。
真正的解决方案
既然 UFW 的 allow 47 靠不住,直接绕过它,用 iptables 在 UFW 之前插入规则:
# 在 ufw-before-input 链最顶部插入,优先级最高
sudo iptables -I ufw-before-input 1 -p gre -j ACCEPT
sudo iptables -I ufw-before-input 2 -p tcp --dport 1723 -j ACCEPT
这里的关键是 -I ufw-before-input 1——把规则插到最前面,让它比 UFW 默认的 DROP 更早执行。
插完之后验证一下:
sudo iptables -L ufw-before-input -n -v
能看到:
ACCEPT 47 -- * * 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1723
再去小米路由器拨号,这次一次就连上了。
补充说明
为了让规则开机后不丢,我同时做了两个持久化操作:
- UFW 规则持久化(端口类规则 UFW 本身会保存)
- iptables 规则持久化:
sudo apt install iptables-persistent -y sudo netfilter-persistent save
另外还确认了内核模块 nf_conntrack_pptp 和 nf_nat_pptp 都已加载:
lsmod | grep pptp
输出正常的话就说明 PPTP 连接追踪已经就绪。
总结
这套方案的核心就三件事:
- 服务器端配好 pptpd + chap-secrets
- 放行 1723 TCP 和 47 GRE
- 绕过 UFW 的协议号 bug,用 iptables 在 UFW 之前直接 ACCEPT
Oracle 云的安全组也要对应放开 1723 TCP 和协议 47 (GRE),否则包在云防火墙层面就被丢了。
这种方案适合家里只有 PPTP 客户端的老式路由器、又想把所有设备都走 VPN 的场景。如果路由器支持 WireGuard 或 OpenVPN,优先选那俩,PPTP 协议本身有弱点,只适合个人内部用。
再次声明:本文由 AI 辅助生成,基于实际操作环境整理,不涉及具体账号凭证和私钥信息。