首页 > 编程知识 正文

搭建ipfs网关,外部网关协议BGP

时间:2023-05-05 19:39:07 阅读:137600 作者:842

by fanxiushu 2021-04-13转载或引用请注明原创作者。

如前一篇文章所述,在xFsRedir软件中使用WFP驱动器框架实现了虚拟局域网功能

(包括创建虚拟LAN节点和到实际LAN的桥接)

您打算使用现成的WFP驱动程序实现其他什么功能?

WFP足够强大,只有虚拟LAN没能充分发挥WFP的价值,所以考虑了代理店。

另外,只需稍微修改我原来的虚拟局域网驱动程序,就可以实现代理功能的驱动程序部分。

当然,如果是APP应用层处理逻辑的一部分,就必须另外开发。

虽然我平时也不怎么用代理互联网。 但是,看了很多类似软件,各种各样。

可能最多的是制作游戏加速器

但是,实现局域网的主机代理的软件似乎并不多。

host agent与以前在CSDN文章中介绍的类似。

3359 blog.csdn.net/fanxiushu/article/details/109098980 (通过网络驱动的代理连接局域网中的所有设备,如WFP ) )。

简单来说,就是把某台A电脑当成网关机,把局域网内其他设备的网关地址设定为A电脑地址,

然后,a电脑按照通常的处理逻辑,在IP和TCP/UDP层修改对应的地址和端口,

然后,NAT网关功能将局域网中所有设备的数据包转发到真正的目标地址。

如果a同时充当代理计算机,则它会将这些数据包转发到代理服务器,然后代理服务器会将数据发送到真正的目标地址。

这意味着网关A机器充当局域网中其他设备的NAT网关路由和代理客户端。

这就是主机代理。 为了方便称为NAT网关代理。

在以上链接的文章《基于WFP等网络驱动实现局域网内所有设备通过代理上网》的描述中,如何实现分组代理转发?

在文章的最后,简述了如何将截取的IP数据包按照定制的协议格式封装后发送到服务端

服务端自己对IP数据包进行解封装,利用虚拟网卡和NAT路由将IP数据包转发到真正的目标。

也就是说,整个代理通信过程都是在走IP包,在底层进行的。

这是一种相对高效的方法,因为它直接传输IP数据包,无需绕圈子。

当然,有时代理协议的格式必须自己定义,服务端必须自己实现。 不像SOCKS5,HTTP代理那样有一大堆服务器软件。

但是,使用linux系统作为服务器时,所有虚拟网卡和NAT路由都是系统附带的,开发过程中不需要太多精力。

因此,总体上也不需要在代理服务器上开发太多精力。

此外,通信协议格式是自定义的,因此可以采用尽可能多的模糊算法,以避免防火墙以协议格式侦听通信。

本文介绍提取IP数据包,组装成SOCKS5协议,发送到通用的SOCKS5代理服务器的方法。

本文选择了SOCKS5协议。 为了让大家容易理解,

另外,SOCKS5协议形式的TCP部分非常简单,作为基础的IP数据包的TCP部分容易变换为SOCKS5协议。

但实际上,SOCKS5处理UDP代理非常困难,不同的SOCKS5代理服务器可能不一定支持,也可能难以理解。

这可能是因为和初始定义的FTP协议一样,初始定义SOCKS5协议的人们的大脑回路发生了变化。

只是,使用的时间太长,已经定型了,不能再改变了。

(因此,与xFsRedir集成的代理功能很可能会使用自定义协议进行传输,这将在那时决定。)

但是我确信我不想在xfs_rdsvr服务器端集成虚拟网卡和NAT路由功能。

因为不是追求效率,而是只要求xfs_rdsvr服务端在各平台上通用且尽可能简单。

这意味着将IP数据包转换为APP应用层通信协议,如本文所述。 )

打包IP包并将其解析为APP应用层数据不是一个简单的过程。 就像这里一样

如3359 blog.csdn.net/fanxiushu/article/details/87958656中所述

在NAT外网侧,试图将IP分组变换为APP应用层的套接字,实现TCP协议栈。

在windows系统上本机实现某个进程或某个进程的SOCKS5代理

(即使这些程序本身不支持SOCKS5代理),方式也相当多。

的文章也简单叙述了,APP应用层使用LSP,或者直接hook某个流程的send、recv等函数等。

或者,使用WFP驱动的Connect Redirect功能将连接转发到127.0.0.1端口。

然后在本地实现侦听此端口的程序,以实现到SOCKS5服务器的代理连接。 等等。

但是,本文描述的功能不仅包括实现本机代理,还包括将本机作为NAT网关。

此时,上述方法不再适用,您只需处理IP数据包,就必须通过SOCKS5代理协议发送数据

只能将IP数据包转换为APP应用层的SOCKS5协议。

首先,让我们看一下SOCKS5协议格式。 (符合TCP代理部分,符合版本5,版本4除外。 )

其实很简单,为了

尽量简单,下面不包括密码验证部分。
首先我们在应用层创建一个socket套接字之后,调用connect函数成功连接到SOCKS5代理服务端,
客户端就开始向SOCKS5服务端发送请求协议版本以及认证方式,
1,具体就是发送3个字节的认证:
      0x05 0x01 0x00 意思是SOCKS版本是 5, 请求一种认证方式,认证方式是无密码的认证。     
2,SOCKS5服务端回复2个字节的认证结果:
     0x05 0x00 第一个字节表示版本5, 第2个字节如果是0 表示认证成功,可以继续
3,客户端发送需要连接的真正目标地址和端口信息,以IPV4地址为例,一共是10个字节的数据:
    0x05 0x01 0x00 0x01 | 0x0a 0x0b 0x0c 0x0d | 0x0A 0x0B 
     第一个字节是版本号,第2个字节是表示CONNECT连接,第3个是保留设置0,第四个是后面地址类型,1表示IPV4地址,
     接下来4个字节表示IPv4的地址,是网络序,最后两个字节是端口,也是网络序。
     意思就是告诉SOCKS5服务端,我想连接真正的服务端地址是 0x0a 0x0b 9x0c 0x0d ,连接的真正端口是 0x0A 0x0B
4,  SOCKS5服务器也回应10个字节应答数据:
     0x05 0x00 0x00 0x01 | 0x00 0x00 0x00 0x00  | 0x00 0x00
     第一个字节代表版本号,第2个字节如果是0 表示成功,其他值表示失败,第3个字节保留设置0,第4个字节表示地址类型,1表示IPv4地址
     接下来4个字节表示代理服务器的地址,最后两个字节表示代理服务器端口,不过这两个是可选的,
     本身客户端connect的时候就已经知道代理服务端的地址和端口了,所以这两个就是多余的。

以上就是普通的 请求-应答流程,一共两个来回。
客户端一共向服务端发送 3 + 10  = 13个字节的数据, 服务端回复 2 + 10 = 12个字节的数据。
这些信息,都对在下面讲述的 IP数据包 组装成SOCKS5协议有用。

接下来再来看看 TCP三次握手的过程:
1, 客户端在应用层调用connect发起连接请求的时候,
       操作系统底层首先会发送一个只包含TCP头以及一些附加信息的IP数据包给服务端,
       这个IP数据包就是 在TCP头部只设置SYN(不会设置ACK标志)标志的数据包,简称SYN包。
       同时SYN包还会包括一个系统随机生成的seq序列号,这个SYN数据包 简单记作:
       SYN = X,(X数系统随机生成的序列号)
2,服务端接收了请求,同样也回复一个只包含TCP头的IP数据包给客户端,
      这个IP数据包TCP头部设置了 SYN标志和ACK标志,我们称作 SYN+ACK 数据包。
      同时SYN+ACK数据包还有一个服务端系统随机生成的seq序列号, 同时会把请求ack序列号增加1,具体就是:
      SYN=Y,ACK=X+1 (Y是服务端系统随机生成的序列号,ACK的数值是客户端序列号+1)
3,客户端接收到了这个syn+ack包,回复ack确认数据包,这个确认数据包的 ack号=Y+1
      这个时候connect成功返回,TCP连接建立,我们之后就可以使用send,recv等函数发送和接收数据了。

有了以上两个方面的知识,我们就可以开始组装底层的IP数据包了(处理IP数据包的TCP部分),
首先我们肯定得跟踪每条完整的TCP连接,如何跟踪TCP连呢?
根据上面的TCP三次握手过程,我们应该很容易找到TCP的线头,那就是SYN数据包,
找到SYN数据包的时候,记录下目标地址,目标端口,源地址,源端口,协议(当然是TCP),也就是我们通常说的五元租。
然后以后的所有IP数据包中,都根据这个五元组确定是否属于某条TCP连接上的数据传输。这个就是TCP跟踪。
不过这里代理的情况有点特殊,因为IP数据包都是统一朝SOCKS5服务端发送,也就是目标地址和目标端口都是固定的,
我们得根据三元组来再加上SOCKS服务端地址来确定每条TCP连接,这个是否能确定呢?
答案是绝大概率可以的,因为我们都是connect发起方,不是服务端accept接收方。
每次connect的时候,系统都会分配不同的端口,不会有端口重复。即使重复也是非常小概率事件,
或者人为的故意在connect之前调用bind绑定。

当我们追踪到一条完整的TCP连接,但是这条TCP连接是朝真正的目标地址发起的,
该如何修改这条TCP连接,让它按照我们的要求,走SOCKS5代理服务器呢?
那就得修改对应的IP数据包,发出去的IP数据包的目标地址和端口改成SOCKS5服务端的地址和端口,
从SOCKS5接收到的IP数据包再把源地址和端口改回原来发出去的真正目标地址和端口。
光这样改还不行,因为SOCKS5是应用层协议,SOCKS5本身有协议头,
因此我们还得修改IP数据包内容,具体就是在上面描述的那样,在客户端发送13个字节的数据,
同时接收的时候还得首先处理SOCKS5服务端发来的12个字节的回复,
完成这个步骤之后,剩下的数据才能原封不动的只管投递即可。

IP数据包的修改注意事项,我在很早的文章有描述:
https://blog.csdn.net/fanxiushu/article/details/8624364 (网络数据拦截之:修改TCP包内容时注意的问题)
其中最麻烦的是seq和ack序列号的追踪和修改。

好在这里的SOCKS5协议足够简单,否则改起来还真不容易。可是即便这样,修改IP数据包也并不容易。
如何在TCP连接中首先插入这13个字节的SOCKS5协议头呢?

我们在发送SYN数据包的时候,记录下真正的目标地址,然后修改目标地址到SOCKS5服务器地址,
这里有个关键问题:关于这个seq序列号的问题:
因为我们可以预见,我们需要一共额外的发送13个字节给服务端,
如果这个SYN数据包不修改这个seq值,那在以后每个数据包都得调整seq和ack值,这样做就比较麻烦。
所以可以考虑在SYN包的时候,把seq序列号前退13个字节, 具体就是  seq = seq - 13 ,

然后在接收到SOCKS5服务端回复的SYN+ACK数据包的时候,开始执行发送SOCKS5协议头计划。
这个接收到的SYN+ACK数据包暂时不朝我们的系统投递,
我们在这里组装一个ACK回复包 + 3个字节的SOCKS5认证的数据,朝SOCKS5服务端发送,
这样SOCKS5接收到数据包之后,就认为连接已经建立了,并且还同时接收到了3个字节的认证数据。
组装这个数据包的时候,也有个关键点: 那就是SYN+ACK回复包中的服务端的seq序列号问题。
因为我们可以预见,我们需要一共额外的从服务端接收12个字节的SOCKS5协议的应答头,
同样的如果这个SYN+ACK数据包不修改这个seq值,那在以后每个数据包都得调整seq和ack值,这样做就比较麻烦。
所以可以考虑在回复ACK包的时候,把seq序列号前退12个字节, 具体就是  seq = seq - 12 ,

接着SOCKS5服务端确认认证方式,发送2个字节的确认数据包过来,
我们接着自己处理这个数据包,
然后再组装10个字节的真正目标地址的SOCKS5请求协议朝SOCKS5服务端发送,
注意调整seq和ack的值。
再然后就是接收SOCKS5服务端发来的10个字节的最终SOCKS5确认信息,
这样SOCKS5协议头的交互就完成了,我们与SOCKS5完成了真正的连接。

但是回到我们本身系统来。
自从我们拦截到本地系统发来SYN数据包之后,就一直在自己跟SOCKS5服务端交互,从来没回复过数据给系统。
因此在完成SOCKS5协议头认证之后,我们得开始回复SYN+ACK数据包给系统,
可以使用之前保存的SOCKS5回复的SYN+ACK数据包给本地系统,记得修改源地址。
因为之前seq和ack都采用了回退算法,这里的以及后面的数据包的 seq和ack都不需要修改了。

再然后系统接受到 SYN+ACK,它认为到目标地址连接成功了(其实是我们做了手脚,真正连接到SOCKS5代理服务器上去了)
然后系统就会开始回复ACK数据包,开始收发数据。在以后的数据包中,我们只需修改对应的地址和端口,然后忠实的投递即可。

以上讲述得比较简单,实际操作的时候,其实需要考虑许多问题,
比如需要考虑丢包重传问题,虽然我们自己交互的数据包就4个,不多,但是也无法保证不会丢包,因此必须处理这种情况。
比如需要仔细计算seq和ACK序列号问题。比如认证失败的时候如何断开两端的问题, 等等。。。

从理论上来说,我们可以在SYN+ACK的时候,直接回复 13个字节给 SOCKS5服务端,这样可以减少处理步骤。
因为TCP本身就是流式连接,这样也不算错。
但是考虑到我们通常的编程习惯和处理数据的习惯,还是分开来好些。

以上算法,倒是是我联想到了另外一种情况:
https://blog.csdn.net/fanxiushu/article/details/87958656  (NDIS协议驱动开发(另类的NAT路由程序开发))

当时就是想把NAT路由程序的外网一侧转成 应用层的 socket 套接字,
当时确实实现了这么一个程序,而且也确实成功把外网一侧的IP数据包转成了socket套接字连接真正的目标,
但是当时使用的是简单的组包TCP的算法,比起系统自己的组包效果差远了,所以在网络不太好的情况下,容易出问题。

而借这次把IP数据包通过修改包内容,把IP数据包转成SOCKS5协议的做法,
完全可以把IP数据包添加某个代理协议头,然后开启本地某个程序,接收这些特定代理协议的TCP连接,
不就堂堂正正的把IP数据包转成socket连接了吗? 而且TCP组包依然使用系统自己的组包算法。
因为我们自己组装TCP包太复杂太麻烦。肯定不如经过几十年发展得稳定的TCP组包算法。

写这篇文章的时候,正在开发 xFsRedir 的代理功能,并且实现了上面所述的把IP数据包转成SOCKS5代理协议的TCP部分,
不过在仔细研究SOCKS5的UDP代理之后,可能会放弃SOCKS5,转而使用自己定义的协议来处理。
xFsRedir是需要实现具备NAT功能的代理,也就是能代理内网的其他机器的通讯,因此也只能采用修改IP数据包的算法,
当然同时也会一起处理本机代理,也是通过修改IP数据包。

如果有兴趣,可关注GITHUB上的xFsRedir
https://github.com/fanxiushu/xFsRedir

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。