免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5642 | 回复: 6
打印 上一主题 下一主题

[内核模块] Netfilter在网络层抓到包后,底层提供了哪些API直接发送IP包? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2018-11-02 15:11 |只看该作者 |倒序浏览
我在路由器下PREROUTING链抓到转发包,并且希望修改包内容继续发送,我该调用底层的哪个API?我知道dev_queue_xmit可以在二层发送,我想知道有没有哪个API可以直接在IP层发送?

谢谢各位大牛~

论坛徽章:
0
2 [报告]
发表于 2018-11-05 08:48 |只看该作者
我想要在路由器netfilter 钩子中捕获到数据包为转发包时,修改目标ip,然后发送出去,但不想调用dev_queue_xmit,所以想知道有没有更上层一点的函数可以直接发送ip包的,最好是不需要处理分片以及设置路由的。

论坛徽章:
1
2017金鸡报晓
日期:2017-01-10 15:13:29
3 [报告]
发表于 2018-11-06 10:16 |只看该作者
你跟踪一下数据包的转发过程就知道啦,大概记得ip层出去的话是ip_output

论坛徽章:
0
4 [报告]
发表于 2018-11-06 10:29 |只看该作者
回复 3# philarlala

感谢回复,我调用过类似ip_local_out之类的函数,但我改了dest_ip后,设置的路由总是不正确,我设置的路由总会让内核崩溃。

论坛徽章:
0
5 [报告]
发表于 2018-11-06 13:25 |只看该作者
本帖最后由 匿名者7 于 2018-11-06 14:05 编辑

/* Send RST reply */
static void send_reset(struct sk_buff *oldskb, int hook)
{
        struct sk_buff *nskb;
        const struct iphdr *oiph;
        struct iphdr *niph;
        const struct tcphdr *oth;
        struct tcphdr _otcph, *tcph;

        /* IP header checks: fragment. */
        if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
                return;

        oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
                                 sizeof(_otcph), &_otcph);
        if (oth == NULL)
                return;

        /* No RST for RST. */
        if (oth->rst)
                return;

        if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
                return;

        /* Check checksum */
        if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
                return;
        oiph = ip_hdr(oldskb);

        nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
                         LL_MAX_HEADER, GFP_ATOMIC);
        if (!nskb)
                return;

        skb_reserve(nskb, LL_MAX_HEADER);

        skb_reset_network_header(nskb);
        niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
        niph->version        = 4;
        niph->ihl        = sizeof(struct iphdr) / 4;
        niph->tos        = 0;
        niph->id        = 0;
        niph->frag_off        = htons(IP_DF);
        niph->protocol        = IPPROTO_TCP;
        niph->check        = 0;
        niph->saddr        = oiph->daddr;
        niph->daddr        = oiph->saddr;

        skb_reset_transport_header(nskb);
        tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
        memset(tcph, 0, sizeof(*tcph));
        tcph->source        = oth->dest;
        tcph->dest        = oth->source;
        tcph->doff        = sizeof(struct tcphdr) / 4;

        if (oth->ack)
                tcph->seq = oth->ack_seq;
        else {
                tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
                                      oldskb->len - ip_hdrlen(oldskb) -
                                      (oth->doff << 2));
                tcph->ack = 1;
        }

        tcph->rst        = 1;
        tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
                                    niph->daddr, 0);
        nskb->ip_summed = CHECKSUM_PARTIAL;
        nskb->csum_start = (unsigned char *)tcph - nskb->head;
        nskb->csum_offset = offsetof(struct tcphdr, check);

        /* ip_route_me_harder expects skb->dst to be set */
        skb_dst_set_noref(nskb, skb_dst(oldskb));

        nskb->protocol = htons(ETH_P_IP);
        if (ip_route_me_harder(nskb, RTN_UNSPEC))
                goto free_nskb;

        niph->ttl        = ip4_dst_hoplimit(skb_dst(nskb));

        /* "Never happens" */
        if (nskb->len > dst_mtu(skb_dst(nskb)))
                goto free_nskb;

        nf_ct_attach(nskb, oldskb);

        ip_local_out(nskb);
        return;

free_nskb:
        kfree_skb(nskb);
}

以上是send_reset的实现,我模仿此函数,在netfilter中自构造了udp包并发送,但每当到               if (ip_route_me_harder(nskb, RTN_UNSPEC))
                goto free_nskb;
这里时系统就会崩溃,据我所知这个函数是用来重新路由的,RTN_UNSPEC表示未知路由。

论坛徽章:
0
6 [报告]
发表于 2018-11-06 16:14 |只看该作者
ip_route_me_harder(nskb, RTN_UNSPEC) 函数崩溃问题已经解决,我将此函数源码拿到我的代码中调用就没有问题。
目前调用 ip_local_out(nskb) 函数时系统又崩溃了,跟踪此函数,实际调用是dst_output()与nf_hook()函数,直接调用这两个函数系统也会崩溃。
有老大知道问题所在么?

论坛徽章:
0
7 [报告]
发表于 2018-11-07 16:10 |只看该作者
目前 alloc_skb()的包调用dst_out函数依然会导致系统崩溃,但skb_copy的包互换ip、port后,计算ip校验和并发送,已经没有问题,目标主机也成功收到。
但不明白alloc_skb的包为何会导致系统崩溃。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP