免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7674 | 回复: 5

[内核模块] 关于路由器下Netfilter截获的转发数据包问题 [复制链接]

论坛徽章:
0
发表于 2018-10-22 09:01 |显示全部楼层
大家好,当前我在路由器下挂载了自己编写的Netfilter的模块,hook点设置的NF_INET_PRE_ROUTING.问题1:
在钩子函数中,我取ip头时,我们正常的取ip头应该是struct * iphdr iph = ip_hdr(skb) ;直接调用系统提供的函数即可
但我在代码中将正常的地址向前偏移了一个IP头的字节才取到了正确的ip头地址,即: struct * iphdr iph = ip_hdr(skb) - 1;
不知道这偏移的20字节是什么信息,我没有分析出来,所以向各位有经验的大佬请教。
问题2:
在if_packet.h中有这样一段宏的定义:
/* Packet types */

#define PACKET_HOST                0                /* To us                */
#define PACKET_BROADCAST        1                /* To all                */
#define PACKET_MULTICAST        2                /* To group                */
#define PACKET_OTHERHOST        3                /* To someone else         */
#define PACKET_OUTGOING                4                /* Outgoing of any type */
/* These ones are invisible by user level */
#define PACKET_LOOPBACK                5                /* MC/BRD frame looped back */
#define PACKET_FASTROUTE        6                /* Fastrouted frame        */


路由器下的客户端不管是通过浏览器访问百度时还是进行其他操作,该模块中的skb->pkt_type的值始终为0,
我认为当这个数据包是转发包时,pkt_type的值应该是PACKET_OTHERHOST才对吧?这一点我不甚理解。
请教各位大佬还有没有什么办法能比较简单的从skb中判断该数据包是转发包来?

论坛徽章:
0
发表于 2018-10-22 09:09 |显示全部楼层
附上代码:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>

#include <linux/socket.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/tcp.h>
#include <linux/udp.h>

#include <linux/netdevice.h>



MODULE_LICENSE("GPL");
MODULE_AUTHOR("bbo");


static struct nf_hook_ops g_hnf;
unsigned int forwardData(unsigned int hooknum,
                      struct sk_buff *__skb,
                      const struct net_device *in,
                      const struct net_device *out,
                      int (*okfn)(struct sk_buff *))
{

    struct sk_buff *skb = NULL;
    struct iphdr *iph = NULL;
    struct tcphdr *tcph = NULL;
    int iph_len = 0, tcph_len = 0;
    unsigned char *payload = NULL;
    skb = __skb;
    iph = ip_hdr(skb) - 1;
    if (!skb || !iph )
        return NF_ACCEPT;
    if (skb->len < 20)
        return NF_ACCEPT;
    if (iph->version != 4)
        return NF_ACCEPT;
    iph_len = iph->ihl * 4;//ip_hdrlen(skb);
    if (skb->protocol != htons(ETH_P_IP))
        printk("skb->protocol:%d\n", ntohs(skb->protocol));
    if (iph->protocol == IPPROTO_TCP)
    {
    if (skb->pkt_type != 0)
        printk("pkt_type=%d\n", skb->pkt_type);
    return NF_ACCEPT;
        unsigned int sip = (unsigned int)iph->saddr;
        unsigned int dip = (unsigned int)iph->daddr;
        tcph = (struct tcphdr*)((unsigned char*)iph + iph->ihl * 4);
        tcph_len = tcph->doff * 4;
        unsigned short sport = 0, dport = 0;
        sport = ntohs(tcph->source);
        dport = ntohs(tcph->dest);
        printk("<0>source ip:%d.%d.%d.%d\n", sip & 0x000000ff, (sip & 0x0000ff00) >> 8, (sip & 0x00ff0000) >> 16, (sip & 0xff000000) >> 24   );
        printk("<0>dest ip:%d.%d.%d.%d\n",   dip & 0x000000ff, (dip & 0x0000ff00) >> 8, (dip & 0x00ff0000) >> 16, (dip & 0xff000000) >> 24   );
        printk("<0>source port:%d, dest port:%d\n", sport, dport);

        return NF_ACCEPT;

    }
    else if (iph->protocol == IPPROTO_UDP)
    {
        return NF_ACCEPT;
    }
    return NF_ACCEPT;

}

static int __init filter_init(void)
{
    printk("<0>init filter feature");
    g_hnf.hooknum = NF_INET_PRE_ROUTING;//NF_INET_LOCAL_IN;
    g_hnf.priority = NF_IP_PRI_MANGLE;
    g_hnf.pf = PF_INET;
    g_hnf.hook = forwardData;
    int ret = nf_register_hook(&g_hnf);
    if (ret < 0)
    {
        printk("<0>netfilter register failed!\n");
        return ret;
    }
    return 0;
}



static void __exit filter_exit(void)
{
    printk("<0>exit module");
    nf_unregister_hook(&g_hnf);
}

module_init(filter_init);
module_exit(filter_exit);

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-12-20 06:20:00
发表于 2018-10-31 22:59 |显示全部楼层
20字节就是ip头呗,好像是skb->network_header 被其他的修改过了,看看有其他的filter吗

论坛徽章:
0
发表于 2018-11-01 09:49 |显示全部楼层
回复 3# goingstudy

感谢回答,并没有其他的filter了,我也觉得是skb->network_header的原因,但没有找到证据。

论坛徽章:
0
发表于 2018-11-01 09:53 |显示全部楼层
在netfilter中,除了skb->pkt_type能判断是否转发包外,还有其他方法可以直接判断吗?
目前我是直接通过判断ip来确认是否转发包,想知道还有没有其他更便捷的方法

论坛徽章:
0
发表于 2018-11-15 08:59 |显示全部楼层
自己来回答问题1:
iph  = ip_hdr(skb) - 1;
这偏移的20字节有16字节是链路层的struct ethhdr,另外那4字节貌似是vlanhdr,我没有解析剩下的那4字节,因为意义不大。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP