Linux下使用Netfilter强制清除IPv4 DF标志

匿名 (未验证) 提交于 2019-12-02 21:56:30
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/force_eagle/article/details/90522425

clear ip df kernel module

此模块比较简单, 主要目的在使用GRE隧道时强制对数据报文长度>GRE隧道MTU的IPv4 DF标志的报文进行分片. Linux默认丢弃此类报文并根据PMTUD是否响应ICMP报文, 而不是直接进行分片!
加载此模块后会对所有数据ipv4报文强制清除DF标志.
ע:
未启用PMTUD功能;
Linux GRE 隧道默认MTU 1476, 默认对所有未设置DF标志报文进行分片后再ENCAP;

prepare

yum install gcc makc perl elfutils-libelf-devel kernel-devel kernel-headers 

source

#ifdef    MODVERSIONS #include  <linux/modversions.h> #endif  #include <linux/version.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/types.h> #include <linux/random.h> #include <linux/vmalloc.h> #include <linux/init.h> #include <net/pkt_sched.h> #include <net/ip.h> #include <net/tcp.h> #include <net/udp.h> #include <net/icmp.h> #include <linux/inet.h> #include <linux/list.h> #include <linux/mm.h> #include <linux/sysctl.h> #include <linux/fs.h> #include <linux/kernel_stat.h> #include <linux/if_vlan.h> #include <linux/netfilter_bridge.h> #include <linux/inetdevice.h> #include <asm/uaccess.h>        /* for put_user */ #include <asm/atomic.h>        /* for put_user */   #include "dbg.h"  #define MTU_DST		1400  #define MKIPV4(a,b,c,d) \ 	(u32)(((__u8)d & 0xFF) << 24 | ((__u8)c & 0xFF) << 16 | ((__u8)b & 0xFF) << 8 | (a & 0xFF))  #if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 13, 0) /*  include/linux/netfilter.h typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,                    struct sk_buff *skb,                    const struct net_device *in,                    const struct net_device *out, #ifndef __GENKSYMS__                    const struct nf_hook_state *state #else                    int (*okfn)(struct sk_buff *) #endif                    );  */ static unsigned int nf_ip_input(const struct nf_hook_ops *ops, 	   struct sk_buff *skb, 	   const struct net_device *in, 	   const struct net_device *out, #ifndef __GENKSYMS__ 	   const struct nf_hook_state *state #else 	   int (*okfn)(struct sk_buff *) #endif ) #else /*  typedef unsigned int nf_hookfn(void *priv,                    struct sk_buff *skb,                    const struct nf_hook_state *state); */  static unsigned int nf_ip_input(void *priv,           struct sk_buff *skb,           const struct nf_hook_state *state) #endif { 	struct iphdr *iph = NULL; 	iph = ip_hdr(skb); 	iph->frag_off = 0x0; 	iph->check = 0; 	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); 	return NF_ACCEPT; }  static struct nf_hook_ops nf_hook_ops[] __read_mostly = {     {         .hook       = nf_ip_input, #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0)         .owner      = THIS_MODULE, #endif         .pf         = PF_INET,         .hooknum    = NF_INET_PRE_ROUTING,         .priority   = NF_IP_PRI_FIRST,     }, };  int nf_ip_df_init( void ) { 	int err = 0; 	pr_notice( "nf_ip_df_init..\n" ); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)  	err = nf_register_net_hook(&init_net, nf_hook_ops); #else 	err = nf_register_hooks(nf_hook_ops, ARRAY_SIZE(nf_hook_ops)); #endif     if (err < 0) {         pr_notice("nf_ip_df_init: can't register hooks.\n");     } 	pr_emerg( "INT_MIN = %d\n", INT_MIN ); 	pr_info( "ip_mtu: register hooks success.\n" ); 	return err; }  void nf_ip_df_fini(void) { 	pr_notice( "nf_ip_df_fini..\n" ); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)  	nf_unregister_net_hook(&init_net, nf_hook_ops); #else 	nf_unregister_hooks(nf_hook_ops, ARRAY_SIZE(nf_hook_ops)); #endif }  module_init(nf_ip_df_init); module_exit(nf_ip_df_fini); MODULE_LICENSE( "GPL" );  

Makefile

ARCH := x86 KVER := $(shell uname -r) KSP ?= /lib/modules/$(KVER)/build  #EXTRA_CFLAGS +=-DTEST  obj-m += ip_df.o  all: clean 	make -C $(KSP) M=`pwd` modules  clean: 	make -C $(KSP) M=`pwd` clean 	rm -f Module.symvers 	rm -f modules.order  test: 	insmod ip_df.ko 
文章来源: https://blog.csdn.net/force_eagle/article/details/90522425
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!