NS3網路模擬(14): TCP串連與連接埠掃描,ns3連接埠掃描
快樂蝦
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居然還有此妙用,哈哈......
努力學習中~~~~~~
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。