icmp篇 突破TCP-IP过滤/防火墙进入内网


随着Internet网络的普及 , 各个中大型公司均建立了自己的局域网络 。而公司内部人员上网的限制也逐渐成为一个大家关心的话题 。目前最为流行的网络工具大多是基于TCP/IP协议的 , 而其中最主要的两个协议就是TCP和UDP协议 。HTTP , FTP等上层协议均是建立在TCP协议之上了 , 而DNS , ICQ , TFTP等则是建立在UDP协议之上的 。往往我们会遇到这样情况:公司禁止了UDP协议 , 因为很大一部分的网络通讯软件都是建立在UDP协议之上的 , 而开通了TCP协议 。这样 , 我们就可以通过TCP协议来为我们转发UDP数据报 , 具体实现原理可以参看eyas的《突破TCP-IP过滤/防火墙进入内网》 , 里面详细讨论了如何实现TCP与UDP数据报之间的相互转发 , 也可以参看本文相关软件T-QQ的源代码 , 里面也包含了TCP与UDP相互转发的功能 , 在此就不多说了 。现在进入正题 , 如何实现用ICMP数据报来突破网关的限制?
ICMP协议(Internet Control Messages Protocol, 网际控制报文协议)是一种多功能的协议 , 在网络上有很多用处 , 比如ICMP扫描 , 拒绝服务(Dos)攻击 , 隧道攻击 , 以及我们最常用到的PING程序 。而我们就是利用ICMP协议来为我们传送(TCP/UDP)数据 。大家知道一般的防火墙都是过滤了来自外部主机的回送请求(echo Request)报文 , 但为了是自己能够探测外部主机的当前状态 , 防火墙都不会过滤掉回送应答(echo Reply)数据报 , 而且ICMP报文可以在广域网上传送 , 这样我们就可以利用它来突破网关的种种限制 。本文主要针对使用ICMP协议来转发UDP数据报的功能 , 并以OICQ为背景 , 至于突破TCP的限制 , 也大同小异 。
以下是QQicmp的工作原理:----->----- ----->----- ----->-----
QQ客户端 < UDP > QQicmp(l) < ICMP > QQicmp(g) < UDP >Tencent服务器
-----<----- -----<----- -----<-----其中QQ客户端和QQicmp(l)都运行在本机上 , 而QQicmp(g)则是运行在网关上(QQicmp(l) 与 QQicmp(g)均是同一程序 , 只是运行模式不同:-l 运行于本地主机 , -g 运行于网关上) , Tencent服务器我想大家都清楚吧 。QQ客户端与QQicmp(l),QQicmp(g)与Tencent服务器之间以UDP通信 , QQicmp(l)与QQicmp(g)之间则是以ICMP通信 。Win2000/xp都提供了自己构造数据报的功能 , 也就是我们可以自己定义发送数据报的各项内容 , 当然也可以监听通过主机的基于IP协议的各种数据报 。为了发送ICMP数据报及接收所有的IP数据报 , 我们必须自定义数据报的格式及校验和的求解:
typedef struct ipheader
{
unsigned char h_lenver; //头部长度及版本
unsigned char tos; //服务类型
unsigned short total_len; //报文总长度
unsigned short ident; //信息包标志
unsigned short frag_and_flags; //标志及分段偏移量
unsigned char ttl; //生命周期
unsigned char proto; //协议类型
unsigned short checksum; //IP校验和
unsigned int sourceip; //源IP地址
unsigned int destip; //目的IP地址
}ipheader;typedef struct icmpheader
{
unsigned char type; //ICMP类型 0->回送应答 8->回送请求
unsigned char code; //代码
unsigned short checksum; //校验和
unsigned short seq; //序号
unsigned short id; //标识符
}icmpheader;unsigned short checksum(unsigned short *buffer,int size)
{
unsigned long cksum=0;
while(size>0) //各位求和
{
cksum =*buffer;
size-=sizeof(unsigned short);
}
if(size)
cksum =*(unsigned char *)buffer;
cksum=(cksum>>16) (cksum & 0xffff);
cksum =(cksum>>16);
return (unsigned short)(~cksum); //再求补
}首先 , 我们更改QQ客户端里的服务器地址为127.0.0.1 , 端口改为QQicmp(l)的监听QQ客户端端口 , 当然你也可以保持默认的8000 ,
这样QQicmp(l)就应该在8000端口监听QQ客户端的数据 。

推荐阅读