基于JAVA的工具的实现
齐鲁学院基于JAVA的内⽹穿透⼯具的实现
基于JAVA的内⽹穿透⼯具的实现
上古卷轴5外交豁免内⽹穿透的说明
内⽹穿透,即NAT穿透,⽹络连接时术语,计算机是局域⽹内时,外⽹与内⽹的计算机节点需要连接通信,有时就会出现不⽀持内⽹穿透。就是说映射端⼝,能让外⽹的电脑到处于内⽹的电脑。不管是内⽹穿透还是其他类型的⽹络穿透,都是⽹络穿透的统⼀⽅法来研究和解决。
NAT技术
NAT技术是通过将专⽤的⽹络地址转换为公⽤地址,从⽽对外隐藏了内部管理的IP地址。这样,通过在内部使⽤⾮注册的IP地址,并将它们转换为⼀⼩部分外部注册的IP地址,从⽽减少了IP地址注册的费⽤以及节省了越来越缺乏的地址空间。同时,这也隐藏了内部⽹络结构,从⽽降低了内部⽹络受到攻击的风险。NAT的功能就是在内部⽹络的私有地址需要与外部通信时,把内部私有地址转换成合法的全局IP地址。NAT可以在两个⽅向上隐藏地址,为了⽀持这种⽅案,NAT在两个⽅向上都要翻译原地址和⽬的地址。NAT的功能通常被集成到路由器、防⽕墙等设备中。NAT设备维护⼀个映射表,⽤它来实现全局到本地和本地到全局的地址转换 [2] 。
NAT有三种类型:静态NAT(StaticNAT)、动态地址NAT(PooledNAT)、⽹络地址端⼝转换NAPT(Port-LevelNAT)。
其中,⽹络地址端⼝转换NAPT(NetworkAddressPortTranslation)则是把内部地址映射到外部⽹络的⼀个IP地址的不同端⼝上。它可以将中⼩型的⽹络隐藏在⼀个合法的IP地址后⾯。NAPT与动态地址NAT不同,它将内部连接映射到外部⽹络中的⼀个单独的IP地址上,同时在该地址上加上⼀个由NAT设备选定的端⼝号。
NAPT是使⽤最普遍的⼀种转换⽅式,在HomeGW中也主要使⽤该⽅式。它⼜包含两种转换⽅式:SNAT和DNAT。
(1)源NAT(SourceNAT,SNAT):修改数据包的源地址。源NAT改变第⼀个数据包的来源地址,它永远会在数据包发送到⽹络之前完成,数据包伪装就是⼀具SNAT的例⼦。
(2)⽬的NAT(DestinationNAT,DNAT):修改数据包的⽬的地址。DestinationNAT刚好与SNAT相反,它是改变第⼀个数据懈的⽬的地地址,如平衡负载、端⼝转发和透明代理就是属于DNAT。
SOCKET介绍
套接字(socket)是⼀个抽象层,应⽤程序可以通过它发送或接收数据,可对其进⾏像对⽂件⼀样的
打开、读写和关闭等操作。套接字允许应⽤程序将I/O插⼊到⽹络中,并与⽹络中的其他应⽤程序进⾏通信。⽹络套接字是IP地址与端⼝的组合。
内容过多,这⾥不在过多的赘述,这篇有很全⾯的介绍,包括TCP/IP⽹络协议的介绍,这也是实现⽹络穿透的⼀个保证,即不考虑⽹络连接情况将数据内容进⾏完全转发,协议的解析等⼯作与直连⽅式不变。 在不考虑⽹络连接带来的IP变化的情况,可以将内容进⾏完全转发,协议的解析等⼯作与直连⽅式不变;也可以将协议通过解析后,再根据⽬标的协议进⾏组装,如HTTPS协议转HTTPS协议。
穿透思路
因NAT⽹内CLIENT可以正常连接到SERVER端,并且能够保持⼀段时间的长连接,则由CLIENT发起连接,建⽴SOCKET对,在SERVER 收到外部请求时,可以通过已经建⽴好的SOCKET将数据传输给CLIENT,CLIENT使⽤相同的⽅式将数据发送给指定的⽹络程序,⽹络程序回发数据后则按原路返回给请求⽅。pc单机游戏
开始前我们先约定下词语:“客户端”:“穿透内⽹端”,“服务端”:“穿透外⽹端”,“应⽤”:“内⽹服务”,“请求”:“外部⽹络请求”。
从以上时序图可以看出,⾸先要使⽤⼀台外部⽹络的服务器(竟然有了外部⽹络,⼲嘛还要使⽤内⽹
做事情?这个内⽹穿透主要是⽤来公司、团队形式的开发测试使⽤,当然也可以将⾃⼰内⽹的机器映射到外⽹,只要每⽉⼏⼗块就可租台⾃⼰的服务器,⽐如 “⼴告位招租”云)。
我要怒放的生命
内⽹需要⼀个客户端来提供隧道的打通⼯作,服务端⽆法直接向客户端发起连接,那么服务端怎么通知客户端?则就需要客户端提前建⽴⼀个长连接的socket对(交互线程),那么在有新连接请求时则可以通过交互线程通知客户端有新连接过来;则客户端发起⼀个新的socket 连接,服务端收到新建⽴的socket后则将这个socket与请求的连接按“读对写、写对读”的⽅式建⽴隧道,客户端使⽤相同的⽅式将新的socket连接与内⽹连接建⽴隧道。
以上就绪后则可以将“请求”发来的数据通过两端隧道发送到应⽤上,应⽤收到数据则作出相应的返回;这个过程便可以完成⼀个完整的⼀问⼀答的请求(典型案例HTTP请求)了,那么再将这个隧道维持⼀个持久性,则可以做到外部请求到应⽤的长连接了(⽐如HTTP1.1、数据库连接等)。到这⾥便可以看出来,这个是固定端⼝的⽅式,那么像FTP这样的动态数据端⼝该怎么解决呢?我不知道 >_>。
在开发过程中有⼏个遇到的问题,在这⾥直接抛出来分享下,如果有更好的解决⽅案请留⾔:
1. 新建⽴socket后,如何将连接配对?在新请求过来后,服务端向客户端发送通知携带⼀个格式化的不同串,根据字符串则可以获悉要
对应哪个请求,从⽽建⽴隧道;但是现在的问题是在客户端不能向应⽤建⽴socket的时候,则按异常处理,不应向服务端建⽴连接,那么服务端则⼀直在等待状态,针对这个等待做的是线程进⾏定时清理超时连接。 定时清理很有效果。
2. 在隧道出现异常(即⽹络断开或请求主动断开)的时候需要向上通知异常退出,当前⽤的是将⾃⾝作为参数传⼊,需要退出时⼦调⽤
⽗函数,进⾏通知关闭,这样耦合太⾼了,如果使⽤control的形式,那么⼦存的参数更加的多,聚合度⼜差点。 ⽤通知接⼝类的⽅式很⾹。
3. 隧道传输过程的加密没有实现。 natcross2实现了。
4. ⾃⾝HTTPS的协议⽅式没有实现,当前的做法是结合nginx的⽅式将HTTPS协议转换成HTTP协议来进⾏传输。 使⽤
SSLServerSocket实现了HTTPS协议的传输,当然只是接收的时候是HTTPS,向⽬标传输时还是HTTP协议,换句话说就是隧道将SSL的外壳去掉了
婚变电视剧5. 总有⼀些莫名的连接持续存在,也不报错退出,即时请求端、应⽤端的机器都关掉。 退出时中间有报错⽽终⽌了线程,导致没有正常
关闭端⼝,出问题的地⽅已经使⽤捕获异常处理了。
代码
本着 “Talk is cheap. Show me the code.” 原则,我们直接上代码。
拍一拍功能在哪里设置
1.  不再维护了,建议使⽤
2.
3.
感兴趣的同学只选择natcross2进⾏使⽤即可,natcross-boot、natcross-boot-client是⼀种快捷的封装,主要是为团队⽅便管理写的管理程序,不⽤细研究,所有值得看的都在natcross2中了
以上三个分别是核⼼码、共⽤的服务端、共⽤的客户端。
核⼼码即主要代码,这个库已经可以做到内⽹穿透的功能业务,ServerApp运⾏在服务端,ClientApp运⾏在内⽹,便可以进⾏了,这个核⼼码已经⽀持了多端⼝的监听,客户端创建多个ClientControlThread便可以实现多映射的穿透。
公⽤服务端,是针对公司、团队的环境进⾏的WEB管理⽅式的封装,使⽤spring-boot作为框架进⾏部署,登录后便可以⾃由添加修改端⼝情况。使⽤sqlite进⾏数据持久化。
初始化密码,⽤户名:admin 密码:123456
web管理⽅式
共⽤客户端,则是和公⽤服务端配套的设置,可以将客户端部署到⼀台内⽹机器上,客户端会定时获取服务端的设置来建⽴⾃⼰的客户端线程,从⽽实现⾃由定制化。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。