netfilter(2) 自定义match模块
代码
先贴上代码,后续再添加解释
uname -r 3.10.0-514.el7.x86_64
用户态代码
/*xt_pktsize.h /usr/inlcude/linux/netfilter_ipv4/*/ 1 #ifndef __IPT_PKTSIZE_H 2 #define __IPT_PKTSIZE_H 3 4 #define PKTSIZE_VERSION "0.1" 5 6 struct xt_pktsize_info { 7 u_int32_t min_pktsize,max_pktsize; 8 }; 9 10 #endif
#include <stdio.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <getopt.h> #include <ctype.h> #include <xtables.h> #include <linux/netfilter_ipv4/xt_pktsize.h> static void __parse_pkts(const char* s,struct xt_pktsize_info *info); static void __print(struct xt_pktsize_info *info); static struct option opts[] = { { "size", 1, NULL, '1' }, {0} }; static void help(void) { printf( "pktsize v%s options:\n" " --size size[:size] Match packet size against value or range\n" "\nExamples:\n" " iptables -A FORWARD -m pktsize --size 65 -j DROP\n" " iptables -A FORWARD -m pktsize --size 80:120 -j DROP\n" , PKTSIZE_VERSION); } /* Parse CLI parameters to xt_entry_match struct. And xtables_match.name will be copied to xt_entry_match struct * In kernel space, the same xt_entry_match will be used to find correspond kenel match mode which is xt_match */ static int parse(int c, char **argv, int invert, unsigned int *flags , const void *entry , struct xt_entry_match **match) { struct xt_pktsize_info *info = (struct xt_pktsize_info *)(*match)->data; switch(c){ case '1': if (*flags) xtables_error(PARAMETER_PROBLEM, "size: `--size' may only be " "specified once"); __parse_pkts(argv[optind-1], info); *flags = 1; break; default: return 0; } return 1; } static void final_check(unsigned int flags) { if(!flags) xtables_error(PARAMETER_PROBLEM,"\npktsize-parameter problem: for pktsize useage type: iptables -m pktsize --help\n"); } static void print(const void *ip, const struct xt_entry_match *match, int numeric) { printf("size "); __print((struct xt_pktsize_info*)match->data); } static void save(const void *ip, const struct xt_entry_match *match) { printf("--size "); __print((struct xt_pktsize_info *)match->data); } static struct xtables_match pktsize= { .name = "pktsize", .version= XTABLES_VERSION, .family = NFPROTO_IPV4, .size = XT_ALIGN(sizeof(struct xt_pktsize_info)), .userspacesize= XT_ALIGN(sizeof(struct xt_pktsize_info)), .help = help, .parse = parse, .final_check= final_check, .print = print, .save = save, .extra_opts = opts }; void _init(void) { xtables_register_match(&pktsize); } static void __print(struct xt_pktsize_info *info) { if (info->max_pktsize == info->min_pktsize) printf("%u ", info->min_pktsize); else printf("%u:%u ", info->min_pktsize, info->max_pktsize); } static void __parse_pkts(const char* s,struct xt_pktsize_info *info) { char* buff,*cp; buff = strdup(s); if(NULL == (cp=strchr(buff,':'))){ info->min_pktsize = info->max_pktsize = strtol(buff,NULL,0); }else{ *cp = '\0'; cp++; info->min_pktsize = strtol(buff,NULL,0); info->max_pktsize = (cp[0]? strtol(cp,NULL,0):0xFFFF); } free(buff); if (info->min_pktsize > info->max_pktsize) xtables_error(PARAMETER_PROBLEM, "pktsize min. range value `%u' greater than max. " "range value `%u'", info->min_pktsize, info->max_pktsize); }
内核态代码
#include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/version.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/xt_pktsize.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Xie"); MODULE_DESCRIPTION("Netfilter Module"); static bool match(const struct sk_buff *skb,struct xt_action_param *param) { const struct xt_pktsize_info *info = param->matchinfo; const struct iphdr *iph = ip_hdr(skb); int truesize = ntohs(iph->tot_len)-(iph->ihl*4); if(truesize >= info->min_pktsize && truesize <= info->max_pktsize) return 1; else return 0; return 1; } static struct xt_match pktsize_match = { .name = "pktsize", .family = AF_INET, .match = match, .matchsize = sizeof(struct xt_pktsize_info), .destroy= NULL, .me = THIS_MODULE, }; static int __init init(void) { return xt_register_match(&pktsize_match); } static void __exit fini(void) { xt_unregister_match(&pktsize_match); } module_init(init); module_exit(fini);
使用
iptables -A INPUT -m pktsize --size 60:100 -j DROP
使用 ping -s 80 会发现不通了。
相关推荐
陌阡 2020-07-19
AHuqihua 2020-06-13
InJavaWeTrust 2020-06-04
jianxm 2020-03-28
心丨悦 2020-02-02
wangxiaoxue 2020-01-23
jyj00 2020-01-11
SDUTACM 2020-01-10
eroshn 2020-01-05
luofuIT成长记录 2019-12-30
心丨悦 2019-12-23
Darklovy 2019-12-06
YYDU 2019-11-17
cooldatabase 2019-11-17
YoungerChen 2019-11-08