内网穿透工具的原理与开发实战
看起来是不是比较绕呢?事实上大名鼎鼎的花生壳内网版以及nat123等内网穿透工具的原理基本就是如此,但是并不完全是这样。因为一个运输层端口只能同时提供一种服务,但是我们会发现花生壳这种内网穿透服务是借助一个公网IP同时给很多用户提供了服务,这是因为花生壳在流量转发这一层上并不是像我之前所说的原封不动的将报文进行转发,而是在转发之前加了一些控制协议的内容,用于指明该转发到哪个花生壳客户端所在的内网主机上。前者这种原封不动的转发方式通常叫做透明传输或者透明代理。 穿透防火墙 为了安全起见,通常会在网络中加入防火墙,防火墙有入站规则和出站规则。如果不是非常严格的安全管控,通常是不会设置出站规则的,但是入站规则一般都会设置的,比如说外部可以通过80端口传入内网的WEB服务器访问网页,但是不能通过3389端口登陆内网的远程桌面。 而在内网渗透的过程中碰到这种情况,我们也可以借助上面内网传统的方式实现穿透防火墙的入站规则。因为防火墙通常只拦截了入站,没有拦截出站,那么我们可以让内网服务器主动出站(主动连接到黑客的服务器),与黑客自己的服务器打通隧道,最终绕过防火墙连上3389远程桌面。 还有一种情况就是我们已经拿下了内网其中一台并没有做任何防火墙规则的白名单服务器,但是我们想连上内网另一台做了入站规则的目标服务器,那么我们可以让这台白名单服务器作为一个跳板,让他先监听自身任意一个端口,然后在有任何用户连上这个端口之后,白名单服务器就主动连上内网的目标服务器,然后借助这台白名单服务器打通黑客和目标服务器的连接隧道。 而在黑客工具中大名鼎鼎的lcx原理也就是如此,前者的实现是lcx的listen和slave命令,后者的实现是lcx的tran命令。 代码实现 知道了原理之后,具体该怎么实现呢? 我这里选择了使用Go语言编程实现了这样一个内网穿透工具。 Golang本身提供了非常多的网络库,并且Golang本身内置的Goroutine能够很方便的处理网络编程中的异步IO,而且最重要的是,Golang开发的程序是可以跨平台运行的,意味着写了一份代码,我们可以在任何一个操作系统上编译并使用。 https://github.com/cw1997/NATBypass 初始运行时根据情况输出欢迎信息已经语法提示(这里要重点注意printWelcome函数末尾调用了time.Sleep阻塞一秒,这是因为fmt包输出是非线程安全的,而log包下的输出都是线程安全的,因此为了防止后面执行流中打的日志会穿插到提示信息中而使用该函数休息一秒钟)。 首先通过判断传入参数决定当前使用何种转发策略。 然后再判断传入参数是否正确,通过正则表达式等方式验证IP的合法性以及端口范围。 通过port2port函数实现了两个端口同时监听双向并且转发数据。 在port2host操作中实现了跳板中转。 在host2host中实现了主动连接打通隧道的功能。 看代码便可以知道,在Golang中进行socket操作的net包要比C语言中的socket.h操作简单很多。 转发功能的核心就在于forward函数部分。 先输出一个日志说明是对哪两个连接进行双向转发,然后通过sync包下的WaitGroup实现一个条件阻塞功能,防止在Goroutine还未执行完,主线程就已经退出了。 然后发射两个Goroutine,分别处理连接1到连接2的IO数据包拷贝以及连接2到连接1的IO数据包拷贝。因为要保证两个端口间的通信是全双工的,也就是两边同时都要能够互相交换数据,所以要用Goroutine来实现这两个操作的并发。 而IO数据包的拷贝核心代码在connCopy函数中,根据是否要记录流量日志判断是否要使用io.MultiWriter这个多路写数据流的函数。 (编辑:厦门网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |