VPS 上的 OpenVPN:没有可打开的 /dev/net/tun 设备
配置通常没问题:来宾根本看不到 tun 设备。先分清是虚拟机还是共享内核的容器,再修真正拥有内核的那一层。
第一次启动就报错,提示 /dev/net/tun 或无法打开的 TUN/TAP 设备。证书还没被读取,所以问题不在配置文件里。守护进程是在向内核索要一个这台来宾并不存在的对象。
该对象是由 tun 模块支撑的字符设备。能否创建它,取决于内核归谁所有。
守护进程向内核要什么
OpenVPN 打开 /dev/net/tun,并向驱动请求一个接口。驱动就是 tun 模块,设备节点则是用户空间访问它的句柄。若模块未加载,节点可能缺失,打开也可能失败。这两种情况都不是改 server.conf 能修好的。
先把这条错误当成平台问题来读。配置错误只会出现在设备打开之后,不会出现在之前。
虚拟机还是共享内核的来宾
在 KVM、Xen 或其他完整虚拟机上,内核由你掌控。你可以加载模块,也可以创建设备节点。在 OpenVZ、Virtuozzo 或 LXC 风格的容器里,来宾与宿主机共享内核,因此里面的 root 无法加载宿主机没有加载的模块。
所以同一个故障有两种完全不同的归属。前者你能在实例内部修好。后者你是在要求宿主机或服务商开放某项能力。
在判断属于哪种情况之前,先运行 ls -l /dev/net/tun、lsmod | grep tun 和 ip -brief link show。
在虚拟机上:开机时加载模块
在虚拟机上,modprobe tun 通常就会创建设备节点。确认节点出现后,要通过发行版的模块配置把加载持久化,而不是依赖一次性的命令。重启后就消失的节点,下个月还会变成同一张工单。
还要确认你启动的内核到底带不带这个模块。精简过的厂商内核可能就没有。
如果节点存在但仍打不开,接下来要怀疑权限和设备的主次设备号。这些是本地修复,不是向服务商提工单。
在容器里,设备归宿主机所有
在容器里,设备和能力是两项独立要求。运行时必须把 /dev/net/tun 透传进来,容器还需要网络能力才能创建接口。既不给设备也不给能力的 rootless 运行时,无论配置怎么写都会一直报同样的打开错误。很多 OpenVZ 主机在客户面板里提供 TUN/TAP 开关,打开它再重启,往往就是全部的解决办法。
向服务商问两个明确的问题:宿主机上是否已加载 tun 模块,这个实例内能否访问该设备?含糊的工单只会得到含糊的回答。
为什么重新编译模块几乎没用
在来宾内自行构建模块很少有用。编译需要当前运行内核的确切配置,而 /proc/config.gz 是可选项,精简镜像里常常没有。即便编出可用的模块,也无法插入容器并不拥有的内核。
设备出现后,先重启服务并确认接口,再去测流量。看到 tun0 只说明守护进程打开了设备。它还不能说明转发、防火墙规则或客户端拿到的路由是否正常。
这些是各自需要证据的独立问题。设备缺失属于前置条件失败;隧道存在却什么都传不过去,属于策略失败。