C语言实现手动封装数据包发送并解析

本文章的学习旨在完成手动封装以太网头部,外层IP头部,GRE头部,内层IP头部以及TCP头部的内容,并将数据发送给服务端,服务端接收后手动解析数据包的内容并打印出来。

GRE VPN(Generic Routing Encapsulation)通用路由封装协议,是对某些网络层协议(如IP和IPX)的数据报进行封装,使这些被封装的数据报能够在另一个网络层协议(如IP)中传输。GRE是VPN(Virtual Private Network)的第三层隧道协议,即在协议层之间采用了一种被称之为Tunnel(隧道)的技术。

运行环境

VMware虚拟机运行两个ubuntu 20.04系统,IP地址分别为192.168.112.128和192.168.112.129

GRE封包

在一些应用场景中,比如公司有总部和分部,要求公司内部的IP地址不能暴露在公网,这时就可以使用GRE对数据包进行再次封装GRE在需要传输的数据包的头部添加GRE头部后,再次对整个数据包进行IP的封装。在GRE隧道传输时,数据包具有双层IP头部,第一个IP头部用于在公网中进行数据传递,第二个IP头部用于在公司内部进行数据传递,这个IP一般为私有地址。具有双层IP头部的包的外层解封之后,露出的是GRE头部,必须运行同样的GRE协议的接口才可以处理此报文。

GRE数据包格式:Gre数据包封装格式、通过NAT设备 - 知乎 GRE、MGRE 详解_gre协议-CSDN博客

RFC文档相关 https://blog.csdn.net/m0_65730854/article/details/122117391

|| 以太网帧头 || 新-IPv4报头 || Gre报头 || 原始-IPv4报头 || TCP报头 || HTTP ||,在代码中需要实现的是手动填充TCP报头信息,原始IPv4报头信息,GRE报头信息

简化GRE包头格式:

Flags and Version:0x3001

Protocol Type:IP(0x0800)

Key:0x00012dff

Sequence Number:2886730204

客户端代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  // For sockaddr_ll
#include 
#include 

#define MAX_PACKET_SIZE 1500

uint16_t source_port = 1234;
uint16_t dest_port = 4321;
uint16_t window_size = 7500;

struct etherhdr
{
    char source_mac[6];
    char dest_mac[6];
    uint16_t protocol; // 0x0800 denote IP
};

struct grehdr
{
    uint16_t flags_and_version;
    uint16_t protocol;
    uint32_t key;
    uint32_t sequence_number;
};

void print_str16(unsigned char buf[], size_t len)
{
    int i;
    unsigned char c;
    if (buf == NULL || len <= 0)
        return;
    for (i = 0; i < len; i++)
    {
        c = buf[i];
        printf("%02x", c);
    }
    printf("\n");
}

void pack_ether_header(char *buffer, char *source_mac, char *dest_mac)
{
    char dst_mac[6] = {0x00, 0x0c, 0x29, 0xdb, 0xd8, 0x5f};
    char src_mac[6] = {0x00, 0x0c, 0x29, 0x0b, 0x1b, 0x21};
    memcpy(buffer, dst_mac, 6);
    memcpy(buffer + 6, src_mac, 6);
    struct etherhdr *etherh 

你可能感兴趣的:(c语言,开发语言)