鸿蒙OS VPN TUN虚拟网卡:虚拟设备与真实网卡的交互

运作流程 / 4人浏览

凌晨三点的深圳,窗外是这座不夜城稀疏的霓虹,而我面前的屏幕,正滚动着密密麻麻的十六进制数据流。我是一名区块链开发者,更准确地说,是一个在鸿蒙OS上折腾VPN协议的“疯子”。三天前,我接到了一个奇怪的需求:为一个去中心化交易所搭建一个基于鸿蒙系统的隐私节点,要求所有流量必须经过一个自定义的TUN虚拟网卡,并且要和真实的物理网卡进行某种“智能交互”——说白了,就是让手机在连接公共Wi-Fi时,能自动把加密货币交易的数据包伪装成普通的视频流量,绕过那些对区块链敏感的防火墙。

我面前的这台华为Mate 60 Pro,已经root过了,跑了最新的鸿蒙NEXT开发者预览版。此刻,它正通过USB连接着我的开发笔记本,而笔记本上,Wireshark正在疯狂抓包。我刚刚创建了一个名为“vpn_tun0”的虚拟接口,并且尝试让它和手机的wlan0(真实Wi-Fi网卡)建立一条“秘密通道”。但事情从一开始就不顺利——我写的那个转发规则,似乎把数据包都丢进了黑洞。

虚拟世界的“网线”:TUN设备到底是什么

如果你不是内核开发者,第一次听到“TUN虚拟网卡”这个词,可能会觉得它是个很高深的东西。其实,你可以把它想象成一根插在操作系统内部的“虚拟网线”。这根网线的一端是你的用户态程序(比如一个VPN客户端),另一端则是内核的网络协议栈。当你把一个IP数据包塞进TUN设备,这个数据包就会像被扔进了一根水管,从另一端的水龙头(你的程序)里流出来——只不过,流出来的是原始的、未经处理的IP报文。

在鸿蒙OS上,创建TUN设备的流程和Linux几乎一致。我打开了一个终端,输入了那行我背得滚瓜烂熟的命令:

bash ip tuntap add dev vpn_tun0 mode tun ip link set dev vpn_tun0 up ip addr add 10.0.0.1/24 dev vpn_tun0

这三行命令,在鸿蒙的内核里创建了一个新的网络接口。它的IP地址是10.0.0.1,子网掩码是255.255.255.0。现在,任何发往10.0.0.0/24这个网段的数据包,都会被我这个程序“截获”。但问题来了:我该怎么让这些数据包,从虚拟的vpn_tun0,走到真实的wlan0,然后发到互联网上?尤其是,当我想让某个特定端口的数据——比如一个比特币交易广播——走一条特殊的路径时。

数据包的“灵魂交换”:从虚拟到真实

凌晨三点十五分,我喝了一口已经凉透的咖啡,决定用最暴力的方法:写一个用户态的程序,直接从TUN设备读取数据包,然后通过原始套接字(Raw Socket)把它们塞进wlan0。听起来很简单?但鸿蒙的权限管理比我想象的要严苛得多。

我的程序核心逻辑是这样的:它打开/dev/net/tun这个设备文件,然后在一个无限循环里,用read()系统调用从TUN设备读取数据包。每个读到的数据包,都是一个完整的IP报文,包含IP头、TCP或UDP头,以及负载数据。然后,程序解析这个IP报文,根据目标端口和协议类型,决定它的“命运”。

我写了一个简单的判断逻辑:

c if (iphdr->protocol == 6 && ntohs(tcphdr->dest) == 8333) { // 这是比特币的P2P协议端口,走加密通道 encrypt_and_send_via_wlan0(packet, len); } else { // 其他流量,直接转发 send_raw_via_wlan0(packet, len); }

这个8333端口,就是比特币节点之间通信的默认端口。我的想法是,当手机上的钱包应用试图连接比特币网络时,这个数据包会被TUN设备拦截,然后被我的程序加密,再通过wlan0发送出去。这样,在运营商或者公共Wi-Fi的管理员看来,他们看到的只是一堆乱码的UDP流量,而不是比特币协议的握手信息。

但当我运行这个程序时,我看到了一个奇怪的现象。数据包确实从TUN设备读出来了,我也成功通过原始套接字把它写入了wlan0。但是,wlan0那边似乎完全没有反应。我用tcpdump在wlan0上监听,一个包都没有出去。

我检查了鸿蒙的网络栈文档,才发现问题所在:鸿蒙的网络安全框架(HNetSec)默认禁止用户态程序直接通过原始套接字发送数据,除非你拥有特定的系统权限。这个权限,在鸿蒙上叫做“ohos.permission.NETACCESSRAW”。我翻遍了开发者文档,发现这个权限只对系统应用开放,普通的第三方应用根本拿不到。

虚拟网卡与真实网卡的“握手协议”

凌晨三点四十分,我开始尝试第二种方案:不直接写原始套接字,而是通过路由表和iptables(鸿蒙上叫hnetfilter)来引导流量。我决定在vpn_tun0和wlan0之间,建立一套类似“NAT”的转发机制。

想法是这样的:所有从vpn_tun0进来的数据包,源IP都是10.0.0.x(虚拟IP)。当这些数据包要出去时,我必须把它们的源IP改成wlan0的真实IP(比如192.168.1.100),并且把源端口也映射一下。回来的时候,再根据映射关系,把目的IP改回10.0.0.x。

在鸿蒙上,我可以用hnetfilter的SNAT和DNAT规则来实现。我写下了这一系列命令:

bash

开启IP转发

echo 1 > /proc/sys/net/ipv4/ip_forward

设置SNAT,让虚拟网卡出去的包,源地址变成wlan0的地址

hnetfilter -t nat -A POSTROUTING -s 10.0.0.0/24 -o wlan0 -j SNAT --to-source 192.168.1.100

设置DNAT,让回来的包,目的地址变回虚拟网卡的地址

hnetfilter -t nat -A PREROUTING -i wlan0 -d 192.168.1.100 -j DNAT --to-destination 10.0.0.1

这些命令执行后,理论上,任何从vpn_tun0发出的数据包,经过wlan0出去时,源IP都会被替换成真实的192.168.1.100。而任何发往192.168.1.100的回应包,又会被改回10.0.0.1。

但现实又给了我一耳光。我测试了一下,从虚拟网卡ping百度:

bash ping -I vpn_tun0 114.114.114.114

结果,请求石沉大海,没有任何回应。我检查了hnetfilter的计数器,发现数据包确实从vpn_tun0走了,也经过了POSTROUTING链,但就是没有出现在wlan0上。

我仔细阅读了鸿蒙的文档,发现了一个关键点:鸿蒙的hnetfilter在处理转发时,有一个“路由决策”的步骤。当一个数据包从vpn_tun0进入,内核会先检查路由表,决定这个包应该从哪个接口出去。如果路由表说“从wlan0出去”,那数据包才会进入FORWARD链,然后经过POSTROUTING。但是,我检查了路由表:

bash ip route show

输出显示,默认路由确实指向wlan0。但问题在于,vpntun0本身也是一个接口,而且它和wlan0不在同一个子网。内核在路由决策时,发现源IP(10.0.0.x)和目标IP(114.114.114.114)都不属于同一个子网,它可能会触发“反向路径过滤”(Reverse Path Filtering)。这个机制会检查:如果从vpntun0收到一个源IP为10.0.0.x的包,内核会问自己:“我能不能通过vpntun0到达10.0.0.x?”答案当然是“能”,因为vpntun0就是10.0.0.0/24的网络。但是,当这个包需要从wlan0出去时,内核又会检查:“我能不能从wlan0到达114.114.114.114?”答案也是“能”。但问题在于,回应的包来了之后,内核会检查:“这个回应的包,应该从哪个接口进来?它的目的IP是10.0.0.x,而这个IP在vpn_tun0上。但回应的包是从wlan0进来的,内核会认为这是一次非对称路由,于是直接丢弃了包。”

这就是为什么ping不通的原因。我需要关闭反向路径过滤。在鸿蒙上,这个参数在/proc/sys/net/ipv4/conf/all/rp_filter里。我把它设为了0:

bash echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter echo 0 > /proc/sys/net/ipv4/conf/vpn_tun0/rp_filter echo 0 > /proc/sys/net/ipv4/conf/wlan0/rp_filter

再次ping,这次,数据包出去了,也收到了回应。但新的问题又出现了:速度非常慢,延迟高达500毫秒,而且丢包率超过30%。

虚拟币热点的“隐形通道”:TUN设备的性能陷阱

凌晨四点二十分,我意识到,这个简单的转发方案,性能完全不可用。原因在于,所有的数据包都要从内核空间拷贝到用户空间(我的程序),再从用户空间拷贝回内核空间(通过原始套接字或hnetfilter)。这个拷贝过程,对于每个数据包来说,都是巨大的开销。尤其是当我要处理比特币网络那种高频的P2P心跳包(每几秒一次)时,这种开销会直接导致节点同步失败。

我决定采用“零拷贝”的思路。在鸿蒙上,有没有办法让TUN设备直接和物理网卡进行DMA(直接内存访问)交互?我查了鸿蒙的HDF(硬件驱动框架)文档,发现一个叫“数据面加速引擎”的模块,它允许用户态程序通过共享内存的方式,直接读写网卡的环形缓冲区。但问题是,这个接口是为有线网络设计的,对Wi-Fi网卡的支持有限。

我换了一个思路:我不需要让所有流量都走这个慢速路径。对于比特币的流量,我可以只让它走TUN设备,而对于其他的流量(比如浏览网页、刷抖音),直接走正常的网络栈。这样,我就可以在用户态程序里,只处理那些真正需要“特殊待遇”的数据包。

我修改了我的程序。它在读取TUN设备时,不再盲目转发所有数据包。而是先解析IP头,如果发现目标端口是8333(比特币)或者30303(以太坊),就把它放入一个高优先级的加密队列,然后通过一个特殊的UDP套接字,直接发送到我在国外的一台VPS上。这台VPS会解开加密,然后以普通比特币节点的身份,把数据包广播出去。而对于其他端口的数据包,我的程序直接把它们丢弃——因为它们本来就不应该走TUN设备,而是走正常的网络。

但这样又带来了一个新问题:我如何确保,那些正常的网络流量(比如微信消息),不会因为我的路由规则而误入TUN设备?我需要在路由表里,设置非常精细的策略路由。比如,只有发往特定IP(我的VPS)的数据包,才走TUN设备;其他的,全走默认路由。

我用了ip rule和ip route命令,创建了一个策略路由表:

bash

创建一个新的路由表,编号100

echo "100 vpntable" >> /etc/iproute2/rttables

规则:如果目标IP是VPS的IP,则查表100

ip rule add to 45.33.32.156 table 100

在表100里,设置默认路由通过TUN设备

ip route add default via 10.0.0.1 dev vpn_tun0 table 100

规则:所有其他流量,查主表(main table)

ip rule add from all table main priority 1000

这样,只有发往VPS的数据包,才会进入TUN设备;其他的,比如你刷微博、看B站,都走正常的wlan0。这个设计,既保证了比特币流量的隐私,又不会影响日常使用。

真实世界的“链上交易”:当TUN设备遇到以太坊

凌晨五点,我开始测试以太坊的交易。我打开了手机上的MetaMask钱包(经过改造的鸿蒙版本),连接到我自己的节点。我发起了一笔测试交易,转0.01个ETH到另一个地址。

在后台,我的程序捕捉到了这个数据包。它的目标端口是30303(以太坊的P2P端口),目标IP是我VPS上的节点。程序立刻对这个数据包进行了加密,并封装成一个新的UDP包,发往VPS。VPS收到后,解密,然后以标准以太坊协议,把交易广播到整个以太坊网络。

我盯着VPS上的日志,看到了交易哈希:0x8f3a...。然后,我打开Etherscan,搜索这个哈希。几秒钟后,页面上显示:“Transaction Pending”。又过了十几秒,状态变成了“Success”。

成功了。这笔交易,从我的鸿蒙手机出发,经过TUN虚拟网卡的拦截,被加密后通过普通的Wi-Fi网络,到达了国外的VPS,最后被广播到了以太坊主网。在整个过程中,我所在的公共Wi-Fi网络的管理员,只能看到我的手机在和某个IP地址进行UDP通信,通信内容是一堆毫无规律的乱码。他们不知道这是以太坊的交易,更不知道交易的金额和接收方。

但有一个细节让我非常在意。在交易广播出去的同时,我注意到VPS上收到了一系列来自不同IP的探测包。这些探测包,目标端口也是30303,但内容却是空的。我立刻意识到,这是某些区块链分析公司在扫描全网节点。他们通过发送空的握手请求,来发现新的节点。如果我的VPS节点回应了这些探测,那么我的VPS的IP就会被打上“以太坊节点”的标签,从而暴露我的活动。

我需要在TUN设备层面,也处理这些探测包。我的程序在解析数据包时,增加了一个规则:如果收到的数据包是来自未知IP的SYN包(TCP握手的第一步),并且目标端口是30303,那么程序不会转发这个包,而是直接回复一个RST包(拒绝连接)。这样,扫描者就会认为这个端口是关闭的,从而忽略我的节点。

这个规则,让我想起了比特币网络中的“隐身模式”。很多比特币节点为了安全,会设置-listen=0,不监听任何端口,只主动发起连接。而我的TUN设备,实际上是在系统层面实现了这种隐身——它让物理网卡看起来就像是一个普通的、没有运行任何区块链软件的设备。

凌晨六点的阳光:虚拟网卡与真实世界的边界

当第一缕阳光透过窗帘的缝隙照进房间时,我的测试终于全部通过了。我创建了一个脚本,可以一键启动这个“隐私VPN”模式。手机连接上公共Wi-Fi后,所有加密货币相关的流量,都会自动通过TUN设备加密转发,而其他流量则一切正常。

我站起身,伸了个懒腰。窗外的深圳已经苏醒,楼下早餐摊的老板正在蒸包子。我拿起手机,连上了楼下那个“ChinaNet-Free”的公共Wi-Fi。然后,我打开了一个去中心化交易所的App,下了一笔小单,买了一点DOGE。整个过程流畅无比,没有任何卡顿。我知道,在网络的另一端,那笔交易正以加密的形式,穿过这座城市无数的路由器,最终到达了某个海外的服务器。

我突然想到一个问题:如果每个人都用这种方式上网,那些依靠分析网络流量来监控加密货币活动的机构,会怎么样?他们可能会看到满世界的加密流量,却无法分辨哪些是真正的交易,哪些是普通的视频流。TUN设备,这个诞生于Linux内核的虚拟网络技术,在鸿蒙OS上,因为其灵活的权限管理和硬件加速能力,正在成为保护数字资产隐私的一把利刃。

但这把利刃,也可能会被滥用。比如,有人可能用它来绕过金融监管,进行非法交易。或者,有人可能用它来搭建僵尸网络,用加密流量隐藏命令与控制服务器的通信。技术本身是中性的,但使用它的人,决定了它的善恶。

我关掉了电脑,决定去楼下吃个早餐。手机屏幕上,那个TUN设备的日志还在滚动。最后一行显示,它刚刚处理了一个来自某个DeFi协议的数据包。那个协议,正在为用户提供高达1000%的年化收益。当然,那又是另一个故事了。

版权声明:

作者: 最新鸿蒙OS VPN免费节点分享

链接: https://harmonyosvpn.com/workflow/harmonyos-vpn-tun-virtual-real-nic-interaction.htm

来源: harmonyosvpn.com

文章版权归作者所有,未经允许请勿转载。

最新文章

归档

标签