ICMP報(bào)文的介紹和使用

ICMP協(xié)議是做什么的

ICMP是"Internet Control Message Protocol"(Internet控制消息協(xié)議)的縮寫。它是TCP/IP協(xié)議族的一個(gè)子協(xié)議,用于在IP主機(jī)、路由器之間傳遞控制消息。
控制消息是指網(wǎng)絡(luò)通不通、主機(jī)是否可達(dá)、路由是否可用等網(wǎng)絡(luò)本身的消息。這些控制消息雖然并不傳輸用戶數(shù)據(jù),但是對于用戶數(shù)據(jù)的傳遞起著重要的作用。
ICMP協(xié)議是一種面向無連接的協(xié)議,用于傳輸出錯(cuò)報(bào)告控制信息。它是一個(gè)非常重要的協(xié)議,它對于網(wǎng)絡(luò)安全具有極其重要的意義。
主要作用:主機(jī)探測、路由維護(hù)、路由選擇、流量控制。我們常用的ping命令和traceroute命令都是通過ICMP協(xié)議來實(shí)現(xiàn)的。

ICMP使用的是什么端口(一個(gè)面試陷阱)?

Linux下端口的劃分和使用是由IANA(Internet Assigned Numbers Authority,因特網(wǎng)已分配數(shù)值權(quán)威機(jī)構(gòu))維護(hù)的,端口號(hào)被劃分為3個(gè)段:
0~1023,這些端口由IANA分配和控制,可能的話,相同端口號(hào)就分配給TCP、UDP和SCTP的同一給定服務(wù)。如80端口被賦予web服務(wù)
102449151,這些端口不受IANA控制,不過由IANA登記并提供他們的使用情況清單,已方便整個(gè)群體。相同端口號(hào)也分配給TCP和UDP的同一給定服務(wù)。如60006003端口分配給這兩種協(xié)議的X Window服務(wù)器。
49152~65535,動(dòng)態(tài)端口。IANA不管這些端口,就是我們所說的臨時(shí)端口。(49152這個(gè)魔數(shù)是65536的四分之三)。
IANA端口號(hào)查詢地址如下:
http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml

常用端口號(hào):

服務(wù)名 端口號(hào)
FTP 21
SSH (Secure Shell) 22
TELNET 23
MAIL(smtp\pop3) 25\110
DNS 53
DHCP 67
HTTP 80
windows遠(yuǎn)程終端 3389
tomcat 8080
mysql 3306
ORACLE 1521、1526

ETH,IP,TCP層的報(bào)文格式

我們先來回顧一下ETH,IP,TCP層的報(bào)文格式
ETH層記錄了MAC地址,IP層記錄了IP地址,TCP層記錄了PORT。這樣TCP協(xié)議就可以通過Socket(IP:PORT)來識(shí)別對方了。

/*
 * 1. eth level[14Bytes]
 * EthHeader{dst:6, src:6, type:2}
 * EthData(RFC894)
 * ----------------------------------------------------------------------
 * | 6Bytes | 6Bytes | 2Bytes | 46~1500Bytes         | 4Bytes  |
 * ----------------------------------------------------------------------
 * | DstMac | SrcMac |  Type  | Data                 |   CRC   | : ETH
 *                   |  0806  | ARP(28)              | PAD(18) |
 *                   |  0835  | PARP(28)             | PAD(18) |
 *                   |  0800  | IP(4~1500)                     |
 *                            | IPHeader | IPData              | : IP
 *                                       | TCPHeader | TCPData | : TCP
 *                                                   | APPData | : APP
 *
 * 2. IP level[20Bytes]
 * IPPacket:{IPHeader(20) + TCPHeader(20+) + [TCPData]}
 * ====================================================
 * 0---------8---------15-------23--------31
 * | v_hl(1) | tos(1)  |       len(2)      |
 * |       id(2)       |      offset(2)    |
 * | ttl(1) | proto(1) |     checksum(2)   |
 * |                  src(4)               |
 * |                  dst(4)               |
 * $                  option               $
 * $                   data                $
 * ====================================================
 * IPHeader(20){v_hl:1, tos:1, len:2, id:2, offset:2, ttl:1, proto:1, checksum:2, src:4, dst:4}
 *
 * 3. TCP level[20+Bytes]
 * ====================================================
 * 0---------8---------15-------23--------31
 * |    src port(2)    |    dst port(2)    |
 * |                  seq(4)               |
 * |                  ack(4)               |
 * |hdlen(1) |flags(1) | window size(2)    |
 * |    checksum(2)    | urgent pointer(2) |
 * $                 option                $
 * $                  data                 $
 * TCPHeader{srcport:2, dstport:2, seq:4, ack:4, hdr_len:1, flags:1, winsize:2, checksum:2, urgent:2}
 */

ICMP報(bào)文格式

詳細(xì)信息:https://www.rfc-editor.org/info/rfc792

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             unused                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Internet Header + 64 bits of Original Data Datagram      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

struct icmphdr
{
  u_int8_t type;                /* message type */
  u_int8_t code;                /* type sub-code */
  u_int16_t checksum;
  union
  {
    struct
    {
      u_int16_t id;
      u_int16_t sequence;
    } echo;                     /* echo datagram */
    u_int32_t   gateway;        /* gateway address */
    struct
    {
      u_int16_t __unused;
      u_int16_t mtu;
    } frag;                     /* path mtu discovery */
  } un;
};

type:一個(gè) 8 位類型字段,表示 ICMP 數(shù)據(jù)包類型;
code:一個(gè) 8 位代碼域,表示指定類型中的一個(gè)功能,如果一個(gè)類型中只有一種功能,代碼域置為 0;
checksum:數(shù)據(jù)包中 ICMP 部分上的一個(gè) 16 位檢驗(yàn)和;
ICMP報(bào)文中沒有PORT,其是根據(jù)id+sequence來進(jìn)行目標(biāo)判斷的。

常見的ICMP報(bào)文類型

ICMP提供多種類型的消息為源端節(jié)點(diǎn)提供網(wǎng)絡(luò)層的故障信息反饋,它的報(bào)文類型可以歸納為以下5個(gè)大類:
診斷報(bào)文(類型8,代碼0;類型0,代碼0);
目的不可達(dá)報(bào)文(類型3,代碼0-15);
重定向報(bào)文(類型5,代碼0-4);
超時(shí)報(bào)文(類型11,代碼0-1);
信息報(bào)文(類型12-18)。

  1. 回音(Echo)屬于資訊信息。ping命令就是利用了該類型的ICMP包。當(dāng)使用ping命令的時(shí)候,將向目標(biāo)主機(jī)發(fā)送Echo-詢問類型的ICMP包,而目標(biāo)主機(jī)在接收到該ICMP包之后,會(huì)回復(fù)Echo-回答類型的ICMP包,并將詢問ICMP包包含在數(shù)據(jù)部分。ping命令是我們進(jìn)行網(wǎng)絡(luò)排查的一個(gè)重要工具。例如一個(gè)IP地址可以通過ping命令收到回復(fù),那么其他的網(wǎng)絡(luò)協(xié)議通信方式也很有可能成功。

  2. 源頭冷卻(source quench)屬于錯(cuò)誤消息。如果某個(gè)主機(jī)快速的向目的傳送數(shù)據(jù),而目的地主機(jī)沒有匹配的處理能力,目的主機(jī)可以向出發(fā)主機(jī)發(fā)出給類型的ICMP包,提醒出發(fā)主機(jī)放慢發(fā)送速度。

  3. 目的地?zé)o法到達(dá)(Destination Uncreachale)屬于錯(cuò)誤信息。如果一個(gè)路由器接收到一個(gè)沒辦法進(jìn)一步接力的IP包,它會(huì)想出發(fā)主機(jī)發(fā)送該類型的ICMP包。比如當(dāng)IP包到達(dá)最后一個(gè)路由器,路由器發(fā)現(xiàn)目的地主機(jī)down機(jī),就會(huì)向出發(fā)主機(jī)發(fā)送目的地?zé)o法到達(dá)(Destinaton Unreacherable)類型的ICMP包。目的地?zé)o法到達(dá)還有其他可能的原因,比如不存在接力路徑,比如不被接收的端口號(hào)等等。

  4. 超時(shí)(Time Exceded)屬于錯(cuò)誤信息。IPV4中的Time to Live(TTL)和IPV6中的Hop Limit會(huì)隨著經(jīng)過的路由器而遞減,當(dāng)這個(gè)區(qū)域值減為0時(shí),就認(rèn)為該IP包超時(shí)(Time Exceeded)。Time Exceeded就是TTL減為0時(shí)路由器發(fā)給出發(fā)地主機(jī)的ICMP包,通知它發(fā)生了超時(shí)錯(cuò)誤。 traceroute就利用了這種類型的ICMP包。traceroute命令用來發(fā)現(xiàn)IP接力路徑上的各個(gè)路由器。它向目的地發(fā)送IP包,第一次的時(shí)候,將TTL設(shè)為1,引發(fā)第一個(gè)路由器的Time Exceeded錯(cuò)誤。這樣,第一個(gè)路由器恢復(fù)ICMP包,從而讓出發(fā)主機(jī)知道途徑的第一個(gè)路由器的信息。隨后TTL被設(shè)置為2,,3,4。。。直到到達(dá)目的主機(jī)。這樣,沿途的每個(gè)路由器都會(huì)向出發(fā)主機(jī)發(fā)送ICMP包來匯報(bào)錯(cuò)誤。traceroute將ICMP包的信息打印在屏幕上,就是接力路徑的信息了。

  5. 重新定向(redirect)屬于錯(cuò)誤信息。當(dāng)一個(gè)路由器收到一個(gè)IP包,對照其routing table,發(fā)現(xiàn)自己不應(yīng)該受到該IP包,它會(huì)向出發(fā)主機(jī)發(fā)送重新定向類型的ICMP,提醒出發(fā)主機(jī)修改自己的routing table。比如下面的網(wǎng)絡(luò):

參見:https://www.cnblogs.com/jingmoxukong/p/3811262.html

這是一個(gè)完整的ICMP類型的列表:

TYPE CODE Description
0 0 Echo Reply--回顯應(yīng)答(Ping應(yīng)答)
3 0 Network Unreachable--網(wǎng)絡(luò)不可達(dá)
3 1 Host Unreachable--主機(jī)不可達(dá)
3 2 Protocol Unreachable--協(xié)議不可達(dá)
3 3 Port Unreachable--端口不可達(dá)
3 4 Fragmentation needed but no frag. bit set--需要進(jìn)行分片但設(shè)置不分片比特
3 5 Source routing failed--源站選路失敗
3 6 Destination network unknown--目的網(wǎng)絡(luò)未知
3 7 Destination host unknown--目的主機(jī)未知
3 8 Source host isolated (obsolete)--源主機(jī)被隔離(作廢不用)
3 9 Destination network administratively prohibited--目的網(wǎng)絡(luò)被強(qiáng)制禁止
3 10 Destination host administratively prohibited--目的主機(jī)被強(qiáng)制禁止
3 11 Network unreachable for TOS--由于服務(wù)類型TOS,網(wǎng)絡(luò)不可達(dá)
3 12 Host unreachable for TOS--由于服務(wù)類型TOS,主機(jī)不可達(dá)
3 13 Communication administratively prohibited by filtering--由于過濾,通信被強(qiáng)制禁止
3 14 Host precedence violation--主機(jī)越權(quán)
3 15 Precedence cutoff in effect--優(yōu)先中止生效
4 0 Source quench--源端被關(guān)閉(基本流控制)
5 0 Redirect for network--對網(wǎng)絡(luò)重定向
5 1 Redirect for host--對主機(jī)重定向
5 2 Redirect for TOS and network--對服務(wù)類型和網(wǎng)絡(luò)重定向
5 3 Redirect for TOS and host--對服務(wù)類型和主機(jī)重定向
8 0 Echo request--回顯請求(Ping請求)
9 0 Router advertisement--路由器通告
10 0 Route solicitation--路由器請求
11 0 TTL equals 0 during transit--傳輸期間生存時(shí)間為0
11 1 TTL equals 0 during reassembly--在數(shù)據(jù)報(bào)組裝期間生存時(shí)間為0
12 0 IP header bad (catchall error)--壞的IP首部(包括各種差錯(cuò))
12 1 Required options missing--缺少必需的選項(xiàng)
13 0 Timestamp request (obsolete)--時(shí)間戳請求(作廢不用)
14 0 Timestamp reply (obsolete)--時(shí)間戳應(yīng)答(作廢不用)
15 0 Information request (obsolete)--信息請求(作廢不用)
16 0 Information reply (obsolete)--信息應(yīng)答(作廢不用)
17 0 Address mask request--地址掩碼請求
18 0 Address mask reply--地址掩碼應(yīng)答

如何判斷目標(biāo)主機(jī)是否可達(dá)

源主機(jī)向目標(biāo)主機(jī)發(fā)送ICMP回顯請求數(shù)據(jù)包,然后等待目標(biāo)主機(jī)的回答。
目標(biāo)主機(jī)在收到一個(gè)ICMP回顯請求數(shù)據(jù)包后,它會(huì)交換源、目的主機(jī)的地址,然后將收到的ICMP回顯請求數(shù)據(jù)包中的數(shù)據(jù)部分原封不動(dòng)地封裝在自己的ICMP回顯應(yīng)答數(shù)據(jù)包中,然后發(fā)回給發(fā)送ICMP回顯請求的一方。
源主機(jī)收到回顯應(yīng)答報(bào)文核對id和seq后,便認(rèn)為目標(biāo)主機(jī)的回顯服務(wù)正常,也即物理連接暢通。
簡單來說:向目標(biāo)主機(jī)發(fā)送ECHO報(bào)文,接收ECHO_REPLY報(bào)文,則認(rèn)為目標(biāo)主機(jī)可達(dá)。

需要注意

ICMP協(xié)議是IP協(xié)議的排錯(cuò)助手,它可以幫助人們及時(shí)發(fā)現(xiàn)IP通信中出現(xiàn)的故障?;贗CMP的ping和traceroute也構(gòu)成了重要的網(wǎng)絡(luò)診斷工具。
然而需要注意的是,盡管ICMP的設(shè)計(jì)是出于好的意圖,但I(xiàn)CMP卻經(jīng)常被黑客借用進(jìn)行網(wǎng)絡(luò)攻擊,比如利用偽造的IP包引發(fā)大量的ICMP回復(fù),并將這些ICMP包導(dǎo)向受害主機(jī),從而形成DoS攻擊。
而redirect類型的ICMP包可以引起某個(gè)主機(jī)更改自己的routing table,所以也被用做攻擊工具。許多站點(diǎn)選擇忽視某些類型的ICMP包來提供自身的安全性。

C語言使用ICMP報(bào)文實(shí)現(xiàn)ping命令

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/ip_icmp.h>

#define ICMP_PACKET_SIZE 16
#define TIMEOUT_SECONDS 2
uint16_t ident=0;

const char *ping_desc(uint8_t type, uint8_t code)
{
    switch(type)
    {
        case ICMP_ECHOREPLY:
            return "Echo Reply";
        case ICMP_ECHO:
            return "Echo Request";
        case ICMP_PARAMPROB:
            return "Bad Parameter";
        case ICMP_SOURCEQUENCH:
            return "Packet lost, slow down";
        case ICMP_TSTAMP:
            return "Timestamp Request";
        case ICMP_TSTAMPREPLY:
            return "Timestamp Reply";
        case ICMP_IREQ:
            return "Information Request";
        case ICMP_IREQREPLY:
            return "Information Reply";
        case ICMP_UNREACH:
            switch(code)
            {
                case ICMP_UNREACH_NET:
                    return "Unreachable Network";
                case ICMP_UNREACH_HOST:
                    return "Unreachable Host";
                case ICMP_UNREACH_PROTOCOL:
                    return "Unreachable Protocol";
                case ICMP_UNREACH_PORT:
                    return "Unreachable Port";
                case ICMP_UNREACH_NEEDFRAG:
                    return "Unreachable: Fragmentation needed";
                case ICMP_UNREACH_SRCFAIL:
                    return "Unreachable Source Route";
                case ICMP_UNREACH_NET_UNKNOWN:
                    return "Unknown Network";
                case ICMP_UNREACH_HOST_UNKNOWN:
                    return "Unknown Host";
                case ICMP_UNREACH_ISOLATED:
                    return "Unreachable: Isolated";
                case ICMP_UNREACH_NET_PROHIB:
                    return "Prohibited network";
                case ICMP_UNREACH_HOST_PROHIB:
                    return "Prohibited host";
                case ICMP_UNREACH_FILTER_PROHIB:
                    return "Unreachable: Prohibited filter";
                case ICMP_UNREACH_TOSNET:
                    return "Unreachable: Type of Service and Network";
                case ICMP_UNREACH_TOSHOST:
                    return "Unreachable: Type of Service and Host";
                case ICMP_UNREACH_HOST_PRECEDENCE:
                    return "Unreachable: Prec vio";
                case ICMP_UNREACH_PRECEDENCE_CUTOFF:
                    return "Unreachable: Prec cutoff";
                default:
                    return "Unreachable: Unknown Subtype";
            }
            break;
        case ICMP_REDIRECT:
            switch(code)
            {
                case ICMP_REDIRECT_NET:
                    return "Redirect: Network";
                case ICMP_REDIRECT_HOST:
                    return "Redirect: Host";
                case ICMP_REDIRECT_TOSNET:
                    return "Redirect: Type of Service and Network";
                case ICMP_REDIRECT_TOSHOST:
                    return "Redirect: Type of Service and Host";
                default:
                    return "Redirect: Unknown Subtype";
            }
        case ICMP_TIMXCEED:
            switch(code)
            {
                case ICMP_TIMXCEED_INTRANS:
                    return "Timeout: TTL";
                case ICMP_TIMXCEED_REASS:
                    return "Timeout: Fragmentation reassembly";
                default:
                    return "Timeout: Unknown Subtype";
            }
            break;
        default:
            return "Unknown type";
    }
}

uint16_t chksum(unsigned short *buf, int len)
{
    uint32_t sum = 0;

    while(len > 1) {
        sum += *buf;
        buf++;
        len -= 2;
    }
    if(len)
        sum += (*(uint8_t *)buf);

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum = (sum >> 16) + sum;

    return ~sum;
}

int ping_write(char *buf, int seq)
{
    struct timeval tv;
    struct icmp *icmp = (struct icmp *)buf;

    icmp->icmp_type = ICMP_ECHO;
    icmp->icmp_code = 0;
    icmp->icmp_id = ident;
    icmp->icmp_seq = seq;
    icmp->icmp_cksum = 0;

    gettimeofday(&tv, NULL);
    memcpy(buf + 8, &tv, sizeof(tv));

    icmp->icmp_cksum = chksum((unsigned short *)icmp, ICMP_PACKET_SIZE);

//    printf("send ICMP packet(type:%d, code:%d, id:%d, seq:%d, checksum:%d\n",
//           icmp->icmp_type, icmp->icmp_code, icmp->icmp_id, icmp->icmp_seq, icmp->icmp_cksum);
}

int ping_read(void *buf, struct sockaddr_in answer)
{
    uint16_t chk_sum;
    struct timeval tv_send, tv_now;
    unsigned int mini_sec;
    struct ip *ip = (struct ip *)buf;
    struct icmp *icmp = (struct icmp *)(buf + (ip->ip_hl << 2));

//    printf("recv ICMP packet(type:%d, code:%d, id:%d, seq:%d, checksum:%d\n",
//           icmp->icmp_type, icmp->icmp_code, icmp->icmp_id, icmp->icmp_seq, icmp->icmp_cksum);

    if(icmp->icmp_id != ident) {
//        printf("ERROR: bad icmp_id %d\n", icmp->icmp_id);
        return -1;
    }

    if(icmp->icmp_type != ICMP_ECHOREPLY) {
        printf("ERROR: %s\n", ping_desc(icmp->icmp_type, icmp->icmp_code));
        return -1;
    }

    chk_sum = icmp->icmp_cksum;
    icmp->icmp_cksum = 0;
    if(chk_sum != chksum((unsigned short *)icmp, ICMP_PACKET_SIZE)) {
        printf("ERROR: bad chksum\n");
        return -1;
    }

    gettimeofday(&tv_now, NULL);
    memcpy(&tv_send, ((char *)icmp + 8), sizeof(tv_send));
    mini_sec = (tv_now.tv_sec - tv_send.tv_sec) * 1000000 + (tv_now.tv_usec - tv_send.tv_usec);

    printf("%d bytes from %s: icmp_seq=%d, ttl=%d, time=%.3f ms\n",
           (ip->ip_hl << 2) + 16,
           inet_ntoa(answer.sin_addr),
           icmp->icmp_seq, ip->ip_ttl, mini_sec/1000.0);
    return 0;
}

int main(int argc, char *argv[])
{
    struct hostent *host;
    struct sockaddr_in dest;
    struct sockaddr_in answer;
    int  answer_len = sizeof(answer);
    int  sock_raw_fd, seq=0;
    char send_buf[ICMP_PACKET_SIZE];
    char recv_buf[50];

    if(argc != 2) {
        printf("Usage: %s ipaddr/hostname\n", argv[0]);
        exit(1);    
    }

    if ((host = gethostbyname(argv[1])) == NULL) {
        printf("ping: unknow host %s \n", argv[1]);
        exit(1);
    }

    ident = getpid() & 0xFFFF;
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    memcpy(&dest.sin_addr, host->h_addr, sizeof(int));
    dest.sin_port = ntohs(0);

    if ((sock_raw_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) {
        perror("socket");
        exit(1);
    }    

    while(seq < 5) {
        seq++;
//        printf("\nid:%d\n", seq);
        ping_write(send_buf, seq);
        if (sendto(sock_raw_fd, (const char*)send_buf, ICMP_PACKET_SIZE, 0, (struct sockaddr *)&dest, sizeof(dest)) == -1) {
            perror("sendto");
            exit(1);
        }

        while(1) {
            int ret = 0;
            struct timeval tv;
            fd_set readset;
            FD_ZERO(&readset);
            FD_SET(sock_raw_fd, &readset);

            tv.tv_sec = TIMEOUT_SECONDS;
            tv.tv_usec = 0;

            if ((ret = select(sock_raw_fd+1, &readset, NULL, NULL, &tv)) == -1) {
                perror("select");
                exit(1);
            } 
            if(ret == 0) {
                printf("time out.\n");
                break;
            } else {
                if(recvfrom(sock_raw_fd, recv_buf, 36, 0, (struct sockaddr *)&answer, &answer_len) == -1) {
                    perror("select");
                    exit(1);
                } else { 
                    if (ping_read(recv_buf, answer) == 0)
                        break;
                }
            }
        }
        sleep(1);
    }
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.這篇文章不是本人原創(chuàng)的,只是個(gè)人為了對這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,360評(píng)論 6 174
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,192評(píng)論 0 8
  • nmap使用指南(終極版) 原創(chuàng)2017-09-09hl0rey信安之路 一、目標(biāo)指定 1.CIDR標(biāo)志位 192...
    用電熱毯烤豬閱讀 12,151評(píng)論 1 49
  • 網(wǎng)絡(luò)層提供的兩種服務(wù) 在計(jì)算機(jī)網(wǎng)絡(luò)領(lǐng)域,網(wǎng)絡(luò)層應(yīng)該向運(yùn)輸層提供怎樣的服務(wù)(面向連接還是無連接)曾引起了長期的爭論,...
    srtianxia閱讀 4,232評(píng)論 0 12
  • 【瓜瓜,29-8-2017 小確幸】#逃跑#第三章講了威伯不小心跑出院子又被捉回來的故事。 無論是他拱開柵欄逃跑還...
    kaigua閱讀 162評(píng)論 0 0

友情鏈接更多精彩內(nèi)容