成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

網絡安全編程:原始套接字的使用

安全
本文通過介紹原始套接字實現經典的網絡命令,即Ping命令。通過完成一個Ping命令來初步了解和掌握原始套接字的使用。

 [[380854]]

使用TCP或UDP時,需要在調用socket()函數時為它的第2個參數指定相應的類型,比如SOCK_STREAM是代表要使用TCP,而SOCK_DGRAM表示要使用UDP協議。除了可以指定這兩種類型以外,還可以指定為原始套接字類型,即SOCK_RAW。當socket()函數的第2個參數指定為SOCK_STREAM或SOCK_DGRAM時,第3個參數可以缺省。而當socket()函數的第2個參數指定為SOCK_RAW時,第3個參數就必須明確指定需要使用的協議。

當套接字類型指定為SOCK_RAW時,協議類型的常用取值有IPPROTO_IP、IPPROTO_ICMP、IPPROTO_TCP、IPPROTO_UDP和IPPROTO_RAW。使用前四種類型,當發送數據時,系統會自動為數據加上IP首部并設置IP首部中的上層協議字段(如果有IP_HDRINCL選項,則系統不會自動添加IP首部);當接收數據時,系統不會將IP首部移除,需要程序自行處理。如果使用IPPROTO_RAW,那么系統將數據包直接送到網絡層發送數據,并且需要程序自己構造IP首部中的字段。

本文通過介紹原始套接字實現經典的網絡命令,即Ping命令。通過完成一個Ping命令來初步了解和掌握原始套接字的使用。

1. Ping命令的使用

Ping命令的目的是為了測試另一臺主機是否可達,Ping命令發送一份ICMP回顯請求報文給主機,并等待返回ICMP回顯應答。一般來說,如果不能Ping到某臺主機,那么就不能與該主機進行通信(例外的情況是對方主機的防火墻將進入主機的回顯請求報文屏蔽掉了,這種情況雖然Ping不通,但是仍然可以正常進行通信)。

Ping命令有很多參數,打開命令行直接輸入Ping后按下回車鍵,這樣就可以看到Ping命令的參數列表,如圖1所示。

圖1  Ping命令的參數列表

通常情況下,用戶都只是簡單Ping一下某個主機的地址。Ping命令的參數可以是主機名稱、域名和IP地址,后兩者是較為常用的。下面簡單演示一個Ping的例子,具體如下: 

  1. C:\>ping 8.8.4.4  
  2. Pinging 8.8.4.4 with 32 bytes of data:  
  3. Reply from 8.8.4.4: bytes=32 time=57ms TTL=47  
  4. Reply from 8.8.4.4: bytes=32 time=54ms TTL=47  
  5. Reply from 8.8.4.4: bytes=32 time=54ms TTL=47  
  6. Reply from 8.8.4.4: bytes=32 time=51ms TTL=47  
  7. Ping statistics for 8.8.4.4:  
  8.  Packets: Sent = 4Received = 4Lost = 0 (0% loss), 
  9. Approximate round trip times in milli-seconds:  
  10.  Minimum = 51msMaximum = 57msAverage = 54ms 

上面就是使用Ping命令對8.8.4.4這個IP進行回顯請求后的輸出信息。這里來解釋一下請求后的回顯信息的含義。

  1. Pinging 8.8.4.4 with 32 bytes of data: 

正在將32字節數據發送到遠程主機8.8.4.4,如果Ping的是一個域名或主機名的話,這里會將域名(主機名)轉換為IP地址顯示出來。 

  1. Reply from 8.8.4.4: bytes=32 time=57ms TTL=47 

本地主機已經收到回顯應答信息,bytes=32表示有32字節,time=57ms表示公用了57毫秒,TTL表示的是生存時間值,該值可以進行設置,該值最大為255。每個處理數據包的路由器都需要把TTL的值減1或減去數據包在路由器中停留的秒數。由于大多數路由器轉發數據包的延時都小于1秒,因此TTL最終成為一個跳站的計數器,所經過的每個路由器都將其值減1,當該值被減到0值時,該包將被丟棄。 

  1. Ping statistics for 8.8.4.4:  
  2.  Packets: Sent = 4Received = 4Lost = 0 (0% loss),  
  3. Approximate round trip times in milli-seconds:  
  4.  Minimum = 51msMaximum = 57msAverage = 54ms 

Ping 8.8.4.4的統計信息為:Sent=4表示發送了4個數據包,Received=4表示接收了4個數據包,Lost=0(0% loss)表示丟失的數據包是0個,丟包率為0%。

發送時間的大概情況:Mininum=51ms,最快是51ms,Maximum=57ms,最慢是57ms,Average=54ms,平均為54ms。

2. Ping命令的構造

Ping命令依賴的不是TCP,也不是UDP,它依賴的是ICMP。ICMP是IP層的協議之一,它傳遞差錯報文以及其他需要注意的信息。ICMP報文通常被IP層或高層協議使用。ICMP封裝在IP數據報內部,如圖2所示。

圖2  ICMP封裝在IP數據報內部

ICMP報文的格式如圖3所示。

圖3  ICMP報文格式

ICMP協議的類型碼與代碼根據不同的情況,各自取不同的值。Ping命令類型碼用到了2個值,分別是0和8。而代碼的取值都是0。當類型碼取值為0時,代碼的0值表示回顯應答;當類型碼取值為8時,代碼的0值表示請求回顯。Ping命令發送一個ICMP數據報時,類型碼為8,代碼為0,表示向對方主機進行請求回顯;當收到對方的ICMP數據報時,類型碼為0,代碼為0,表示收到了對方主機的回顯應答。簡單來說,Ping命令發出的數據中,類型是8,代碼是0,如果對方有回應,那么對方回應的數據中,類型是0,代碼是0。

在自己實現Ping命令時,就是去自己構造一個請求回顯的ICMP數據報,然后進行發送。ICMP的數據結構定義如下: 

  1. // ICMP 協議結構體定義  
  2. struct icmp_header  
  3.  
  4.   unsigned char icmp_type; // 消息類型  
  5.   unsigned char icmp_code; // 代碼  
  6.   unsigned short icmp_checksum; // 校驗和  
  7.   unsigned short icmp_id; // 用來唯一標識此請求的 ID 號,通常設置為進程 ID  
  8.   unsigned short icmp_sequence; // 序列號  
  9.   unsigned long icmp_timestamp; // 時間戳  
  10. }; 

ICMP的數據結構在網絡開發中會經常用到,可以將其保存以備后用。

明白了ICMP協議的數據結構,現在用抓包工具(也可以稱為協議分析工具)Wireshark來分析一下ICMP結構真實的情況,如圖4所示。

圖4  ICMP數據結構分析

在圖4中,標識1的部分是對協議進行過濾設置的,在該部分輸入“ICMP”可以讓Wireshark只顯示ICMP的數據記錄。相應地,可以輸入“TCP”、“UDP”、“HTTP”等協議進行篩選過濾。標識2的部分用于顯示篩選后的ICMP記錄,從這里可以明顯看出源IP地址、目的IP地址和協議的類型。標識3的部分用于顯示ICMP數據結構的值和附加的數據內容。最下面的部分顯示了數據的原始的二進制數據,在熟練掌握協議后,查看原始的二進制數據也并不是不可能的。

3. Ping命令的實現

有了前面的基礎,就可以構造自己的ICMP數據報來構造自己的Ping命令了。首先,定義兩個常量,還有計算校驗和的函數,具體如下: 

  1. struct icmp_header  
  2.  
  3.   unsigned char icmp_type; // 消息類型  
  4.   unsigned char icmp_code; // 代碼  
  5.   unsigned short icmp_checksum; // 校驗和  
  6.   unsigned short icmp_id; // 用來唯一標識此請求的 ID 號,通常設置為進程 ID  
  7.   unsigned short icmp_sequence; // 序列號  
  8.   unsigned long icmp_timestamp; // 時間戳 
  9. };  
  10. #define ICMP_HEADER_SIZE sizeof(icmp_header)  
  11. #define ICMP_ECHO_REQUEST 0x08  
  12. #define ICMP_ECHO_REPLY 0x00  
  13. // 計算校驗和  
  14. unsigned short chsum(struct icmp_header *picmp, int len)  
  15.  
  16.   long sum = 0 
  17.   unsigned short *pusicmp = (unsigned short *)picmp;  
  18.   while ( len > 1 )  
  19.   {  
  20.     sum += *(pusicmp++);  
  21.     if ( sum & 0x80000000 )  
  22.     {  
  23.       sum = (sum & 0xffff) + (sum >> 16);  
  24.     }  
  25.     len -2
  26.   }  
  27.   if ( len )  
  28.   {  
  29.     sum += (unsigned short)*(unsigned char *)pusicmp;  
  30.   }  
  31.   while ( sum >> 16 )  
  32.   {  
  33.     sum = (sum & 0xffff) + (sum >> 16);  
  34.   }  
  35.   return (unsigned short)~sum;  

ICMP的校驗值是一個16位的無符號整型,它會將ICMP協議頭不的數據進行累加,當累加有溢出的話,會將溢出的部分也進行累加。具體計算校驗和的算法就不過多介紹了,如果對校驗和計算的代碼不了解,可以進行單步調試來進行分析。再來看一下對于ICMP結構體的填充,具體代碼如下: 

  1. BOOL MyPing(char *szDestIp)  
  2.  
  3.   BOOL bRet = TRUE 
  4.   WSADATA wsaData;  
  5.   int nTimeOut = 1000 
  6.   char szBuff[ICMP_HEADER_SIZE + 32] = { 0 };  
  7.   icmp_header *pIcmp = (icmp_header *)szBuff;  
  8.   char icmp_data[32] = { 0 };  
  9.   WSAStartup(MAKEWORD(2, 2), &wsaData); 
  10.   // 創建原始套接字  
  11.   SOCKET s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)  
  12.   // 設置接收超時  
  13.   setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char const*)&nTimeOut, sizeof(nTimeOut));  
  14.   // 設置目的地址  
  15.   sockaddr_in dest_addr;  
  16.   dest_addr.sin_family = AF_INET 
  17.   dest_addr.sin_addr.S_un.S_addr = inet_addr(szDestIp);  
  18.   dest_addr.sin_port = htons(0);  
  19.   // 構造 ICMP 封包  
  20.   pIcmp->icmp_type = ICMP_ECHO_REQUEST 
  21.   pIcmp->icmp_code = 0 
  22.   pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();  
  23.   pIcmp->icmp_sequence = 0 
  24.   pIcmp->icmp_timestamp = 0 
  25.   pIcmp->icmp_checksum = 0 
  26.   // 拷貝數據  
  27.   // 這里的數據可以是任意的  
  28.   // 這里使用 abc 是為了和系統提供的看起來一樣  
  29.   memcpy((szBuff + ICMP_HEADER_SIZE), "abcdefghijklmnopqrstuvwabcdefghi", 32);  
  30.   // 計算校驗和  
  31.   pIcmp->icmp_checksum = chsum((struct icmp_header *)szBuff, sizeof(szBuff));  
  32.   sockaddr_in from_addr;  
  33.   char szRecvBuff[1024];  
  34.   int nLen = sizeof(from_addr);  
  35.   sendto(s, szBuff, sizeof(szBuff), 0, (SOCKADDR *)&dest_addr, sizeof(SOCKADDR));  
  36.   recvfrom(s, szRecvBuff, MAXBYTE, 0, (SOCKADDR *)&from_addr, &nLen);  
  37.   // 判斷接收到的是否是自己請求的地址  
  38.   if ( lstrcmp(inet_ntoa(from_addr.sin_addr), szDestIp) )  
  39.   {  
  40.     bRet = FALSE 
  41.   }  
  42.   else  
  43.   {  
  44.     struct icmp_header *pIcmp1 = (icmp_header *)(szRecvBuff + 20);  
  45.     printf("%s\r\n", inet_ntoa(from_addr.sin_addr));  
  46.   }  
  47.   return bRet;  

這就是Ping命令的全部代碼了。自己寫一個函數調用它進行測試。

在Windows XP以上的操作系統中運行時,比如Windows 8系統,程序可能會無法正常的運行,這是因為操作系統權限所導致的。在被編譯好的程序上單擊右鍵,在彈出的菜單上選擇“以管理員身份運行”,這樣程序就可以正常的執行了。 

 

責任編輯:龐桂玉 來源: 計算機與網絡安全
相關推薦

2015-03-31 11:24:02

2021-03-03 12:20:42

網絡安全DLL編程

2015-10-16 09:33:26

TCPIP網絡協議

2013-12-27 13:39:23

Java套接字

2021-01-26 13:45:03

網絡安全Winsock編程

2021-03-05 13:46:56

網絡安全遠程線程

2014-12-17 09:22:10

網絡·安全技術周刊

2015-05-28 10:47:38

Unix網絡編程TCP

2021-02-21 18:19:43

網絡安全網絡安全編程創建進程

2021-02-23 10:20:07

網絡安全進程代碼

2022-10-08 07:30:17

網絡安全編程語言C++

2016-10-10 00:18:27

2014-12-11 09:20:30

TCP

2012-01-06 13:58:47

JavaTCP

2009-03-10 13:59:41

C#套接字編程

2021-06-18 09:55:09

網絡安全目錄監控

2011-03-17 13:32:45

2021-03-01 11:38:15

網絡安全進程代碼

2021-06-11 13:40:17

網絡安全專殺工具病毒

2014-12-15 09:28:54

UDP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: aaa大片免费观看 | 四虎影音 | 精品美女久久久 | 日日干综合| 日韩欧美在线播放 | 亚洲人精品午夜 | 欧美日韩国产三级 | 99国内精品 | 色综合久久久久 | 一级在线毛片 | 激情a| 91麻豆蜜桃一区二区三区 | 国产一区二区三区高清 | 日韩欧美国产一区二区三区 | 成人午夜精品 | 欧美精品乱码99久久影院 | 国产97碰免费视频 | 不卡的av在线 | 欧美日韩一区二区三区四区 | 日韩一区二区三区在线视频 | 欧美6一10sex性hd | 羞羞色影院 | 国产成人福利在线 | 日韩欧美视频在线 | 午夜小视频免费观看 | 久久精品日产第一区二区三区 | 国产特一级黄色片 | 欧美日韩福利 | 中文视频在线 | 91久久精品国产91久久性色tv | 91社区在线观看 | 欧美一级片在线观看 | 日日干日日色 | 国产成人a亚洲精品 | 波多野结衣在线观看一区二区三区 | 免费黄色片在线观看 | 日本特黄a级高清免费大片 国产精品久久性 | 欧美另类视频在线 | 中文字幕日韩一区二区 | 日韩精品一区二区三区中文字幕 | 中文字幕亚洲精品在线观看 |