本文共 7007 字,大约阅读时间需要 23 分钟。
/* * "XXX" target extension for iptables! 其中就是一个幌子,为了使用iptables而已! * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License; either * version 2 of the License, or any later version, as published by the * Free Software Foundation. */#include#include #include "compat_user.h"static void xxx_tg_help(void){ printf("XXX takes no options\n\n");}static int xxx_tg_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **target){ return 0;}static void xxx_tg_check(unsigned int flags){}static struct xtables_target xxx_tg_reg = { .version = XTABLES_VERSION, .name = "XXX", .revision = 1, .family = NFPROTO_IPV4, .help = xxx_tg_help, .parse = xxx_tg_parse,};static __attribute__((constructor)) void xxx_tg_ldr(void){ xtables_register_target(&xxx_tg_reg);}
/* * xt_xxx - kernel module to drop and re-NEW CONNTRACK to * fit NAT * * Original author: Wangran*/#include #include #include #include "compat_xtables.h"MODULE_AUTHOR("Wanagran ");MODULE_DESCRIPTION("Xtables: xxx match module");MODULE_LICENSE("GPL");MODULE_ALIAS("ipt_xxx");/* * queue handler捕获数据包,然后重新注入,区别在于: * 1:如果本身是NOTRACK的数据包,直接注回去; * 2:如果本身没有绑定任何conntrack,直接注回去; * 3:如果本身有conntrack,删掉该conntrack后,注回去 * 3.1.不是注回原来的位置,而是注回PREROUTING最开始的位置。 * 注意:虽然TAGEGET本身已经阻止了1,2的情况,还是判断了一下, * 因为虽然我知道这一点,但是resetct_queue并不清楚... */static int resetct_queue(struct nf_queue_entry *entry, unsigned queue_num){ struct sk_buff *skb = entry->skb; struct nf_conn *ct = NULL; enum ip_conntrack_info ctinfo; if (nf_ct_is_untracked(skb)) goto reinject; else if (!(ct = nf_ct_get(skb, &ctinfo))) goto reinject; else { // 为了重新初始化conntrack,使之状态变为可做NAT的NEW! struct list_head *elem = &nf_hooks[entry->pf][entry->hook]; nf_reset(skb); nf_ct_kill(ct); entry->elem = list_entry(elem, struct nf_hook_ops, list); }reinject: nf_reinject(entry, NF_ACCEPT); return 0;}/* * XXX的执行TARGET,旨在针对以下的一类数据包进行queue处理: * 本身是NEW状态,且已经被confirm了,这种数据包在其conntrack * 过期之前,无疑已经不会再去匹配任何NAT规则了! */static unsigned intxxx_tg4(struct sk_buff **skb, const struct xt_action_param *par){ struct nf_conn *ct; enum ip_conntrack_info ctinfo; ct = nf_ct_get(*skb, &ctinfo); if (!ct || ct == &nf_conntrack_untracked) { return XT_CONTINUE; } // 仅仅处理正向数据包,否则... if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { return XT_CONTINUE; } if (ctinfo == IP_CT_NEW && !nf_ct_is_confirmed(ct)) { return XT_CONTINUE; } return NF_QUEUE;}static struct nf_queue_handler xxxqh = { .name = "resetct", .outfn = resetct_queue,};static struct xt_target xxx_tg_reg[] __read_mostly = { { .name = "XXX", .revision = 1, .family = NFPROTO_IPV4, .table = "mangle", .hooks = 1 << NF_INET_PRE_ROUTING, .target = xxx_tg4, .me = THIS_MODULE, },};static int __init xt_xxx_target_init(void){ int status = 0; status = nf_register_queue_handler(NFPROTO_IPV4, &xxxqh); if (status < 0) { printk("XXX: register queue handler error\n"); goto err; } status = xt_register_targets(xxx_tg_reg, ARRAY_SIZE(xxx_tg_reg)); if (status < 0) { printk("XXX: register target error\n"); goto err; }err: return status;}static void __exit xt_xxx_target_exit(void){ nf_unregister_queue_handlers(&xxxqh); return xt_unregister_targets(xxx_tg_reg, ARRAY_SIZE(xxx_tg_reg));}module_init(xt_xxx_target_init);module_exit(xt_xxx_target_exit);
这样的话,所有进来的数据包都会执行下面的逻辑:
如果这样,相当于架空了整个ip_conntrack的优化,这种鲁莽的做法并不是我的目的,我希望它和其它的match比如mark,condition一起使用,这样就可以把不相关的数据包过滤掉而不触及,依旧执行往常的逻辑,这就是我为何一直坚持使用iptables的原因而不是使用其它的用户态/内核态通信的方式。就想之前我提到的基于ip_conntrack的快速/慢速匹配方式那样,这个NAT及时匹配也可以使用类似的逻辑:
iptables -t mangle -A PREROUTING -m condition --condition slow ... -j XXX转载地址:http://brmhl.baihongyu.com/