NS3网络仿真(14): TCP连接与端口扫描

快乐虾

http://blog.csdn.net/lights_joy/

欢迎转载,但请保留作者信息

本节学习一下使用NS3构造一个TCP包,再利用构造好的TCP包进行最简单的TCP端口扫描。

1.    TCP协议数据报头

下图中给出了TCP协议数据报头的格式。

源端口、目的端口:16位长。标识出远端和本地的端口号。

顺序号:32位长。表明了发送的数据报的顺序。

确认号:32位长。希望收到的下一个数据报的序列号。

TCP协议数据报头DE 头长:4位长。表明TCP头中包含多少个32位字。

接下来的6位未用。

ACK:ACK位置1表明确认号是合法的。如果ACK为0,那么数据报不包含确认信息,确认字段被省略。

PSH:表示是带有PUSH标志的数据。接收方因此请求数据报一到便可送往应用程序而不必等到缓冲区装满时才传送。

RST:用于复位由于主机崩溃或其它原因而出现的错误的连接。还可以用于拒绝非法的数据报或拒绝连接请求。

SYN:用于建立连接。

FIN:用于释放连接。

窗口大小:16位长。窗口大小字段表示在确认了字节之后还可以发送多少个字节。

校验和:16位长。是为了确保高可靠性而设置的。它校验头部、数据和伪TCP头部之和。

可选项:0个或多个32位字。包括最大TCP载荷,窗口比例、选择重发数据报等选项。

最大TCP载荷:允许每台主机设定其能够接受的最大的TCP载荷能力。在建立连接期间,双方均声明其最大载荷能力,并选取其中较小的作为标准。如果一台主机未使用该选项,那么其载荷能力缺省设置为536字节。

窗口比例:允许发送方和接收方商定一个合适的窗口比例因子。这一因子使滑动窗口最大能够达到232字节。

TCP协议数据报头选择重发数据报:这个选项允许接收方请求发送指定的一个或多个数据报。

2.    连接请求

当一个客户端向一个服务器发出连接请求时,它将首先发送一个SYN报文:

这是一个从192.168.24.1到192.168.24.129的FTP连接请求。对照上一节的包结构不难理解。下面我们用NS3构造一个这样的包。

首先我们构造一个TCP包头:

		ns3::Ptr<ns3::Packet> pkt = ns3::Create<ns3::Packet>();
		ns3::TcpHeader tcphdr;
		tcphdr.SetSourcePort(rand()%32768);
		tcphdr.SetDestinationPort(i);  // 任意填写
		tcphdr.EnableChecksums();
		tcphdr.SetFlags(ns3::TcpHeader::SYN);
		tcphdr.SetWindowSize(8192);
		tcphdr.SetSequenceNumber(ns3::SequenceNumber32(rand()));
		tcphdr.AppendOption(mss);
		tcphdr.AppendOption(ns3::TcpOption::CreateOption(ns3::TcpOption::NOP));
		tcphdr.AppendOption(ws);
		tcphdr.AppendOption(ns3::TcpOption::CreateOption(ns3::TcpOption::NOP));
		tcphdr.AppendOption(ns3::TcpOption::CreateOption(ns3::TcpOption::NOP));
这里的源端口随机选择了一个数,目标端口i是一个循环递增的数,也就是我们要扫描的目标端口,需要注意的是,在NS3中并不支持sack permit这一个选项,因此我们直接忽略了它。
接下来构造IP数据包的包头:
		// 添加IP头
		ns3::Ipv4Header iph;
		iph.SetDestination((const char*)dest_ip);
		iph.SetSource((const char*)src_ip);
		iph.SetIdentification(rand() % 65536);
		iph.SetTtl(64);
		iph.SetDontFragment();
		iph.SetProtocol(ns3::TcpL4Protocol::PROT_NUMBER);
		iph.EnableChecksum();
再接下来就是将TCP头加到空的数据包的前面:
		tcphdr.InitializeChecksum(iph.GetSource(), iph.GetDestination(), TcpL4Protocol::PROT_NUMBER);
		pkt->AddHeader(tcphdr);
这里有一点需要注意的是tcp头中的checksum计算需要包含源IP、目标IP和协议号。
再将ip报文的头加上:
		iph.SetPayloadSize(pkt->GetSize());
		pkt->AddHeader(iph);
最后加上以太网的帧头:
		// 添加以太网头
		ns3::EthernetHeader eeh;
		eeh.SetDestination((const char*)dest_mac);
		eeh.SetSource((const char*)src_mac);
		eeh.SetLengthType(ns3::Ipv4L3Protocol::PROT_NUMBER);
		pkt->AddHeader(eeh);

大功告成!

下面就是我们构造出来的SYN数据包:

对于每一个要扫描的端口,只需要构造一个SYN包,再将这些生成的包放到winpcap的发送队列里去,一次性送出。

然后就可以坐等服务端的响应了。

嗯,这个效率可比开一堆线程进行connect快多了~~~

1.1    连接响应

当一个端口允许连接时,服务端将响应SYN/ACK,就像这样的:

而当服务端拒绝连接时,它将回复RST包:

我们所需要做的就是判断一下回包的类型,确认此端口是否可以连接就OK了:

bool CNetHostPortScan::ProcessTcpPacket(ns3::EthernetHeader& eh, ns3::Ipv4Header& iph, ns3::TcpHeader& th, ns3::Ptr<ns3::Packet>& pkt)
{
	// 处理tcp包,返回true表示已经处理
	if ((th.GetFlags() & TcpHeader::SYN) && (th.GetFlags() & TcpHeader::ACK))
	{
	// 此端口可以响应tcp
......
	}
	return true;
}

再加上一点UI的显示,我们就得到了一个自己的端口扫描工具:

4.    结论

1、NS3对数据包的处理效率不高,因此导致了我们构造32768个包所用的时间比网络发包并等待回应的时间还长。

2、自己构造TCP包的扫描方式比用上层的connect方式速度要快得多,基本上2秒钟就把所有端口都扫出来了~~~

嗯,仿真用的NS3居然还有此妙用,哈哈......

努力学习中~~~~~~

??

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-17 21:19:56

NS3网络仿真(14): TCP连接与端口扫描的相关文章

NS3网络仿真(2):first.py

1    安装基本模块 11  安装Python 12  安装PTVS 13  添加对python-279的支持 2    在vs2013下编译NS3 3    编译NetAnim 4    在vs2013下使用ns 快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 学习一下ns中的第一个示例脚本,first.py,这个示例模拟一个Echo服务和客户端之间的通信. 1.1    导入所需要的库 ns3的每一个模块都有一个对应的用C++开发的dl

NS3网络仿真(7): Wifi节点

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在上一节中,我们仿真了一个总线型网络,这一节尝试将上一节中的n0变成一个无线的AP,再连上几个节点.这也是NS3中的示例third.cc干的事情,只是我们用Python实现. // Default Network Topology // // Wifi 10.1.3.0 // AP // * * * * // | | | | 10.1.1.0 // n5 n6 n7 n0 -----------

【网络协议】TCP连接的建立和释放

转载请注明出处:http://blog.csdn.net/ns_code/article/details/29382883 TCP首部格式 先看TCP报文段的格式,例如以下; TCP报文段首部的前20个字节是固定的,后面有4N字节是依据须要而添加的选项.因此TCP报文段的最小长度为20个字节. 首部固定部分的各字段的意义例如以下: 1.源port和目的port:加上IP首部的源IP地址和目的IP地址,确定唯一的一个TCP连接.另外通过目的port来决定TCP将数据报交付于那个应用程序,从而实现T

NS3网络仿真(8): 实时仿真

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 NS3支持实时仿真,且可以将NS3模拟生成的数据包通过主机上真实的网卡发送出去,本节尝试运行NS3中自带的fd-emu-ping示例,使用NS3模拟一台设备,再通过主机上的网口ping一台网络上的真实设备. // Allow ns-3 to ping a real host somewhere, using emulation mode // // +----------------------

NS3网络仿真(6): 总线型网络

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在NS3提供的第一个示例first.py中,模拟了一个点对点的网络,接下来的一个示例代码模拟了一个总线型网络及CSMA协议. # // Default Network Topology # // # // 10.1.1.0 # // n0 -------------- n1 n2 n3 n4 # // point-to-point | | | | # // ================ #

NS3网络仿真(12): ICMPv4协议

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 ICMP的全称是 Internet ControlMessage Protocol .其目的就是让我们能够检测网络的连通状况.ICMP主要是透过不同的类别(Type)与代码(Code) 让机器来识别不同的连接状况.本节利用NS3学习一下此协议. 1.1    报文格式 ICMP的报文格式如下: 即ICMP报文是IP报文的数据,而IPv4报文的格式如下: 在网上抓一个ping包来看看: 这是一个从

NS3网络仿真(13): FdNetDevice的问题

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在前面的小节中,我们使用FdNetDevice进行了实时仿真,利用NS3向一台实际的机器发送ping包,但得到的结果显然有点偏离我们的预期结果,因为ping包的响应时间明显长于正常情况下的响应时间. 这个是用NS3发送ping包的结果: 使用WireShark在NS3使用的适配器上抓包,这个是在物理网卡上抓到的包: 显然对端的响应是没有问题的,莫非问题出现在winpcap的发送上?刚好学习ICM

NS3网络仿真(9): 构建以太网帧

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在NS3使用了一个叫Packet的类来表示一个数据帧,本节尝试用它构造一个以太网帧. 以下是一个典型的ARP请求帧: 我们就用Packet来创建一个同样的帧. 首先创建一个空的数据包: Ptr<Packet>pkt = Create<Packet>(); 接下来加上ARP头: //加入arp头 ArpHeader ah; ah.SetRequest(Mac48Address(&qu

NS3网络仿真(3): NetAnim

快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 在NS3提供的示例first.py中,并没有生成NetAnim所需要的xml文件,本节我们尝试用NetAnim来展示first.py的仿真结果. 依照NetAnim的说明,在Run开始前加上一行: anim = ns.netanim.AnimationInterface('first.xml') ns.core.Simulator.Run() ns.core.Simulator.Destroy(