免费注册 查看新帖 |

Chinaunix

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

[网络子系统] Netfilter 修改源ip地址错误,系统死机,求大神帮忙!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2017-04-07 15:48 |只看该作者 |倒序浏览
本人想写一个关于Netfilter 的内核模块,这个模块主要用来检查所以进入本机的数据包,如果是发给本机的(192.68.4.103)tcp包,就修改包头的源IP地址为100.100.100.100 然后通过。小弟初学内核编程,一个人鼓捣了好久。对源文件编译通过后无法正常加载该模块。每次一加载,键盘后两个灯就会不停闪烁,电脑死机,没有任何反映(屏幕不变黑)。
本人使用的是ubuntu 16.04  操作系统。
下面是本人写的模块文件。
跪求各位大神给予小弟指点迷津。



  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/netfilter.h>
  4. #include <linux/netfilter_ipv4.h>
  5. #include<linux/inet.h>
  6. #include<net/ip.h>
  7. #include<net/tcp.h>
  8. #include <linux/netdevice.h>
  9. #include <linux/inet.h>
  10. #include <linux/socket.h>
  11. #include <linux/skbuff.h>

  12. MODULE_LICENSE("GPL");
  13. MODULE_AUTHOR("LINHOS");

  14. #define IF_NAME "eno1"   //本机网卡名称
  15. struct nf_hook_ops nfho;

  16. static unsigned int checkIP(
  17.         unsigned int hooknum,  //钩子点
  18.         struct sk_buff *__skb,
  19.         const struct net_device *in,
  20.         const struct net_device *out,
  21.         int(*okfn)(struct sk_buff *)//?
  22. ) {
  23.     struct sk_buff *skb; //数据包
  24.     struct net_device *dev; // 驱动设备
  25.     //struct ethhdr *eth_out;  //输出接口  在修改mac地址的时候启用
  26.     struct iphdr *iph;  //ip头
  27.     struct tcphdr *tcph;  //tcp头
  28.     int tot_len;  //总长度
  29.     unsigned int iph_len;  //ip头长度
  30.     int tcph_len;  //tcp头长度
  31.     int ret;
  32.     skb = __skb;
  33.     if (skb == NULL)
  34.         return NF_ACCEPT;
  35.     iph = ip_hdr(skb); //获得ip头
  36.     if (iph == NULL)
  37.         return NF_ACCEPT;
  38.     tot_len = ntohs(iph->tot_len);
  39.     if (iph->daddr =="192.68.4.103") {  //本机ip地址
  40.         iph_len = ip_hdrlen(skb);//获取ip首部长度
  41.         skb_pull(skb, iph_len);//指针跳转ip头长度
  42.         skb_reset_transport_header(skb);//重置IP头?
  43.         if (iph->protocol ==IPPROTO_TCP) {//  判断协议类型(TCP)
  44.             tcph = tcp_hdr(skb);
  45.             tcph_len = tcp_hdrlen(skb);
  46.             iph->saddr = in_aton("100.100.100.100"); //修改源IP地址
  47.             dev = dev_get_by_name(&init_net, IF_NAME);  //获取驱动
  48.             tcph->check = 0;  //校验码置0
  49.             skb->csum = csum_partial((unsigned char *) tcph,
  50.                                      tot_len - iph_len,
  51.                                      0);
  52.             //重置校验和
  53.             tcph->check = csum_tcpudp_magic(iph->saddr,
  54.                                             iph->daddr,
  55.                                             ntohs(iph->tot_len) - iph_len,
  56.                                             iph->protocol,
  57.                                             skb->csum);
  58.             //tcp校验
  59.             iph->check = 0;
  60.             iph->check = ip_fast_csum(iph, iph->ihl);
  61.             //ip头校验,需要先置0
  62.             skb->ip_summed = CHECKSUM_NONE;  //设定不需要进行硬件校验
  63.             skb->pkt_type = PACKET_HOST;
  64.             skb->dev = dev;
  65.             skb_push(skb, iph_len);  //退入第三层
  66.             skb_push(skb, ETH_ALEN);  //退入第二层
  67.             ret = dev_queue_xmit(skb);  //发送数据包
  68.             if (ret < 0) {   //发送失败
  69.                 printk(KERN_ERR "dev_queue_xmit() error!\n");
  70.                 return NF_DROP;  //丢弃
  71.             }
  72.             return NF_STOLEN;  
  73.         }
  74.         skb_push(skb, iph_len);
  75.         skb_reset_transport_header(skb);
  76.     }
  77.     return NF_ACCEPT;
  78. }


  79. static int __initfilter_init(void){
  80.     printk("------------------------------------checkIP  is OK!-------------------------------------");
  81.     nfho.hook = checkIP;
  82.     nfho.pf = AF_INET;  //设置协议类型,与PF_INEF相同
  83.     nfho.hooknum = NF_INET_PRE_ROUTING;

  84.     nfho.priority = NF_IP_PRI_FIRST;  //设置钩子的优先级
  85.     int ret = nf_register_hook(&nfho);   //注册钩子
  86.     if (ret < 0) {
  87.         printk(KERN_ERR "can't modify skb hook!");
  88.         return ret;
  89.     }
  90.     return 0;
  91. }

  92. static void filter_exit(void) {
  93.     nf_unregister_hook(&nfho);
  94. }

  95. module_init(filter_init);
  96. module_exit(filter_exit);
复制代码
求大神指导我写的哪里错了,该怎么改。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2017-04-08 01:43 |只看该作者
回复 1# linhos

if (iph->daddr =="192.68.4.103") {  //本机ip地址

你从哪里知道 ip 地址是这么比较的饿?

论坛徽章:
0
3 [报告]
发表于 2017-04-10 09:08 |只看该作者
回复 2# Godbach

呃,这是我的一个失误。因为一直调不通,因此写了很多个版本,改疏忽了。
原本是这么写的:
if (iph->daddr ==in_aton("192.68.4.103"))
但是这样子编译出来还是有问题,首先是网络不通了,wireshark 也查不到想符合的结果(没有源地址是100.100.100.100)
其次就是我改了下return NF_STOLEN 改为了NF_ACCEPT ,但这会导致在加载模块的时候引起系统死机(无任何相应,键盘灯不停闪烁)。
跪求大神指点迷津啊! 我只想想根据目的地址,修改源IP,然后转发(或者接收)

论坛徽章:
0
4 [报告]
发表于 2017-04-10 09:57 |只看该作者
回复 2# Godbach

Netfilter 现在的钩子函数指针是这样的:typedef unsigned int nf_hookfn (void *priv,
                struct sk_buff *skb,
                const struct nf_hook_state *state);
这是不是意味着现在使用Netfilter 写的钩子函数不应该再用
unsigned int checksum(unsigned int hooknum,
                        struct sk_buff *__skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *))这种函数形式了?
如果是的话,我到现在没有在网上找到一个符合现在钩子函数指针形式的例子。如果不是的话,函数类型和个数不匹配,会不会对程序有影响?
求大神指教,该怎么从头学习Netfilter?



论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
5 [报告]
发表于 2017-04-10 15:07 |只看该作者
回复 4# linhos
从内核中学习吧。 参考现在内核中 netfilter 的 hook 的用法,把代码改成适合当前内核版本的。
这个接口之前应该至少变过两次了。


论坛徽章:
0
6 [报告]
发表于 2017-04-10 15:32 |只看该作者
回复 5# Godbach
有没有适合现在版本(4.0以上)的Netfilter 的hook 用法的书或者文章之类的?最好带上列子。求大神推荐。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
7 [报告]
发表于 2017-04-10 17:02 |只看该作者
回复 6# linhos

内核代码就是第一手最好用的例子。

论坛徽章:
0
8 [报告]
发表于 2017-04-11 09:02 |只看该作者
回复 7# Godbach

问大神一个简单的问题:假如我通过Netfilter,只修改了skb 的 原ip地址,我需要重新设置tcp/udp 校验和吗? 我需要重新设置skb 的csum 吗?

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
9 [报告]
发表于 2017-04-11 13:49 |只看该作者
回复 8# linhos

你了解下 TCP 的校验和包含哪些部分的计算,就知道是否需要重新计算了。

招聘 : c/c++研发
论坛徽章:
0
10 [报告]
发表于 2017-04-28 15:34 |只看该作者
你在prerouting拿到的包还没找路由呢,就调用dev_queue_xmit,那肯定出问题啊
调内核最好开启kdump,挂了也能分析问题在哪
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP