看了Nicolas寫的netfilter寫匹配器,自己嘗試編譯測試,發現iptables 以及內核版本升級很多數據結構和函數接口都改變了,需要做大量的修改才能運行。
運行 iptables/netfilter
1)iptables
從 ftp://ftp.netfilter.org/pub/iptables/ 下載iptables 的源碼然後拷貝libipt_ipaddr.c 到 iptables-1.4.10/extensions.
拷貝ipt_ipaddr.h 到 ./include/linux/netfilter_ipv4/
然後
- $./configure
- $make && make install
編譯這個內核模塊需用到3個文件:
ipt_ipaddr.h ipt_ipaddr.c Makefile
編譯完內核模塊之後用
- $ sudo modprobe x_tables
- $ sudo insmod ipaddr.ko
- sudo iptables -I OUTPUT -m ipaddr --ipsrc ipaddr --ipdst ipaddr
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/netfilter_ipv4/ip_tables.h>
- #include "ipt_ipaddr.h"
- #define NIPQUAD(addr) \
- ((unsigned char *)&addr)[0], \
- ((unsigned char *)&addr)[1], \
- ((unsigned char *)&addr)[2], \
- ((unsigned char *)&addr)[3]
- #define NF_IP_LOCAL_IN 1
- #define NF_IP_LOCAL_OUT 3
- static int ipt_match(const struct sk_buff *skb,struct xt_action_param *param)
- {
- const struct net_device *in = param->in;
- const struct net_device *out = param->out;
- const struct ipt_ipaddr_info *info = param->matchinfo;
- struct iphdr *iph = ip_hdr(skb);
- printk("entered ipt_match !\n");
- printk(KERN_INFO "ipt_ipaddr: IN=%s OUT=%s TOS=0x%02X "
- "TTL=%x SRC=%u.%u.%u.%u DST=%u.%u.%u.%u "
- "ID=%u IPSRC=%u.%u.%u.%u IPDST=%u.%u.%u.%u\n",
- in ? (char *)in : "", out ? (char *)out : "", iph->tos,
- iph->ttl, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr),
- ntohs(iph->id), NIPQUAD(info->ipaddr.src), NIPQUAD(info->ipaddr.dst)
- );
- if (info->flags & IPADDR_SRC) {
- if ( (ntohl(iph->saddr) != ntohl(info->ipaddr.src)) ^ !!(info->flags & IPADDR_SRC_INV) ) {
- printk(KERN_NOTICE "src IP %u.%u.%u.%u is not matching %s.\n",
- NIPQUAD(info->ipaddr.src),
- info->flags & IPADDR_SRC_INV ? " (INV)" : "");
- return 0;
- }
- }
- if (info->flags & IPADDR_DST) {
- if ( (ntohl(iph->daddr) != ntohl(info->ipaddr.dst)) ^ !!(info->flags & IPADDR_DST_INV) ) {
- printk(KERN_NOTICE "dst IP %u.%u.%u.%u is not matching%s.\n",
- NIPQUAD(info->ipaddr.dst),
- info->flags & IPADDR_DST_INV ? " (INV)" : "");
- return 0;
- }
- }
- return 1;
- }
- static int ipaddr_checkentry(const struct xt_mtchk_param *param)
- {
- printk("entered ipaddr_checkentry\n");
- const struct ipt_ipaddr_info *info = param->matchinfo;
- unsigned int hook_mask = param->hook_mask;
- unsigned int matchsize = param->match->matchsize;
- char tablename[XT_TABLE_MAXNAMELEN];
- const struct ipt_ip *ip = (struct ipt_ip *)param->entryinfo; // this is specified by param->family.
- if (hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
- printk(KERN_WARNING "ipt_ipaddr: only valid with the FILTER table.\n");
- return 0;
- }
- if (matchsize != XT_ALIGN(sizeof(struct ipt_ipaddr_info))) {
- printk(KERN_ERR "ipt_ipaddr: matchsize differ, you may have forgotten to recompile me.\n");
- return 0;
- }
- strcpy(tablename,param->match->table);
- printk(KERN_INFO "ipt_ipaddr: Registered in the %s table, hook=%x, proto=%u\n",
- tablename, hook_mask, ip->proto);
- return 1;
- }
- static struct xt_match ipaddr_match = {
- .match = ipt_match,
- .matchsize = XT_ALIGN(sizeof(struct ipt_ipaddr_info)), /// without this may cause invalid size 0 != 12
- .name = "ipaddr",
- .checkentry = ipaddr_checkentry,
- .me = THIS_MODULE
- };
- static int __init init(void)
- {
- printk(KERN_INFO "ipt_ipaddr: init!\n");
- return xt_register_match(&ipaddr_match);
- }
- static void __exit fini(void)
- {
- printk(KERN_INFO "ipt_ipaddr: exit!\n");
- xt_unregister_match(&ipaddr_match);
- }
- module_init(init);
- module_exit(fini);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Nicolas Bouliane && Samuel Jean");
- MODULE_DESCRIPTION("netfilter module skeleton");
ipt_ipaddr.h
- #ifndef _IPT_IPADDR_H
- #define _IPT_IPADDR_H
- #include <linux/types.h>
- #define IPADDR_SRC 0x01 /* Match source IP addr */
- #define IPADDR_DST 0x02 /* Match destination IP addr */
- #define IPADDR_SRC_INV 0x10 /* Negate the condition */
- #define IPADDR_DST_INV 0x20 /* Negate the condition */
- struct ipt_ipaddr {
- __u32 src, dst;
- };
- struct ipt_ipaddr_info {
- struct ipt_ipaddr ipaddr;
- /* Flags from above */
- __u8 flags;
- };
- #endif
- #include <stdbool.h>
- #include <stdio.h>
- #include <netdb.h>
- #include <string.h>
- #include <stdlib.h>
- #include <getopt.h>
- #include <iptables.h>
- #include <xtables.h>
- #include <linux/netfilter_ipv4/ipt_ipaddr.h>
- //./configure --prefix= ./install
- /*
- * ./install/sbin/iptables -m ipaddr -h
- */
- static void ipaddr_help(void)
- {
- printf (
- "IPADDR options:\n"
- "[!] --ipsrc <ip>\t\t The incoming ip addr matches.\n"
- "[!] --ipdst <ip>\t\t The outgoing ip addr matches.\n"
- "\n"
- );
- }
- static struct option ipaddr_opts[] = {
- { .name = "ipsrc", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "ipdst", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = 0 }
- };
- static void ipaddr_init(struct xt_entry_match *m)
- {
- /* Can't cache this
- *nfcache |= NFC_UNKNOWN;*/
- }
- __be32 in_aton(const char *str)
- {
- unsigned long l;
- unsigned int val;
- int i;
- l = 0;
- for (i = 0; i < 4; i++)
- {
- l <<= 8;
- if (*str != '\0')
- {
- val = 0;
- while (*str != '\0' && *str != '.' && *str != '\n')
- {
- val *= 10;
- val += *str - '0';
- str++;
- }
- l |= val;
- if (*str != '\0')
- str++;
- }
- }
- return htonl(l);
- }
- struct in_addr* dotted_to_addr(const char *arg)
- {
- struct in_addr * p;
- p = malloc(sizeof(struct in_addr));
- printf("%x\n",p);
- p->s_addr = in_aton(arg);
- return p;
- }
- static void parse_ipaddr(const char *arg, __u32 *ipaddr)
- {
- struct in_addr *ip;
- printf("in parse_ipaddr arg is %s",arg);
- ip = dotted_to_addr(arg);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Bad IP address `%s'\n", arg);
- *ipaddr = ip->s_addr;
- }
- static int ipaddr_parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_match **match)
- {
- struct ipt_ipaddr_info *info = (struct ipt_ipaddr_info *)(*match)->data /*NULL*/;
- printf("entered ipaddr_parse\n");
- switch(c) {
- case '1':
- if (*flags & IPADDR_SRC)
- xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Only use --ipsrc once!");
- *flags |= IPADDR_SRC;
- info->flags |= IPADDR_SRC;
- if (invert)
- info->flags |= IPADDR_SRC_INV;
- parse_ipaddr(argv[optind-1], &info->ipaddr.src);
- break;
- case '2':
- if (*flags & IPADDR_DST)
- xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Only use --ipdst once!");
- *flags |= IPADDR_DST;
- info->flags |= IPADDR_DST;
- if (invert)
- info->flags |= IPADDR_DST_INV;
- parse_ipaddr(argv[optind-1], &info->ipaddr.dst);
- break;
- default:
- return 0;
- }
- return 1;
- }
- static void ipaddr_final_check(unsigned int flags)
- {
- if (!flags)
- xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Invalid parameters.");
- }
- /*
- * Can't call it ipaddr, because
- * the main structure is already
- * called like that.
- */
- static void print_ipaddr(__u32 *ip_addr)
- {
- printf( "%u.%u.%u.%u ",
- ((unsigned char *)ip_addr)[0],
- ((unsigned char *)ip_addr)[1],
- ((unsigned char *)ip_addr)[2],
- ((unsigned char *)ip_addr)[3]
- );
- }
- static void ipaddr_print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
- {
- const struct ipt_ipaddr_info *info = (const struct ipt_ipaddr_info *)match->data;
- printf("entered ipaddr_print\n");
- if (info->flags & IPADDR_SRC) {
- printf("src IP ");
- if (info->flags & IPADDR_SRC_INV)
- printf("! ");
- print_ipaddr((__u32 *)&info->ipaddr.src);
- }
- if (info->flags & IPADDR_DST) {
- printf("dst IP ");
- if (info->flags & IPADDR_DST_INV)
- printf("! ");
- print_ipaddr((__u32 *)&info->ipaddr.dst);
- }
- }
- /*
- * iptables-saves
- */
- static void ipaddr_save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
- {
- const struct ipt_ipaddr_info *info = (const struct ipt_ipaddr_info *)match->data;
- printf("entered ipaddr_save\n");
- if (info->flags & IPADDR_SRC) {
- if (info->flags & IPADDR_SRC_INV)
- printf("! ");
- printf("--ipsrc ");
- print_ipaddr((__u32 *)&info->ipaddr.src);
- }
- if (info->flags & IPADDR_DST) {
- if (info->flags & IPADDR_DST_INV)
- printf("! ");
- printf("--ipdst ");
- print_ipaddr((__u32 *)&info->ipaddr.dst);
- }
- }
- static struct xtables_match ipaddr = {
- .family = NFPROTO_UNSPEC,
- .name = "ipaddr",
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct ipt_ipaddr_info)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_ipaddr_info)),
- .help = ipaddr_help,
- /// .init = ipaddr_init,
- .parse = ipaddr_parse,
- .final_check = ipaddr_final_check,
- .print = ipaddr_print,
- .save = ipaddr_save,
- .extra_opts = ipaddr_opts
- };
- void _init(void)
- {
- xtables_register_match(&ipaddr);
- }
- EXTRA_CFLAGS := -g -O2 ##Debug info .
- KVERS = $(shell uname -r)
- ifneq ($(KERNELRELEASE),)
- obj-m = ipaddr.o
- ipaddr-objs := ipt_ipaddr.o
- else
- KDIR := /lib/modules/$(KVERS)/build
- all:
- make -C $(KDIR) M=$(PWD) modules
- clean:
- rm -f *.ko *.o *.mod.o *.mod.c *.order *~ *.symvers
- endif