TUN/TAP 虚拟网卡与 VPN 代理:TUN0 路由拦截与 TAP0901 驱动

TUN vs TAP

特性TUNTAP
模拟对象IP 网络接口以太网卡
工作层第三层(IP 层)第二层(数据链路层)
处理单元IP 数据包以太网帧
支持协议仅 IPIP、ARP、广播等
典型用途全局路由代理局域网桥接
CPU 开销较小较大

TUN 适合”全部流量走 VPN”,TAP 适合”需要访问远程 LAN 内设备”的桥接场景。

TUN 模式的流量拦截

VPN 客户端启用 TUN 模式的流程:

  1. 创建虚拟网卡 tun0
  2. 修改系统路由表,将默认路由(0.0.0.0/0)指向 tun0
  3. 所有出站 IP 包经过 tun0 → VPN 客户端加密封装 → 通过真实网卡发送到 VPN 服务器
[本地应用]
    | (IP 包)
    v
[tun0 虚拟网卡]
    | (加密封装)
    v
[VPN 客户端程序]
    |
    v
[VPN 服务器 -> 目标网络]

TUN 全局模式会代理 localhost

开启全局代理时,若未排除环回地址,127.0.0.1 的流量也会被 tun0 拦截,导致本地服务访问失败。

排除 localhost(OpenVPN 配置)

route 127.0.0.1 255.0.0.0 net_gateway

或在客户端设置中勾选”分流模式”,只代理外网 IP。

TAP0901 驱动(Windows)

TAP-Windows Adapter V9tap0901)是 OpenVPN 在 Windows 上使用的虚拟以太网卡驱动,安装后在网络适配器列表中以普通网卡形式出现。

驱动通过设备文件暴露接口:

\\.\Global\{TAP-Adapter-GUID}.tap

Java 通过 JNA 读写数据包

// 打开设备文件
HANDLE h = Kernel32.INSTANCE.CreateFile(
    "\\\\.\\Global\\{GUID}.tap",
    WinNT.GENERIC_READ | WinNT.GENERIC_WRITE,
    0, null, WinNT.OPEN_EXISTING,
    WinNT.FILE_ATTRIBUTE_NORMAL, null
);

// 读取以太网帧
byte[] buf = new byte[2048];
IntByReference bytesRead = new IntByReference();
Kernel32.INSTANCE.ReadFile(h, buf, buf.length, bytesRead, null);

// 写入以太网帧
Kernel32.INSTANCE.WriteFile(h, buf, bytesRead.getValue(), bytesRead, null);

操作虚拟网卡需要管理员权限。TAP0901 只在 Windows 上可用;Linux 和 macOS 使用系统内置的 TUN/TAP 接口。

实现 VPN 客户端的选型

目标方案难度
仅代理指定应用流量纯 Socket / SOCKS5 代理
全局系统流量拦截TUN/TAP 驱动 + JNI/JNA

Java 只能做用户空间的协议与加密逻辑;全局流量拦截必须借助内核级虚拟网卡驱动(TUN/TAP)。