PPTP VPN 拨号一直转圈?UFW 放行了 47 却仍连不上的真正原因

说明:本文由 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

再去小米路由器拨号,这次一次就连上了。

补充说明

为了让规则开机后不丢,我同时做了两个持久化操作:

  1. UFW 规则持久化(端口类规则 UFW 本身会保存)
  2. iptables 规则持久化
    sudo apt install iptables-persistent -y
    sudo netfilter-persistent save

另外还确认了内核模块 nf_conntrack_pptpnf_nat_pptp 都已加载:

lsmod | grep pptp

输出正常的话就说明 PPTP 连接追踪已经就绪。

总结

这套方案的核心就三件事:

  1. 服务器端配好 pptpd + chap-secrets
  2. 放行 1723 TCP 和 47 GRE
  3. 绕过 UFW 的协议号 bug,用 iptables 在 UFW 之前直接 ACCEPT

Oracle 云的安全组也要对应放开 1723 TCP 和协议 47 (GRE),否则包在云防火墙层面就被丢了。

这种方案适合家里只有 PPTP 客户端的老式路由器、又想把所有设备都走 VPN 的场景。如果路由器支持 WireGuard 或 OpenVPN,优先选那俩,PPTP 协议本身有弱点,只适合个人内部用。


再次声明:本文由 AI 辅助生成,基于实际操作环境整理,不涉及具体账号凭证和私钥信息。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理

滚动至顶部