移动端 | 加入收藏 | 设为首页 | 最新ss | 赞助本站 | RSS
 

freefq.comfree——免费、自由fq——翻墙

困在墙内,请发邮件到freefqcom#gmail.com获得最新免费翻墙方法!
您当前的位置:首页 > 网络翻墙技巧

使用TUN的模式

时间:2022-05-28  来源:  作者: 条评论
TUN 是内核提供的三层虚拟网络设备,由软件实现来替代真实的硬件,相当于在系统网络栈的三层(网络层)位置开了一个口子,将符合条件(路由匹配)的三层数据包交由相应的用户空间软件来处理,用户空间软件也可以通过TUN设备向系统网络栈注入数据包。可以说,TUN设备是用户空间软件和系统网络栈之间的一个通道。

TAP 是二层(以太网)虚拟网络设备,处理的是以太帧,更加底层可以拿到更多信息,但不在本文的讨论范围。C7v免费翻墙网

我们想要利用TUN来做一些事情,实际上就是要编写一个用户态程序,拿到 TUN 设备句柄,向其写入序列化的IP数据包,从中读取数据并还原成IP数据包进行处理,必要时需要取出其payload继续解析为相应传输层协议。C7v免费翻墙网

通常使用 TUN 技术的是 VPN 和代理程序,然而这两类程序在对待 TUN 中传递的 IP 数据包时通常有不同的行为:C7v免费翻墙网

  • VPN 通常做网络层的封装:将拿到的 IP 包进行加密和封装,然后通过某个连接传输到另一个网络中,在解封装和解密后,将 IP 包发送到该网络。在这个过程中,对 IP 包本身的修改是非常小的,不会涉及到整体结构的变动,通常仅会修改一下源 IP 和目标 IP ,做一下 NAT。C7v免费翻墙网

  • 代理程序 通常是传输层的代理:在从 TUN 设备拿到 IP 包后,需要继续解析其 payload,还原出 TCP 或者 UDP 结构,然后加密和封装传输层 (TCP或UDP) 的 payload。网络层的 IP 和传输层的端口信息通常会作为该连接的元数据进行处理,使用额外的加密和封装手段。C7v免费翻墙网

简单来说,VPN 不需要解析 IP 包的 payload,而代理程序需要解析出传输层信息并处理,特别是像 TCP 这样复杂的协议,对其处理更是需要非常小心和严谨。对于代理程序这样的需求,如果我们使用 TUN 技术,通常有两种模式:在用户态实现网络栈,或者直接利用操作系统网络栈实现。C7v免费翻墙网

第一种选择是在用户态实现网络栈,这是不小的工程啊,特别是实现 TCP 协议,因为其协议非常复杂,实现起来有很多细节需要注意,所以自己实现非常容易犯错。所以我们一般会直接找现成的实现来用,现有不少比较成熟且高效的实现,我相信肯定比我自己写的要好几个数量级。C7v免费翻墙网

  • 如果使用 C 语言,lwIP 是一个非常不错的选择,由瑞典计算机科学研究所科学院开源,这是一个轻量级的 TCP/IP 栈实现,在占用超少内存的情况下,实现了完整的 TCP,被广泛应用到嵌入式设备中,稳定性有保证。同时,lwIP 有很多其他语言的绑定,包括 go 和 rust,这使我们在使用其他语言开发时也可以选择 lwIP 作为用户态网络栈实现。C7v免费翻墙网

  • 如果选择使用 Go 语言开发 TUN 的用户态程序(其实这也是大多数人的选择),可以选择 Google 开源的 gVisor 中的实现,gVisor项目目的是为容器提供自己的应用程序内核,其中 tcpip 的实现有 Google 背书,质量有保证。C7v免费翻墙网

  • 如果选择使用 Rust 进行开发,我们的选择就会困难一点,并没有一个饱经风霜、经过时间检验的实现,在广泛对比之后我推荐 smoltcp,这是为裸机实时系统开发的独立的、事件驱动的 TCP/IP 栈,其设计目标是简单和健壮,应该可以信任吧。C7v免费翻墙网

  • 当然,我觉得还有一个可以期待的实现,就是 Google 为 Fuchsia 操作系统开发的 Netstack3,之前是由 Go 实现的,不过现在 Google 用 Rust 重新实现了一个新的,谷歌背书,可以期待。C7v免费翻墙网

在看完可供选择的实现后,我们来看一下在用户空间实现的网络栈如何使用。虽然不同在不同实现下,各个库有不同的编程接口和使用方法,但基本的思路都是一致的,这里我们便仅讨论基本使用流程。C7v免费翻墙网

从原理上来讲,用户态网络栈就是要不断通过协议解析,从 IPv4 数据包中不断解析出 TCP 流中的载荷数据;将传输层载荷通过不断的协议封装,拿到最终的 IPv4 数据包。C7v免费翻墙网

从 TUN 往外读C7v免费翻墙网

从 TUN 设备所对应的句柄中读出了一段字节序列,便是需要处理的IP数据包,一般是 IPv4 协议,不过还是需要先根据字节序列的第一个字节进行判断。C7v免费翻墙网

如果判断为 IPv4 包,就将整个字节序列扔到 IPv4 的 Packet Parser 实现中,还原出 IPv4 数据包结构。根据 IPv4 Header 中的 protocol 字段,判断 payload 应该使用哪个上层协议解析。rfc791C7v免费翻墙网

一般仅需要处理 ICMP、TCP、UDP 这三种协议,拿 TCP 为例,只需要将 IPv4 的 payload 扔到 TCP 的 Parser 中,即可取出我们想要的传输层载荷。(实际情况当然没有说的这么简单)C7v免费翻墙网

向 TUN 写数据C7v免费翻墙网

写的过程其实就是读的过程反过来,拿到的是某个传输层协议的 payload,就拿UDP为例,根据该数据报的元信息,构建出完整的 UDP Header,然后将 payload 内容拼接进去。C7v免费翻墙网

接下来构建 IPv4 Header,然后将 UDP 报文拼接进 IPv4 payload 中。在拿到 IPv4 数据包后,即可序列化为字节序列,写入 TUN 句柄了。C7v免费翻墙网

上面的读、写过程看起来简单,但实际需要考虑的东西非常多,包括但不限于分片、丢包、重传、流量控制等等,TCP 作为一个极其复杂的传输层协议,有巨多情况需要考虑,很明显用上面的基本思路是非常繁琐并且难以使用的。C7v免费翻墙网

众多用户态网络栈肯定考虑到了这一点,实现都提供了非常友好且直接的接口,可以直接创建一个 TCP/IP 网络栈实例,拿到两个句柄,一端负责读取和写入网络层 IP 数据包,另一端负责接收和写入传输层载荷,中间的复杂转换关系和特殊情况都被内部屏蔽掉了。C7v免费翻墙网

根据我们的需求,实际就是在 IPv4 和 TCP payload 之间进行转换,而操作系统的网络栈正好就有这个功能,我们无法简单的直接使用操作系统的网络栈代码,但是可以想办法复用操作系统网络栈提供的功能。TUN 在网络层已经打开了一个口子,还需要在传输层也打开一个口子,其实可以利用操作系统提供的 socket。C7v免费翻墙网

我们使用操作系统提供的 Socket 创建一个传输层的 Listener,将某个 IPv4 数据包的目标 IP 和目标端口修改为我们监听的 IP 和端口,然后通过 TUN 将该 IPv4 数据包注入到操作系统的网络栈中,操作系统就会自动的进行相应的解析,并将所需要的传输层 payload 通过前面创建的 Socket 发送给 Listener,由此便利用操作系统网络栈完成了 “往外读” 的操作。C7v免费翻墙网

对于“向里写”的操作,只需要向刚刚创建的传输层连接句柄写入即可,操作系统的网络栈同样会进行相应的封包,最后形成 IPv4 数据包。很明显,需要考虑反向的数据包,当向传输层连接的句柄中写入数据、操作系统的网络栈封包时,源 IP 和源端口会被视为新的目标 IP 和目标端口,因为我们需要使返回的 IPv4 数据包能够被 TUN 接口捕获到,在上面步骤中就不能只修改目标 IP 和目标端口,同时还要修改源 IP 和源端口,源 IP 应该限制为 TUN 网段中的 IP。C7v免费翻墙网

在利用操作系统网络栈时,通常是以下步骤,这里拿 TCP 协议举例。C7v免费翻墙网

在我们的例子中, TUN网络的配置为 198.10.0.1/16,主机IP为 198.10.0.1,代理客户端监听 198.10.0.1:1313,App想要访问 google.com:80,自定义的DNS服务返回google.com的 Fake IP 198.10.2.2C7v免费翻墙网

1. Proxy 创建 TCP Socket ListenerC7v免费翻墙网

这里首先要在系统网络栈的传输层开个口子,创建一个 TCP Socket Listener,监听 198.10.0.1:1313C7v免费翻墙网

2. 某 App 发起连接C7v免费翻墙网

当某需要代理的App发起连接,访问 google.com:80,我们通过自定义的 DNS 服务返回一个 Fake IP (198.10.2.2),使流量被路由到 TUN 设备上。C7v免费翻墙网

当然这里也可以不使用 Fake IP 方式来捕获流量,通过配置路由规则或者流量重定向也可以将流量导向 TUN 设备,不过 Fake IP 是最常用的方法,所以这里以此举例。C7v免费翻墙网

 C7v免费翻墙网

3. 将 TUN 读取到的 IPv4 解析为 TCP 载荷数据C7v免费翻墙网

TUN 设备捕获到流量,也就是 IPv4 数据包,在读取出来后,需要利用系统网络栈解析出 TCP 载荷数据。C7v免费翻墙网

这一步,需要将读取到的IPv4数据包进行修改,也就是我们上面说的 源IP、源端口,目标IP和目标端口,还有相应的 checksum 也需要重新计算。修改的目的是让 IPv4 数据包通过 TUN 注入到操作系统网络栈后,能够被正确路由并通过一开始监听的TCP Socket将最里层的 TCP payload 返还给我们。C7v免费翻墙网

C7v免费翻墙网

这里为了方便,直接将源 IP 和源端口设置为初始的目标 IP 和目标端口,在实际编程时,有更多的设置策略,也就是 NAT 策略。C7v免费翻墙网

4. 代理客户端请求代理服务器C7v免费翻墙网

此时代理客户端已经拿到了请求的真实 TCP 载荷,并且可以通过获取 TCP 连接的 peer 信息得到在第3步修改的源 IP 和源端口,通过这些信息可以通过查 NAT 表得到 App 真正想要访问的 IP 和 端口(甚至可以通过查 DNS 请求记录拿到域名信息),因此代理客户端可以根据自己的协议进行加密和封装等操作,然后发送给代理服务端,由代理服务端进行真实的请求操作。C7v免费翻墙网

Google

5. 将返回数据封包回 IPv4 并写入 TUNC7v免费翻墙网

通过代理客户端与代理服务端、代理服务端与谷歌的通信,拿到谷歌真正的返回数据,现在需要重新封装回 IPv4 数据包,还是利用系统网络栈:将数据写入 TCP Socket (198.10.0.1:1313) 中,便可以在 TUN 侧拿到封装好的 IPv4,就是这么轻松。C7v免费翻墙网

Kernel

6. App 拿到返回数据C7v免费翻墙网

Kernel

上面的过程便是利用操作系统网络栈完成 IPv4 到 TCP 载荷数据及其反方向转变的过程。通过这种办法,可以充分利用操作系统的实现,都是饱经检验,质量可靠,且满足各种复杂情况。但是也有缺点,数据需要拷贝多次,增加了性能损耗和延迟。C7v免费翻墙网

我这里想说的 NAT 策略不是指常说的那四种 NAT 类型,当然你可以去实现不同的NAT类型来满足各种各样的需求,但那是更深入的话题,不在本文讨论。C7v免费翻墙网

在刚刚的流程的第3步中,你应该发现对源 IP 和源端口的修改是有限制的,我们需要将 IP 限定为 TUN 网段,从而使返回的数据包可以重新被 TUN 设备捕获。但是这种限制是非常宽松的,在我们的例子对 TUN 设备网段的配置中,你有 2^16 个 IP 可供选择,每一个 IP 又有 2^16 个端口可供选择。C7v免费翻墙网

但是如果你仔细观察,你会发现上面的例子并没有充分利用这些资源,我们仅仅是将 Fake IP 作为源 IP、真实目标端口作为源端口,而这个 IP 的其他端口都被闲置了。同时我也在其他人写的某些程序中发现,他们仅选择一个 IP 设置为源 IP,通过合理的分配该 IP 的端口作为源端口,在这种情况下, TUN 网段中其余的 IP 资源就被浪费了。C7v免费翻墙网

以上两种 NAT 策略在个人电脑上没啥问题,但是如果代理客户端运行在网关上,网络中访问的 IP 数量超过网段中 IP 数量上限,或者 hash(ip:port) 数量超过端口总数(2^16),就会难以继续分配 NAT 项。因此我们应该专门编写一个 NAT 管理组件,合理分配 IP 和端口资源,争取做到利用最大化。C7v免费翻墙网

抛开事实不谈,如果我们想要代理全部流量,就是要通过路由规则将所有流量导向我们的 TUN 设备,这是很直观且朴素的想法,就像下面的命令一样单纯:C7v免费翻墙网

 
1
sudo route add -net 0.0.0.0/0 dev tun0

如果你真的这么写,你就会发现你上不了网了。这是因为出现了环路。C7v免费翻墙网

如果稍微思考一下,你就会发现,虽然我们想要代理所有流量,但是代理客户端与代理服务端的流量却是需要跳过的,如果用上面的路由,就会导致代理客户端发出的流量经过路由然后从 TUN 重新回到了代理客户端,这是一个死环,没有流量可以走出去。流量只近不出,来回转圈,你的文件打开数爆炸,操作系统不再给你分配更多的句柄,数据来回拷贝,你的CPU风扇猛转,电脑开始变卡。C7v免费翻墙网

这是我们不想看到的,需要采取一些措施避免环路的产生。在实践中有不少方法可以避免这种情况的发生,例如通过合理的配置路由规则,使连接代理服务器的流量可以顺利匹配到外部网络接口。只不过这种方法不够灵活,如果代理服务器 IP 发生变化则需要及时改变路由规则,非常麻烦,所以我们接下来介绍其他的方法。C7v免费翻墙网

Fake IP 就是我们上面例子中用到的方法,这是一种限制进入流量的方法。基本思路是自己实现一个 DNS 服务器,对用户的查询返回一个假的 IP 地址,我们可以将返回的 IP 地址限制为 TUN 设备的网络段,这样应用发起的流量其实便是发给 TUN 网络的流量,自然的被路由匹配,而无需像前面那样路由全部的流量,其余的流量包括代理客户端发起的请求便不会被路由,可以保证不产生环路。C7v免费翻墙网

当代理客户端需要知道应用真正想要请求的地址时,就通过一些接口向自己实现的 DNS 服务器进行反向查询即可。C7v免费翻墙网

通过前面的分析,可以发现产生环路是因为代理客户端本身发出的流量被系统路由到 TUN 设备导致的,因此我们可以想办法让代理客户端本身发起的流量不走 TUN 而是从真实的物理网络接口出去。C7v免费翻墙网

在 (类)Unix 系统中,可以对代理客户端的流量打上 fwmark 防火墙标记,然后通过策略路由使带有标记的流量走单独的路由表出去,从而绕过全局的流量捕获。C7v免费翻墙网

cgroupC7v免费翻墙网

cgroup 是 Linux 内核的功能,可以用来限制、隔离进程的资源,其中 net_cls 子系统可以限制网络的访问。在网络控制层面,可以通过 class ID 确定流量是否属于某个 cgroup,因此可以对来自特定 cgroup 的流量打上 fwmark,使其能够被策略路由控制。C7v免费翻墙网

我们可以创建一个用于绕过代理的 cgroup ,对该 cgroup 下进程的流量使用默认的路由规则,而不在该 cgroup 的其余进程的流量都要路由到 TUN 设备进行代理。C7v免费翻墙网

TAP 在2层,读取和写入的数据需要是以太帧结构C7v免费翻墙网

TUN 在3层,读取和写入的数据需要是IP数据包结构C7v免费翻墙网

在给网卡配置IP时,其实是修改内核网络栈中的某些参数,而不是修改网卡。虽然网卡也会有一些可供修改的配置项,但一般情况是通过其他方法进行修改的(驱动程序)。C7v免费翻墙网

物理网卡会有 DMA 功能,在启用 DMA 时网卡和网络栈(内存中的缓冲区)的通讯由 DMA 控制器管理,因此性能更高延迟也更低。C7v免费翻墙网

在Linux下一切皆文件,/dev/net/tun 是特殊的字符(char)设备文件,通过打开这个文件获得一个文件句柄,然后通过 ioctl() 系统调用对其进行配置。在这里可以选择打开TUN设备还是TAP设备,可以设置设备名称。C7v免费翻墙网

详见:Network device allocationC7v免费翻墙网

BPF 是一种高级数据包过滤器,可以附加到现有的网络接口,但其本身不提供虚拟网络接口。 TUN/TAP 驱动程序提供虚拟网络接口,可以将 BPF 附加到该接口。C7v免费翻墙网

来顶一下
返回首页
返回首页
欢迎评论:免登录,输入验证码即可匿名评论 共有条评论
用户名: 密码:
验证码: 匿名发表

推荐资讯

Octohide VPN:快如闪电的免费VPN
Octohide VPN:快如闪
原子网络加速器 - 免费高速VPN 一键链接 方便快捷
原子网络加速器 - 免费
foxovpn绿狐VPN——即连即用、快速、安全
foxovpn绿狐VPN——即
Dubai VPN - Free, Fast & Secure VPN下载
Dubai VPN - Free, Fa
相关文章
栏目更新
栏目热门
墙外新闻
读者文摘

你可以访问真正的互联网了。You can access the real Internet.

管理员精中特别提醒:本网站域名、主机和管理员都在美国,且本站内容仅为非中国大陆网友服务。禁止中国大陆网友浏览本站!若中国大陆网友因错误操作打开本站网页,请立即关闭!中国大陆网友浏览本站存在法律风险,恳请立即关闭本站所有页面!对于您因浏览本站所遭遇的法律问题、安全问题和其他所有问题,本站均无法负责也概不负责。

特别警告:本站推荐各种免费科学上网软件、app和方法,不建议各位网友购买收费账号或服务。若您因付费购买而遭遇骗局,没有得到想要的服务,请把苦水往自己肚子里咽,本站无法承担也概不承担任何责任!

本站严正声明:各位翻墙的网友切勿将本站介绍的翻墙方法运用于违反当地法律法规的活动,本站对网友的遵纪守法行为表示支持,对网友的违法犯罪行为表示反对!

网站管理员定居美国,因此本站所推荐的翻墙软件及翻墙方法都未经测试,发布仅供网友测试和参考,但你懂的——翻墙软件或方法随时有可能失效,因此本站信息具有极强时效性,想要更多有效免费翻墙方法敬请阅读本站最新信息,建议收藏本站!本站为纯粹技术网站,支持科学与民主,支持宗教信仰自由,反对恐怖主义、邪教、伪科学与专制,不支持或反对任何极端主义的政治观点或宗教信仰。有注明出处的信息均为转载文章,转载信息仅供参考,并不表明本站支持其观点或行为。未注明出处的信息为本站原创,转载时也请注明来自本站。

鉴于各种免费翻墙软件甚至是收费翻墙软件可能存在的安全风险及个人隐私泄漏可能,本站提醒各位网友做好各方面的安全防护措施!本站无法对推荐的翻墙软件、应用或服务等进行全面而严格的安全测试,因此无法对其安全性做保证,无法对您因为安全问题或隐私泄漏等问题造成的任何损失承担任何责任!

S. Grand Ave.,Suite 3910,Los Angeles,CA 90071

知识共享许可协议
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。