【问题标题】:netfilter_queue ipv4 optional header removalnetfilter_queue ipv4 可选标头删除
【发布时间】:2020-11-11 15:14:37
【问题描述】:

我正在实现基于 netfilter_queue 的用户程序,该程序删除 ipv4 可选标头“时间戳”

ping 与这个程序配合得很好,因为它使用 ICMP 传输。

基于 TCP 的应用程序不起作用。我用wireshark检查过,这个程序很好地删除了时间戳。相反,基于 TCP 的应用程序不会为该数据包发送 ACK,远程服务器会无限期地重新传输相同的数据包。

是否缺少 TCP 数据包处理的程序?我只是修改了 IPv4 标头部分。那为什么tcp传输根本不起作用呢?

我的主要代码是:

static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
          struct nfq_data *nfa, void *data)
{
    
    unsigned int timestamp = 0;
    bool ptype = true;
    int pnow = 20;
    int plast = 20;
    int ihl;
    
    struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);

    unsigned char* rawBuff = NULL;
    int len;
    len = nfq_get_payload(nfa, &rawBuff);
    if(len < 0) printf("Failed to get payload");

    struct pkt_buff* pkBuff = pktb_alloc(AF_INET, rawBuff, len, 0x20);
    struct iphdr* ip = nfq_ip_get_hdr(pkBuff);
    
    ihl = ip->ihl;
    uint8_t* buff = NULL;
    
    if( (ip->daddr != 0x0101007f) && (ip->daddr != 0x0100007f) && (ip->daddr != 0x0100A9C0) && (ip->saddr != 0x0100A9C0)) { // filter_out dns
        if(ip->version == 4) {
            if(ihl != 5) { // if ipv4 packet header is longer than default packet header
                buff = pktb_data(pkBuff); // packet buffer
                plast = ihl * 4;
                while(pnow != plast) {
                    if(buff[pnow] == 0x44) { // timestamp type
                        ptype = false;
                        break;
                    }
                    else {
                        if(buff[pnow+1] == 0) {
                            pnow = pnow + 4;
                        }
                        else {
                            pnow = pnow + buff[pnow+1];
                        }
                    }
                }
            }
            if(!ptype) {
                timestamp = buff[pnow + 4] << 24 | buff[pnow + 5] << 16 | buff[pnow + 6] << 8 | buff[pnow + 7];
                if(timestamp > 100000) { // if TS is big, delete it.
                    ip->ihl -= 2;
                    nfq_ip_mangle(pkBuff, pnow, 0, 8, "", 0);
                }
            }
        }
    }
    
    nfq_ip_set_checksum(ip);
    if(nfq_ip_set_transport_header(pkBuff, ip) < 0) printf("Failed to set transport header");

    int result = 0;
    result = nfq_set_verdict(qh, ntohl(ph->packet_id), NF_ACCEPT, pktb_len(pkBuff), pktb_data(pkBuff));
    pktb_free(pkBuff);
    return result;
}

iptables 设置为:

sudo iptables -t mangle -A PREROUTING -j NFQUEUE -p all --queue-num 0
sudo iptables -t mangle -A POSTROUTING -j NFQUEUE -p all --queue-num 0

【问题讨论】:

    标签: tcp timestamp netfilter packet-mangling


    【解决方案1】:

    你不应该把 TCP 头放在 IP 头之后吗?

     0...............20.........28..........48..........
     +---------------+----------+-----------+-----------+
     |IP HEADER      |IP OPTIONS| TCP HEADER|TCP OPTIONS|
     +---------------+----------+-----------+-----------+
    

    因此,减少ihl 的值,您将在 IP 标头和 TCP 标头之间造成差距。 您需要使用memmove 并减少ihl 值。

    【讨论】:

      【解决方案2】:

      似乎 netfilter_queue 出现故障。调试内核后,我可以确定 skbuff 的 network_header 指针没有更新,即使我更改了 netfilter_queue 的等效指针。损坏的数据包被数据包长度检查代码丢弃。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-28
        • 1970-01-01
        • 2011-05-18
        相关资源
        最近更新 更多