前言
在中国,由于互联网用户众多,运营商无法保证每个宽带用户都将获得世界上唯一的公共IPv4地址。因此,许多用户会发现通过路由器查看的WAN端IP与通过百度“IP”关键字获得的IP不一致,前者的IP是私有IP。
在某些情况下,公共IP是昂贵的。虽然企业本身拥有少量的独立公共IP,但由于成本限制,它无法为企业中的每个主机提供公共IP。并非所有服务都需要暴露给公共网络进行访问,然后企业可以使用NAT技术通过某些规则将大量内部网IP映射到公共IP。最常见的技术之一是NAPT,也称为“网络端口地址转换”。由于服务通常通过端口提供,因此可以通过特定规则向少量公共IP打开特定服务。
问题
但有时我们的个人宽带用户也希望将他们的服务发布到公共IP。例如,我们创建了一个非常漂亮的网站,我们希望在互联网上发布,供所有人访问。如何在没有公共IP的情况下实现它?
同时,当我们对企业进行渗透测试时,我们发现企业的公共网络服务器只打开公共网络的公共80端口,以及我们筹集时需要使用的3389等端口权利不对公共网络开放。那我该怎么办?
解决这些问题的方法是通过内联网。
NAPT原则
简而言之,NAT网关上将有一个映射表。该表记录了Intranet向公共网络发送请求的IP和端口。然后,如果主机向公共网络设备发出请求,则内部网主机请求。数据包被传输到NAT网关,NAT网关将数据包的源IP地址和源端口修改为NAT网关自己的IP地址和任何自身未使用的非冲突端口,并记录修改那个。在映射表上。最后,将修改后的数据包发送给请求的目标主机,在目标主机发回响应报文后,根据目的IP地址和响应报文中的目的端口,找到映射表,找到哪个内联网主机转发到。这样,内网主机通过NAPT技术和没有公网IP的路由器的唯一公网IP地址访问公网设备。具体原则我去网上查找图片:
从这里可以看出,NAPT只解决了内网主机在没有公网IP地址的情况下访问公网主机的问题,但没有解决公网主机主动向内网主机发起请求的问题。
私人地址
私有地址在早期的RFC 1918文档中描述。
Internet Assigned Numbers Authority为专用网络维护以下三个IP地址块。
10.0.0.0 - 10.255.255.255(10/8位前缀)
172.16.0.0 - 172.31.255.255(172.16/12位前缀)
192.168.0.0 - 192.168.255.255(192.168/16位前缀)
我们可以看到有1个A类地址块,32个B类地址块和256个C类地址块。主流家庭路由器使用C型专用地址作为路由器LAN侧的IP地址,因此我们可以看到路由器设置页面的IP通常从192.168开始。
原因
我来谈谈家庭宽带的情况。如果家庭宽带没有公共IP地址,则表示您在此计算机上侦听的任何端口只能在本地网卡所在的网络中访问。该网络通常是路由器LAN端所在的网络。如果没有制定特定的映射规则,则连接到路由器WAN侧的网络将无法访问主机提供的服务。
如果您想在这种情况下让WAN端(如果运营商为您分配公共IP地址,那么连接到WAN侧的网络通常是公共网络),那么您需要在路由器上进行端口映射。例如,路由器的LAN IP为192.168.1.1,WAN IP为23.23.23.23。我希望内部网192.168.1.2主机的端口80提供的HTTP服务器可以通过公共网络上的http://23.23.23.23直接访问。映射192.168.1.2: 80到23.23.23.23: 80。
但是,通常,运营商不向普通用户提供公共网络IP。然后,在公共网络上仍然无法访问以这种方式进行映射,因为路由器的WAN端连接到运营商更高级别的路由器的LAN端。说真的,连层连接最终都连接到公共网络。此行为称为流量渗透。一定的国内电力,某种宽带有很多这种行为。通过流量渗透提供的宽带服务似乎很便宜,但它有很大的影响。因为每个人共享一个IP,可能会导致许多网站的反垃圾邮件策略无辜,或者在内部节省带宽和使用缓存。一些不应缓存的敏感安全页面会被缓存,甚至一些网站缓存失败也完全无法实现。有些人发现即使他们有公共IP,他们仍然无法通过传统方法设置服务器。到底是怎么回事?这是为了防止黑客打开各种非法服务,防止黑客攻击扫描仪。鸡肉和批量扫描,一些常见的端口已被禁止,例如,中国电信将阻止80,8080和其他端口。这个禁令,虽然在一定程度上确保了我们的网络安全,例如,前一段时间的勒索软件病毒,因为大多数国内用户没有独立的公共IP,而且操作系统最容易受到一些漏洞的影响, 135,139和其他港口被禁止运营商,使得在国内个人家用电脑中招聘的可能性要小得多;但是,即使存在公共网络IP,也不可能使用公共端口向外部网络提供服务,而只能向其他端口提供服务。这有什么问题?典型的问题是WEB网站默认使用端口80,因此输入URL时不需要输入端口号,这样更漂亮。
解
如果我们遇到上述情况,我们该如何解决呢?
如果我们没有公共网络服务器,我们可以使用国内着名的“花生壳”,“nat123”等服务来实现,但它们背后的原理是什么?
如果我们有公共IP服务器,我们可以使用此公共IP服务器来提供服务。以及如何具体操作?
解决方案实施
假设我们有一个公共网络服务器,其IP为45.45.45.45。我们有另一个内部网服务器IP为23.23.23.23。我们现在要打开23.23.23.23: 80,内网服务器上的HTTP服务为45.45.45.45。
最简单和最粗鲁的方式是我们可以直接在公共网络服务器上重建整个Intranet服务器环境。
但这很麻烦。我们有时不想这样做。我们只想简单地使用公共网络服务器的网络来发布内联网服务。
过去,我们通过NAPT原则了解到NAPT使Intranet主机能够在没有公共IP的情况下访问公共网络主机。然后我们可以这样做:假设公共网络IP是23.23.23.23,内部网IP是192.168.1.2。公共网络主机首先侦听端口80.该端口用于向外部提供HTTP服务,80是WEB服务器的默认端口。同时,任何其他端口(这里我们假设7777),该端口用于让Intranet服务器主动连接以打开隧道。然后,Intranet向公共网络主机的7777发起请求,以便内部网成功建立与公共网络主机的连接通道。然后,当任何客户端主动连接到公共网络的端口80时,公共网络在接收到连接请求后立即通过先前建立的隧道将连接请求转发到内联网主机,并且内联网主机从隧道接收数据分组。然后主动连接到内部端口主机自己的端口80.连接成功后,数据包将按原样转发到端口80。在HTTP服务器程序处理数据包之后,生成响应包然后转发回。最后,它到达公共网络的端口80,然后返回到最初请求公共网络服务器80的端口的客户端。它似乎更多或更少?事实上,着名的花生壳网内版和nat123等内联网穿透工具的原理基本相同,但并不完全正确。因为传输层端口只能同时提供一种服务,但我们会发现花生网这种内联网渗透服务通过公共IP地址同时为许多用户提供服务。这是因为花生壳正在流量转发。在该层,我没有按照我之前的说法转发消息,但在转发之前添加了一些控制协议,以指示哪个花生shell客户端被转发到Intranet主机。前者,原始转发方法通常称为透明传输或透明代理。
穿透防火墙
出于安全原因,防火墙通常会添加到网络中,防火墙具有入站和出站规则。如果不是非常严格的安全控制,通常不设置出站规则,但通常设置入站规则。例如,外部可以通过内网的80端口WEB服务器访问网页,但无法通过3389端口登录。 Intranet的远程桌面。
在内部网络渗透的过程中,我们还可以使用传统的内部网络方式来实现穿透防火墙的入站规则。因为防火墙通常只拦截入站并且不拦截出站,所以我们可以让内网服务器主动退出站点(主动连接到黑客的服务器),用黑客自己的服务器打开隧道,最后绕过防火墙和连接到3389远程桌面。
另一种情况是我们已经采用了其中一个内部网并且没有为白名单服务器制定任何防火墙规则,但我们希望连接到已制定入站规则的内部网上的另一个目标服务器,然后我们可以将其作为白名单服务器充当跳板,允许他收听自己的任何端口,然后在任何用户连接到端口后,白名单服务器主动连接到Intranet的目标服务器,然后使用白名单服务器打开黑客。到目标服务器的连接隧道。
黑客工具中着名的lcx原则也是如此。前一个实现是lcx listen和slave命令,后一个实现是lcx tran命令。
码
了解原理后,如何实现呢?
我选择使用Go编程实现这样的Intranet渗透工具。
Golang本身提供了大量的网络库,Golang的内置Goroutine可以轻松处理网络编程中的异步IO,最重要的是,Golang开发的程序可以跨平台运行,这意味着已经编写了一个。代码,我们可以在任何操作系统上编译和使用。
https://github.com/cw1997/NATBypass初始运行时输出欢迎消息根据情况已经有语法提示(这里一定要注意调用time.Sleep在printWelcome函数结束时阻塞一秒,这是因为fmt包输出是非线程安全的并且日志包下的输出是线程安全的。因此,为了防止将后续执行流中的日志插入到提示消息中,请使用此函数休息一秒钟。
首先,通过确定传入参数来确定当前使用的转发策略。
然后确定传入参数是否正确,并通过正则表达式验证IP的合法性和端口范围。
port2port功能使两个端口能够同时监听双向和转发数据。
Springboard传输是在port2host操作中实现的。
主动连接隧道的功能在host2host中实现。
查看代码,您知道Golang中的套接字操作的网络包比C中的socket.h操作简单得多。
转发功能的核心是前向功能部分。
首先输出一个日志,指示在两个方向上转发哪两个连接,然后通过同步包下的WaitGroup实现条件阻塞功能,以防止主线程在Goroutine尚未执行后退出。
然后传输两个Goroutines,分别处理连接1的IO数据包副本到连接2和连接2的IO数据包副本到连接1。因为有必要确保两个端口之间的通信是全双工的,也就是说,双方必须能够同时互相交换数据,所以有必要使用Goroutine来实现两者的并发性。操作。
IO数据包的复制核心代码在connCopy函数中,根据是否记录流量日志判断是否使用io.MultiWriter多路写入数据流功能。
如果打开的日志文件的文件流成功,则io.MultiWriter函数将生成多路复用的写入流。这里,多路复用写入流的变量被命名为w,并且同时写入写入w写入流的任何数据。在先前参与执行多写流创建功能io.MultiWriter的参数中,这里的参数是conn1和logFile,它是端口1和日志文件流。
然后,调用io.Copy以将在第二参数的读取流中读取的数据源连续复制到第一参数的写入流中。
这里应该注意io.Copy功能是同步阻塞的,这意味着只要连接没有被破坏,程序执行流程就会一直停留在这个功能中。如果复制失败,将返回io.Copy函数,即执行下面的代码。复制错误意味着连接可能已断开连接,因此首先断开与写入流的连接。重要的是要注意为什么写流被断开而不是读写流。因为我们在我们面前发射了两个Goroutines,如果全部盲目断开,将导致另一个Goroutine丢失未写入的数据。具体来说,可以根据TCP分析四次。
实际执行
如果您没有Golang环境,则可以直接下载已编译的可执行文件。下载地址:https://github.com/cw1997/NATBypass/releases
我们来看看代码编译后的实际操作。上图的左侧显示了虚拟机运行的Intranet服务器。他设定了入境规则。直接连接192.168.2.112: 3389无法连接到远程桌面。