zoukankan      html  css  js  c++  java
  • 原始套接字概述

    大多数程序员所接触到的套接字(Socket)为两类:
    (1)流式套接字(SOCK_STREAM):一种面向连接的Socket,针对于面向连接的TCP服务应用;
    (2)数据报式套接字(SOCK_DGRAM):一种无连接的Socket,对应于无连接的UDP服务应用。
    从用户的角度来看,SOCK_STREAM、SOCK_DGRAM这两类套接字似乎的确涵盖了TCP/IP应用的全部,因为基于TCP/IP的应用,从协议栈的层次上讲,在传输层的确只可能建立于TCP或UDP协议之上(图1),而SOCK_STREAM、SOCK_DGRAM又分别对应于TCP和UDP,所以几乎所有的应用都可以用这两类套接字实现。

    但是,当我们面对如下问题时,SOCK_STREAM、SOCK_DGRAM将显得这样无助:
    (1) 怎样发送一个自定义的IP包?
    (2) 怎样发送一个ICMP协议包?
    (3) 怎样使本机进入杂糅模式,从而能够进行网络sniffer?
    (4) 怎样分析所有经过网络的包,而不管这样包是否是发给自己的?
    (5) 怎样伪装本地的IP地址?
    这使得我们必须面对另外一个深刻的主题――原始套接字(Raw Socket)。Raw Socket广泛应用于高级网络编程,也是一种广泛的黑客手段。著名的网络sniffer、拒绝服务攻击(DOS)、IP欺骗等都可以以Raw Socket实现。
    Raw Socket与标准套接字(SOCK_STREAM、SOCK_DGRAM)的区别在于前者直接置"根"于操作系统网络核心(Network Core),而SOCK_STREAM、SOCK_DGRAM则"悬浮"于TCP和UDP协议的外围,如图2所示:

    当我们使用Raw Socket的时候,可以完全自定义IP包,一切形式的包都可以"制造"出来。因此,本文事先必须对TCP/IP所涉及IP包结构进行必要的交待。
    目前,IPv4的报头结构为:

    版本号(4)
    包头长(4)
    服务类型(8)

    数据包长度(16)

    标识(16)

    偏移量(16)

    生存时间(8)

    传输协议(8)

    校验和(16)

    源地址(32)

    目的地址(32)

    选项(8)

    .........

    填充

    对其进行数据结构封装:

    typedef struct _iphdr //定义IP报头
    {
    unsigned char h_lenver; //4位首部长度+4位IP版本号
    unsigned char tos; //8位服务类型TOS
    unsigned short total_len; //16位总长度(字节)
    unsigned short ident; //16位标识
    unsigned short frag_and_flags; //3位标志位
    unsigned char ttl; //8位生存时间 TTL
    unsigned char proto; //8位协议 (TCP, UDP 或其他)
    unsigned short checksum; //16位IP首部校验和
    unsigned int sourceIP; //32位源IP地址
    unsigned int destIP; //32位目的IP地址
    } IP_HEADER;

    或者将上述定义中的第一字节按位拆分:

    typedef struct _iphdr //定义IP报头
    {
    unsigned char h_len : 4; //4位首部长度
    unsigned char ver : 4; //4位IP版本号
    unsigned char tos;
    unsigned short total_len;
    unsigned short ident;
    unsigned short frag_and_flags;
    unsigned char ttl;
    unsigned char proto;
    unsigned short checksum;
    unsigned int sourceIP;
    unsigned int destIP;
    } IP_HEADER;

    更加严格地讲,上述定义中h_len、ver字段的内存存放顺序还与具体CPU的Endian有关,因此,更加严格的IP_HEADER可定义为:

    typedef struct _iphdr //定义IP报头
    {
    #if defined(__LITTLE_ENDIAN_BITFIELD)
    unsigned char h_len : 4; //4位首部长度
    unsigned char ver : 4; //4位IP版本号
    #elif defined (__BIG_ENDIAN_BITFIELD)
    unsigned char ver : 4; //4位IP版本号
    unsigned char h_len : 4; //4位首部长度
    #endif
    unsigned char tos;
    unsigned short total_len;
    unsigned short ident;
    unsigned short frag_and_flags;
    unsigned char ttl;
    unsigned char proto;
    unsigned short checksum;
    unsigned int sourceIP;
    unsigned int destIP;
    } IP_HEADER;

    TCP报头结构为:

    源端口(16)

    目的端口(16)

    序列号(32)

    确认号(32)

    TCP偏移量(4)

    保留(6)

    标志(6)

    窗口(16)

    校验和(16)

    紧急(16)

    选项(0或32)

    数据(可变)

    对应数据结构:

    typedef struct psd_hdr //定义TCP伪报头
    {
    unsigned long saddr; //源地址
    unsigned long daddr; //目的地址
    char mbz;
    char ptcl; //协议类型
    unsigned short tcpl; //TCP长度
    }PSD_HEADER;
    typedef struct _tcphdr //定义TCP报头
    {
    unsigned short th_sport; //16位源端口
    unsigned short th_dport; //16位目的端口
    unsigned int th_seq; //32位序列号
    unsigned int th_ack; //32位确认号
    unsigned char th_lenres; //4位首部长度/4位保留字
    unsigned char th_flag; //6位标志位
    unsigned short th_win; //16位窗口大小
    unsigned short th_sum; //16位校验和
    unsigned short th_urp; //16位紧急数据偏移量
    } TCP_HEADER;

    同样地,TCP头的定义也可以将位域拆分:

    typedef struct _tcphdr
    {
    unsigned short th_sport;
    unsigned short th_dport;
    unsigned int th_seq;
    unsigned int th_ack;
    /*little-endian*/
    unsigned short tcp_res1: 4, tcp_hlen: 4, tcp_fin: 1, tcp_syn: 1, tcp_rst: 1, tcp_psh: 1, tcp_ack: 1, tcp_urg: 1, tcp_res2: 2;
    unsigned short th_win;
    unsigned short th_sum;
    unsigned short th_urp;
    } TCP_HEADER;

    UDP报头为:

    源端口(16)

    目的端口(16)

    报文长(16)

    校验和(16)

    对应的数据结构为:

    typedef struct _udphdr //定义UDP报头
    {
    unsigned short uh_sport;//16位源端口
    unsigned short uh_dport;//16位目的端口
    unsigned short uh_len;//16位长度
    unsigned short uh_sum;//16位校验和
    } UDP_HEADER;

    ICMP协议是网络层中一个非常重要的协议,其全称为Internet Control Message Protocol(因特网控制报文协议),ICMP协议弥补了IP的缺限,它使用IP协议进行信息传递,向数据包中的源端节点提供发生在网络层的错误信息反馈。ICMP报头为:

    类型(8)

    代码(8)

    校验和(16)

    消息内容

    常用的回送与或回送响应ICMP消息对应数据结构为:

    typedef struct _icmphdr //定义ICMP报头(回送与或回送响应)
    {
    unsigned char i_type;//8位类型
    unsigned char i_code; //8位代码
    unsigned short i_cksum; //16位校验和
    unsigned short i_id; //识别号(一般用进程号作为识别号)
    unsigned short i_seq; //报文序列号
    unsigned int timestamp;//时间戳
    } ICMP_HEADER;

    常用的ICMP报文包括ECHO-REQUEST(响应请求消息)、ECHO-REPLY(响应应答消息)、Destination Unreachable(目标不可到达消息)、Time Exceeded(超时消息)、Parameter Problems(参数错误消息)、Source Quenchs(源抑制消息)、Redirects(重定向消息)、Timestamps(时间戳消息)、Timestamp Replies(时间戳响应消息)、Address Masks(地址掩码请求消息)、Address Mask Replies(地址掩码响应消息)等,是Internet上十分重要的消息。后面章节中所涉及到的ping命令、ICMP拒绝服务攻击、路由欺骗都与ICMP协议息息相关。
    另外,本系列文章中的部分源代码参考了一些优秀程序员的开源项目,由于篇幅的关系我们不能一一列举,在此一并表示感谢。

  • 相关阅读:
    解析大型.NET ERP系统 权限模块设计与实现
    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
    解析大型.NET ERP系统 单据编码功能实现
    解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
    Windows 10 部署Enterprise Solution 5.5
    解析大型.NET ERP系统 设计异常处理模块
    解析大型.NET ERP系统 业务逻辑设计与实现
    解析大型.NET ERP系统 多国语言实现
    Enterprise Solution 管理软件开发框架流程实战
    解析大型.NET ERP系统 数据审计功能
  • 原文地址:https://www.cnblogs.com/hackpig/p/1668278.html
Copyright © 2011-2022 走看看