• 网络协议深度解析:SSL、 TLS、HTTP和 DNS(C/C++代码实现)


    在数字化时代,网络协议构成了互联网通信的基石。SSL、TLS、HTTP和DNS是其中最关键的几种,它们确保了我们的数据安全传输、网页的正确显示以及域名的正常解析。

    要理解这些协议,首先需要了解网络分层模型。SSL和TLS位于传输层之上,用于加密数据;HTTP是应用层协议,负责网页内容的传输;而DNS则在应用层与传输层之间,它将人类可读的域名转换为机器可读的IP地址。

    详细分析各个协议

    DNS(域名系统)的主要作用

    域名系统(DNS)是互联网的一项关键服务,它负责将用户可读的域名(如www.example.com)转换为网络设备可识别的IP地址(如192.0.2.1)。这个过程被称为域名解析。没有DNS,我们就需要记住复杂且难以记忆的数值序列来访问网站,这就大大降低了互联网的可用性。

    DNS查询过程

    当用户尝试访问一个网站时,以下是一个典型的DNS查询过程:

    1. 首先,用户的设备(比如电脑或手机)上的应用程序(通常是网页浏览器)会检查本地缓存,看看是否已经有对应域名的IP地址记录。如果有,它就直接使用该IP地址。

    2. 如果本地缓存中没有记录,设备会向配置的本地DNS服务器(通常由互联网服务提供商提供)发起解析请求。

    3. 本地DNS服务器收到请求后,会先检查自己的缓存。如果找到相应的记录,它会直接返回结果给请求者。

    4. 如果本地DNS服务器没有相关信息,它就会进行递归查询。在递归查询中,本地DNS服务器会代表请求者向其他DNS服务器发起查询请求,直到得到最终结果为止。

    5. 迭代查询则不同,它是一步接一步的过程,每一步只提供下一级查询的线索。在这种情况下,本地DNS服务器会告诉请求者下一个应该查询的DNS服务器的地址,请求者接着向这个新的地址发送请求,如此循环直至达到最终的权威名称服务器。

    6. 权威名称服务器负责管理特定域的DNS记录,它对所请求的域名拥有权威的信息。当查询到达这里,权威服务器会返回所请求的域名对应的IP地址记录。

    7. 一旦本地DNS服务器从权威名称服务器获取到所需的IP地址,它会将这个信息缓存起来以供后续使用,并将结果返回给原始请求者。

    8. 最后,原始请求者的设备收到解析出的IP地址,并使用该地址连接到目标网站。

    从上面信息了解到,DNS通过一种分布式数据库的方式工作,它将域名解析任务分散到全球众多的DNS服务器上。这些服务器相互协作,通过递归或迭代查询,最终将用户友好的域名转换为网络上的设备能够理解的IP地址。

    HTTP(超文本传输协议)的主要作用

    超文本传输协议(HTTP)是用于传输网页文档的核心技术,它基于请求/响应模型工作。HTTP允许客户端(通常是Web浏览器)向服务器发送请求,并接收包含网页内容的响应。这个协议是无状态的,意味着每次通信后不会留下记录,除非使用某些技术如Cookie或会话标识来维持状态。

    HTTP在应用层上运行,通常通过TCP/IP协议在网络中传输数据,但也可以在其他协议上运行,只要它们能提供类似可靠的流传输服务。

    HTTP请求/响应模型

    HTTP通信遵循一个非常直接的模型:一方(客户端)发送请求,另一方(服务器)返回响应。

    • 请求:由以下几部分组成:

      • 请求行:包含HTTP方法(如GET、POST)、请求的URL和HTTP协议版本。
      • 请求头:包含关于请求的附加信息,例如用户代理、接受的内容类型、语言等。
      • 空行:用以分隔请求头和请求体。
      • 请求体:对于一些请求方法(如POST、PUT),可能包含额外的数据。
    • 响应:同样由以下几部分组成:

      • 状态行:包含HTTP协议版本、状态码和状态消息。
      • 响应头:包含关于响应的附加信息,例如内容类型、内容长度、服务器信息等。
      • 空行:用以分隔响应头和响应体。
      • 响应体:实际返回给客户端的数据,比如HTML文档、图片或其他资源。

    HTTP方法和状态码

    • 方法

      • GET:请求指定资源的表示形式。使用查询字符串可包含额外信息。
      • POST:提交要处理的数据,比如表单内容。
      • PUT:上传指定的资源替换目标资源。
      • DELETE:删除指定的资源。
      • HEAD:请求资源的头部信息,不返回实体主体。
      • OPTIONS:描述目标资源的通信选项。
      • CONNECT:建立网络隧道,转换为代理服务器。
      • 还有其他不常用的方法,如TRACE、PATCH等。
    • 状态码

      • 1xx(信息):请求已接收,继续处理。
      • 2xx(成功):请求正常处理完毕。例如,200 OK 表示请求成功,204 No Content 表示请求成功但没有内容返回。
      • 3xx(重定向):需要进一步操作以完成请求。例如,301 Moved Permanently 表示资源永久移动到新位置,304 Not Modified 表示资源未修改,可以使用缓存的副本。
      • 4xx(客户端错误):请求有语法错误或请求无法实现。例如,400 Bad Request 表示服务器无法理解请求的语法,404 Not Found 表示找不到请求的资源。
      • 5xx(服务器错误):服务器在处理请求的过程中发生了错误。例如,500 Internal Server Error 表示服务器内部错误,503 Service Unavailable 表示服务器目前无法处理请求。

    总结来说,HTTP是Web通信的基础,它定义了客户端和服务器之间交换信息的格式和规则。了解HTTP的方法和状态码对于开发和维护网站和网络应用程序至关重要。

    SSL/TLS(安全套接字层/传输层安全)

    SSL和TLS用于加密客户端与服务器之间的通信,保障数据传输安全

    SSL(Secure Sockets Layer)和TLS(Transport Layer Security)是网络安全中非常重要的技术。它们通过综合运用对称加密、非对称加密、消息认证码等密码学技术,为互联网上的数据传输提供安全保障。具体来说,SSL和TLS的主要作用包括:

    • 加密数据:防止敏感信息如登录凭证、交易细节等在传输过程中被未授权的第三方窃取;
    • 数据完整性:确保数据在传输过程中没有被篡改;
    • 身份验证:验证通信双方的身份,保证用户正在与真正的服务器进行交流。

    SSL/TLS的握手过程涉及多个步骤,这个过程确定了加密参数,并在客户端与服务器之间建立了加密连接。具体如下:

    1. 客户端发起请求:客户端发送一个"client hello"消息到服务器,包含版本信息、加密套件列表、压缩算法和其他必要信息。此消息以明文形式发送。
    2. 服务器响应:服务器回应一个"server hello"消息,选择客户端提供的加密套件,并发送自己的数字证书及相关信息。
    3. 客户端验证:客户端接收服务器的证书,并对证书的有效性进行验证。如果需要,客户端也可能发送自己的证书给服务器进行双向验证。
    4. 密钥协商:双方根据协商的加密套件进行密钥交换。如果是使用RSA算法,服务器会用自己的私钥加密一个预备主秘钥,客户端用服务器的公钥解密得到主秘钥。
    5. 确立加密参数:使用从前面步骤得到的主秘钥,生成加密和MAC(消息认证码)密钥,这些密钥将用于后续的所有通信。
    6. 加密通信:双方确认无误后,开始使用协商好的加密参数进行加密通信。

    了解HTTPS(HTTP over SSL/TLS)的结合方式

    HTTPS,全称为HTTP Secure,也就是安全版的HTTP,它将HTTP协议与SSL/TLS协议结合起来,在互联网上提供加密的数据传输。具体结合方式如下:

    1. 应用层与传输层的安全封装:在标准的HTTP通信过程中,所有的数据传输都是明文形式的,这意味着数据可以被任何监听网络流量的人读取。而HTTPS通过在HTTP之上添加SSL/TLS协议,为数据提供了加密处理。这样即便是数据被截获,没有相应的密钥也无法解密数据内容。
    2. 保持HTTP的应用逻辑不变:在HTTPS的工作模式中,原有的HTTP请求和响应的处理逻辑并没有改变。只是在数据传输到TCP协议之前,先由SSL/TLS进行加密,确保了传输过程的安全性。这种分层的方法既保障了旧的HTTP应用无需修改即可升级到HTTPS,也符合了TCP/IP协议族的分层哲学。
    3. 使用安全的握手建立连接:当客户端与服务器进行HTTPS通信时,会首先建立一个SSL/TLS的握手,以确保双方的身份验证,并且确立加密参数和密钥。这个过程是整个加密通信的基础,并确保了后续所有传输的数据都能得到加密保护。
    4. 对外部资源的处理:现代网页通常包含多个外部资源,如图片、CSS和JavaScript文件等。在使用HTTPS时,即使是这些外部资源,浏览器也会分别建立安全的连接来获取它们,从而确保整个页面加载过程的数据安全。

    所以,HTTPS的核心在于它在HTTP上增加了一层SSL/TLS协议,以实现数据的加密传输。这种机制不仅提高了数据传输的安全性,而且在很大程度上继承了原有HTTP协议的应用模型,使得从HTTP迁移到HTTPS的过程对于开发者和用户来说相对平滑。

    网络协议深度解析:SSL、 TLS、HTTP和 DNS(C/C++代码实现)

    #define PKT_PARSE_OK 0
    #define PKT_PARSE_ERR -1
    
    #define PKT_IPPROTO_ICMP                1       //ICMP
    #define PKT_IPPROTO_TCP			  	    6		//TCP
    #define PKT_IPPROTO_UDP					17		//UDP
    
    #pragma pack(1)
    
    typedef struct  {
    	uint8_t		dest[6];
    	uint8_t		src[6];
    	uint16_t	type;
    }PKT_ETH_HEADER_S;
    
    ///* IPv4 header */
    typedef struct 
    {
        uint8_t	ver_ihl;			/*Version (4 bits) + Internet header length (4 bits)*/
        uint8_t	tos;				/*Type of service*/
    	uint16_t  tlen;				/*Total length*/ 
        uint16_t  identification;	/*Identification*/
        uint16_t  flags_fo;			/*Flags (3 bits) + Fragment offset (13 bits)*/
        uint8_t	ttl;				/*Time to live*/
        uint8_t	proto;				/*Protocol*/
        uint16_t  crc;				/*Header checksum*/
        uint32_t	saddr;			/*Source address*/
        uint32_t	daddr;			/*Destination address*/
        //uint32_t	op_pad;			/*Option + Padding*/
    } PKT_IP_HEADER_S;
    //
    ///* UDP header*/
    typedef struct 
    {
        uint16_t sport;				/*Source port*/
        uint16_t dport;				/*Destination port*/
        uint16_t len;					/*Datagram length*/
        uint16_t crc;					/*Checksum*/
    } PKT_UDP_HEADER_S;
    //
    ///* TCP header*/
    typedef struct 
    {
        uint16_t 	sport;				/*Source port*/
        uint16_t 	dport;				/*Destination port*/
        uint32_t	seq;				/*Sn number*/
        uint32_t	ack;				/*Ack number*/
        uint16_t	flags;
        uint16_t	win;				/*Window size*/
        uint16_t	sum;				/*Checksum*/
        uint16_t	urp;				/*Urgent pointer*/
    } PKT_TCP_HEADER_S;
    
    typedef struct 
    {
        uint32_t          linkid;
        uint32_t          seq; //seq
        uint32_t		  ack;//ack
        uint32_t		  exp;//expire next seq
    	uint16_t	      flags;
    	uint16_t	      win;//Window size
    	uint16_t	      crc;//Checksum
    	uint16_t	      urp;//Urgent pointer
    }PKT_TCP_S;
    
    typedef struct 
    {
        uint32_t      linkid;
    	uint16_t      crc;	//Checksum
        uint32_t		len;    //udp len with head
        uint8_t*      data;
    }PKT_UDP_S;
    
    typedef union  
    {
        PKT_TCP_S tcp;
        PKT_UDP_S udp;
    }PKT_TRANS_LAYER_U;
    
    typedef struct 
    {
        uint32_t sip;       //源ip
        uint32_t dip;       //目的ip
        uint16_t sport;     //源port
        uint16_t dport;     //目的port
        uint8_t  proto;       //传输层协议PKT_IPPROTO_TCP,PKT_IPPROTO_UDP
        uint8_t *peth_pkt;      // 报文指针
        uint8_t *pnet_pkt;      //网络层指针,网络层起始
        uint8_t *ptrans_pkt;    //传输层指针,传输层起始
        uint8_t *papp_pkt;      //数据层指针,数据层起始
        uint8_t *pmpls_pkt;
    	uint8_t *l2;
    	uint8_t *l3;
    	uint8_t *l4;
        uint16_t pkt_len;      //整个报文长度
        uint16_t ethh_len;      //2-2.5层头长度
        uint16_t net_len;      //ip数据长度,网络层+传输层+应用层
        uint16_t trans_len;    //传输层数据长度,传输层+应用层
        uint16_t app_len;      //应用层数据长度
        uint16_t mpls_len;      //应用层数据长度
        uint16_t eth_pack_num;   //2.5层封装层数
        uint8_t  vlan_flag;
    	uint8_t  ipfrag_flag;  //ip分片标记,1分片
    	uint8_t  mpls_flag;  
    	uint8_t  ipv4_flag;
    	uint8_t  ipv6_flag;
    	uint8_t  icmp_flag;
    	uint16_t app_proto; //应用层协议类型
        PKT_TRANS_LAYER_U trans_info; //tcp,udp信息 
    }PKT_INFO_S;
    #pragma pack()
    
    #define IP_SIP(p)		ntohl(((PKT_IP_HEADER_S *)(p))->saddr)			/*源IP*/
    #define IP_DIP(p)		ntohl(((PKT_IP_HEADER_S *)(p))->daddr)			/*目的IP*/
    #define IP_HLEN(p)		((((PKT_IP_HEADER_S *)(p))->ver_ihl & 0x0F) << 2)	/*IP头长度*/
    #define IP_PLEN(p)		ntohs(((PKT_IP_HEADER_S *)(p))->tlen)				/*IP包长度*/
    #define IP_IDEN(p)      ntohs(((PKT_IP_HEADER_S *)(p))->identification)   /*IP包标识*/
    #define IP_OFF(p)		((ntohs(((PKT_IP_HEADER_S *)(p))->flags_fo)&0x1FFF)<<3) 
    #define IP_MF(p)		((((PKT_IP_HEADER_S *)(p))->flags_fo&0x20)>>5)		
    #define UDP_SPORT(p)    ntohs(((PKT_UDP_HEADER_S *)(p))->sport)			/*Upd包源端口*/
    #define UDP_DPORT(p)	ntohs(((PKT_UDP_HEADER_S *)(p))->dport)			/*Udp包目的端口*/
    #define UDP_PLEN(p)		ntohs(((PKT_UDP_HEADER_S *)(p))->len)				/*Udp包的长度*/
    #define UDP_HLEN        (uint16_t)8
    #define TCP_SN(p)		ntohl(((PKT_TCP_HEADER_S*)(p))->seq)
    #define TCP_ACK(p)		ntohl(((PKT_TCP_HEADER_S*)(p))->ack)
    #define TCP_HLEN(p)		((((PKT_TCP_HEADER_S*)(p))->flags&0x00F0)>>2)
    #define TCP_SPORT(p)	ntohs(((PKT_TCP_HEADER_S *)(p))->sport)			/*Tcp包源端口*/
    #define TCP_DPORT(p)    ntohs(((PKT_TCP_HEADER_S *)(p))->dport)			/*Tcp包目的端口*/
    #define TCP_WIN(p)      ntohs(((PKT_TCP_HEADER_S *)(p))->win)
    #define TCP_SYN(p)		(((PKT_TCP_HEADER_S*)(p))->flags&0x0200)
    #define TCP_FIN(p)		(((PKT_TCP_HEADER_S*)(p))->flags&0x0100)
    #define TCP_RST(p)		(((PKT_TCP_HEADER_S*)(p))->flags&0x0400)
    #define TCP_ACKF(p)      (((PKT_TCP_HEADER_S*)(p))->flags&0x1000)
    
    struct http_header {
        char *name, *value;
    };
    
    struct http_message {
        char type;
    
        char *method, *url;
        char *protocol;
        char *status, *line;
    
        #define HTTP_HEADER_MAX 16
        struct http_header headers[HTTP_HEADER_MAX];
    
        char *body;
    
        char connection_close;
        char connection_keepalive;
        char gzip_supported;
    };
    
    typedef enum {
        DNS_UDP = 0,
        DNS_TCP,
    }DNS_TRANS_TYPE;
    
    typedef struct {
        DNS_TRANS_TYPE trans_type;
        int requestID;//请求标识
    	int requestFlag;//请求标志
    	char*  dns_queries_data;
        unsigned short dns_queries_len;
    	char  DNSname[DNS_DATA_LENGTH+1];//DNS名称
    	unsigned short requestType;//查询类型	
    	unsigned short  requestClass;//查询类
    }DNS_REQUEST_INFO;    
    
    ...
    
    void CallBackPacket(char *data, int len)
    {
    ...
    
        if (pkt_info.proto == PKT_IPPROTO_TCP && pkt_info.dport == 443)
        {
            //printf("-------------Https Packet Start------------- \n");
    
            char servername[128] = {0};
            int namelen = 0;
            err = ssl_clienthello_parser_servername(pkt_info.papp_pkt, pkt_info.app_len, servername, &namelen);
            if (err != 0)
            {
                //printf("    Not Find ServerName.\n");
            }
            else
            {
                if (namelen >= 128)
                    return;
    
                servername[namelen] = 0;
                printf("[HTTPS] Find ServerName: %s, Sip:%d.%d.%d.%d Dip:%d.%d.%d.%d Sport:%d Dport:%d \n", servername,
                    pkt_info.sip >> 24 & 0xff, pkt_info.sip >> 16 & 0xff, pkt_info.sip >> 8 & 0xff, pkt_info.sip & 0xff,
                    pkt_info.dip>> 24 & 0xff, pkt_info.dip >> 16 & 0xff, pkt_info.dip >> 8 & 0xff, pkt_info.dip & 0xff,
                    pkt_info.sport, pkt_info.dport);
            }
            
            //printf("-------------Https Packet E n d------------- \n");
        }
        else if (pkt_info.proto == PKT_IPPROTO_UDP && pkt_info.dport == 53)
        {
            DNS_REQUEST_INFO dns_req = {0};
            err = dns_parse(pkt_info.papp_pkt, pkt_info.app_len, &dns_req);
            if (err == 0)
            {
                printf("[DNS] DNS ServerName: %s, Sip:%d.%d.%d.%d Dip:%d.%d.%d.%d Sport:%d Dport:%d \n", dns_req.DNSname,
                    pkt_info.sip >> 24 & 0xff, pkt_info.sip >> 16 & 0xff, pkt_info.sip >> 8 & 0xff, pkt_info.sip & 0xff,
                    pkt_info.dip>> 24 & 0xff, pkt_info.dip >> 16 & 0xff, pkt_info.dip >> 8 & 0xff, pkt_info.dip & 0xff,
                    pkt_info.sport, pkt_info.dport);
            }
           
        }
        else if (pkt_info.proto == PKT_IPPROTO_TCP && pkt_info.dport == 80)
        {
            struct http_message http_msg = {0};
            err = http_parser(pkt_info.papp_pkt, &http_msg, HTTP_REQUEST);
            if (err == 0)
            {
                int i = 0;
                char host[256] = {0};
                for (; i < 16; i++)
                {
                    if (http_msg.headers[i].name)
                    {
                        if (strncmp(http_msg.headers[i].name, "Host", 4) == 0)
                        {
                            strcpy(host, http_msg.headers[i].value);
                            int len = strlen(host);
                            if (host[len-1] == '\r')
                                host[len-1] = 0;
                            break;
                        }
                    }
                }
    
                printf("[HTTP] Method:%s Host:%s URL: %s, Sip:%d.%d.%d.%d Dip:%d.%d.%d.%d Sport:%d Dport:%d \n", 
                    http_msg.method,
                    host,
                    http_msg.url,
                    pkt_info.sip >> 24 & 0xff, pkt_info.sip >> 16 & 0xff, pkt_info.sip >> 8 & 0xff, pkt_info.sip & 0xff,
                    pkt_info.dip>> 24 & 0xff, pkt_info.dip >> 16 & 0xff, pkt_info.dip >> 8 & 0xff, pkt_info.dip & 0xff,
                    pkt_info.sport, pkt_info.dport);            
            }
        }
    ...
        return;
    }
    ...
    int main(int argc, char *argv[])
    {
    ...
    
        fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if(fd<0)
        {
            printf("socket create err %d. \n", fd);
            goto failed_2;
        }
    
    //PACKET_VERSION和 SO_BINDTODEVICE可以省略
    #if 1
        const int tpacket_version = TPACKET_V1;
        /* set tpacket hdr version. */
        ret = setsockopt(fd, SOL_PACKET, PACKET_VERSION, &tpacket_version, sizeof (int));
        if(ret<0)
        {
            printf("setsockopt packet version err %d. \n", ret);
            goto failed_2;
        }
    
        /* bind to device. */
        ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intfName, strlen(intfName));
        if(ret<0)
        {
            printf("setsockopt bind device error %d . \n", ret);
            goto failed_2;
        }
    #endif
    
        struct tpacket_req req;
    #define PER_PACKET_SIZE 2048
        const int BUFFER_SIZE = 1024*1024*16; //16MB的缓冲区
        req.tp_block_size = 4096;
        req.tp_block_nr = BUFFER_SIZE/req.tp_block_size;
        req.tp_frame_size = PER_PACKET_SIZE;
        req.tp_frame_nr = BUFFER_SIZE/req.tp_frame_size;
    
        ret = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *)&req, sizeof(req));
        if(ret<0)
        {
            printf("setsockopt rx ring error %d . \n", ret);
            goto failed_2;
        }
    
        buff = (char *)mmap(0, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if(buff == MAP_FAILED)
        {
            printf("mmap err. \n");
            goto failed_2;
        }
    
        int nIndex=0, i=0;
        while(1)
        {
            //这里在poll前先检查是否已经有报文被捕获了
            struct tpacket_hdr* pHead = (struct tpacket_hdr*)(buff+ nIndex*PER_PACKET_SIZE);
            //如果frame的状态已经为TP_STATUS_USER了,说明已经在poll前已经有一个数据包被捕获了,如果poll后不再有数据包被捕获,那么这个报文不会被处理,这就是所谓的竞争情况。
            if(pHead->tp_status == TP_STATUS_USER)
                goto process_packet;
    
            //poll检测报文捕获
            struct pollfd pfd;
            pfd.fd = fd;
            //pfd.events = POLLIN|POLLRDNORM|POLLERR;
            pfd.events = POLLIN;
            pfd.revents = 0;
            ret = poll(&pfd, 1, -1);
            if(ret<0)
            {
                perror("poll");
                goto failed_1;
            }
    
    process_packet:
            //尽力的去处理环形缓冲区中的数据frame,直到没有数据frame了
            for(i=0; i<req.tp_frame_nr; i++)
            {
                struct tpacket_hdr* pHead = (struct tpacket_hdr*)(buff+ nIndex*PER_PACKET_SIZE);
    
                //XXX: 由于frame都在一个环形缓冲区中,因此如果下一个frame中没有数据了,后面的frame也就没有frame了
                if(pHead->tp_status == TP_STATUS_KERNEL)
                    break;
    
                //处理数据frame
                CallBackPacket((char*)pHead+pHead->tp_mac, pHead->tp_len);
                //char* mac = (char*)pHead+pHead->tp_mac;
                //printf("GetPacket,Len:%d,Mac:%2x-%2x-%2x-%2x-%2x-%2x\n", pHead->tp_len,
                //    mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
    
                //重新设置frame的状态为TP_STATUS_KERNEL
                pHead->tp_len = 0;
                pHead->tp_status = TP_STATUS_KERNEL;
    
                //更新环形缓冲区的索引,指向下一个frame
                nIndex++;
                nIndex%=req.tp_frame_nr;
            }
    
        }
    ...
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355

    Makefile

    CC = gcc
    CFLAGS = -Wall -g
    LIBS = -lpthread
    
    all: main
    
    main: main.o dns_parser.o http_parser.o packet_handle.o pkt_parse.o ssl_parser.o
    	$(CC) $(CFLAGS) -o main main.o dns_parser.o http_parser.o packet_handle.o pkt_parse.o ssl_parser.o $(LIBS)
    
    main.o: main.c
    	$(CC) $(CFLAGS) -c main.c
    
    dns_parser.o: dns_parser.c
    	$(CC) $(CFLAGS) -c dns_parser.c
    
    http_parser.o: http_parser.c
    	$(CC) $(CFLAGS) -c http_parser.c
    
    packet_handle.o: packet_handle.c
    	$(CC) $(CFLAGS) -c packet_handle.c
    
    pkt_parse.o: pkt_parse.c
    	$(CC) $(CFLAGS) -c pkt_parse.c
    
    ssl_parser.o: ssl_parser.c
    	$(CC) $(CFLAGS) -c ssl_parser.c
    
    clean:
    	rm -f *.o main
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    运行结果:
    If you need the complete source code, please add the WeChat number (c17865354792)

    使用套接字接收网络数据包的示例。它创建了原始套接字,并将其绑定到指定的网络接口上。然后,它使用mmap()函数将一个环形缓冲区映射到内存中,以便存储捕获的数据包。接下来,它使用poll()函数检测是否有新的数据包到达,如果有,则处理这些数据包。在处理数据包时,它会调用CallBackPacket()函数处理数据包

    总结

    SSL(安全套接层)和TLS(传输层安全)是用于在互联网通信中提供安全和数据完整性的协议。它们位于传输层之上,确保数据在传输过程中被加密,以防止未经授权的访问和篡改。

    HTTP(超文本传输协议)是一种应用层协议,用于在互联网上传输网页和其他资源。它定义了客户端和服务器之间的通信规则,确保网页内容能够正确地传输和显示。

    DNS(域名系统)是一种将人类可读的域名转换为机器可读的IP地址的系统。它位于应用层和传输层之间,当用户在浏览器中输入一个域名时,DNS会将其解析为对应的IP地址,以便计算机能够找到并连接到目标服务器。

    We also undertake the development of program requirements here. If necessary, please follow the WeChat official account 【程序猿编码】and contact me

    参考:RFC 1035、RFC 2246、RFC 7235

  • 相关阅读:
    将 Apache Kafka SASL OUTHBEARER 与 Python 一起使用
    CTFHub-SSRF-读取伪协议
    Matlab optimtool优化阵列天线的幅相激励
    [附源码]java毕业设计学生宿舍管理系统
    Android ASM插桩探索及实战
    周末抽了一天时间开发了一款Storage加强插件
    Cesium从已知的自定义材质扩展其他效果(二)
    【元胞自动机】模拟电波在整个心脏中的传导和传播的时空动力学研究(Matlab代码实现)
    软考中级软件设计师--3.知识产权
    git:一些撤销操作
  • 原文地址:https://blog.csdn.net/chen1415886044/article/details/137334349