簡體   English   中英

修改捕獲的數據包的標頭

[英]Modify header of a captured packet

我正在嘗試使用libnetfiletr_queue修改IP標頭以包含更多IP選項。 到目前為止,我已經成功地獲得了如下所示的數據包。

if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
    fprintf(stderr, "Unable to set nfq_set_mode\n");
    exit(1);
}

然后我設法走得很遠,如下圖所示,

static int my_callBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,struct nfq_data *tb)
{   
    int id = 0;
    int packet_len;
    unsigned char *data;
    struct nfqnl_msg_packet_hdr *packet_hdr;
    unsigned char *data;

    packet_hdr = nfq_get_msg_packet_hdr(tb);

    if (packet_hdr) {
        id = ntohl(packet_hdr->packet_id);          
    }

    packet_len = nfq_get_payload(tb, &data);

    if (packet_len >= 0) {
        //print payload length
        printf("payload_length = %d ", packet_len);
        //modify packet ip header  
    }

    return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}

但是從這里開始,我對如何繼續修改捕獲的數據包的IP header//modify packet ip header注釋有點困惑。例如對IP頭的修改(例如流量類(IPV6)/ IP選項) / version / flags / destination address是好的,因為我只需要了解修改是如何工作的:)。

我嘗試了很多資源,無法繼續進行任何進一步的工作。 非常感謝您對此查詢的專家建議和幫助。 :)

非常感謝你 :)

要修改IP標頭的值,首先要定義表示標頭的結構。 通過閱讀您嘗試訪問的協議的RFC規范,您可以找到結構應該是什么。

以下是RFC for IPv6的鏈接: https//tools.ietf.org/html/rfc2460#section-3

IPv6標頭的第一行有點棘手,因為它們沒有使用字節對齊的字段。 Version字段為4位寬,Traffic Class為8位寬,Flow Label為20位寬。 整個標頭是320位(40字節),其中256個是src和dest地址。 其他字段只使用64位,因此最簡單的定義結構如下:

struct ipv6_hdr {
    uint32_t row1;
    uint16_t payload_length;
    uint8_t next_header;
    uint8_t hop_limit;
    uint16_t src[8];
    uint16_t dest[8];
};

要提取第一行值,可以使用一些屏蔽:

#define VERSION_MASK 0xF0000000
#define TRAFFIC_CLASS_MASK 0x0FF00000
#define FLOW_LABEL_MASK 0x000FFFFF

struct ipv6_hdr foo;

...

nfq_get_payload(tb, &foo); // Just an example; don't overflow your buffer!

// bit-wise AND gets masked field from row1
uint8_t version = (uint8_t) ((foo->row1 & VERSION_MASK) >> 28);  // shift (32-4) bits

一旦將結構指向數據有效負載,假設您的字節數組與此格式匹配,修改標頭值將變為簡單的賦值:

version = 6;

// bit-wise OR puts our value in the right place in row1
foo->row1 &= ~(VERSION_MASK) // clear out the old value first
foo->row1 = ((uint32_t) version << 28) | foo->row1;  

我選擇在結構中使src和dest地址成為16位值的數組,因為IPv6地址是一系列8位,16位值。 這樣可以很容易地隔離任何給定的字節對。

在將適當的結構應用於數據有效負載之前,您必須確定數據有效負載的格式。

有關如何創建IPv4標頭的信息,請查看其RFC: http//tools.ietf.org/html/rfc791#section-3.1

希望這會有所幫助(您可能必須使用我的代碼示例來獲得正確的語法,這已經過了幾個月)。


根據評論中的要求編輯有關校驗和的信息

修改標題后,請按照此RFC生成校驗和: https//tools.ietf.org/html/rfc1071

在產生新的校驗和之前,關鍵是將標題中的校驗和字段歸零。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM