- 论坛徽章:
- 0
|
再次见识了内核的伟大,大半年不碰,忘记的一干二净!!!写netfilter,netlink不得不提的就是九贱和duanjigang了...
Linux 用户态与内核态的交互——netlink 篇
http://bbs.chinaunix.net/viewthread.php?tid=822500
netlink socket 编程之 why & how
http://linux.chinaunix.net/bbs/viewthread.php?tid=1031932&extra=page%3D1%26amp%3Bfilter%3Ddigest
有了上面两篇文章加kernel source基本上你可以干许多事了...
环境:
centos5.2 2.6.18
作用:
./user -i 禁止ping
./user -d ipaddr 禁止指定ip的tcp连接
iptables+netfilter这一套以前一直是限于理论层面,今天就自己实践了下.
我这里只是写我写程序的过程中遇到的问题,一些概念上的东东,上面两位大师已经写得很好了,我就不班门弄斧了.
- struct sock* netlink_kernel_create(int unit, unsigned int groups,
- void (*input)(struct sock *sk, int len),
- struct module *module)
-
复制代码
why&how那篇是:
- struct sock * netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
-
复制代码
取数据我这里传的是结构体
- nlh = (struct nlmsghdr*)skb->data;
- icmp_off = ((OWN *)NLMSG_DATA(nlh))->icmp_off;
- drop_ip = ((OWN *)NLMSG_DATA(nlh))->drop_ip;
-
复制代码
netlink主要就是create和取数据那个地方,我这里是看kernel source追寻到了,不同的版本可能不一样.
- nfho.hook = hook_func;
- nfho.hooknum = NF_IP_LOCAL_IN;
- nfho.pf = PF_INET;
- nfho.priority = NF_IP_PRI_FIRST;
- nf_register_hook(&nfho);
-
复制代码
想挂多个hook的话可以
- nf_register_hook(&nfho);
- nf_register_hook(&nfho1);
-
复制代码
也可以
- nf_register_hooks(opts, ARRAY_SIZE(opts));
-
复制代码
取头,可以去ip.h tcp.h等去找
好了废话了这么多,上代码了
内核态程序
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/skbuff.h>
- #include <linux/ip.h>
- #include <linux/in.h>
- #include <net/tcp.h>
- #include <net/icmp.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <net/sock.h>
- #include <net/netlink.h>
- #include "hook.h"
- static struct nf_hook_ops nfho;
- struct sock *nl_sk = NULL;
- EXPORT_SYMBOL_GPL(nl_sk);
- static int icmp_off = 0;
- static unsigned int drop_ip = 0;
- void input (struct sock* sk, int len)
- {
- struct sk_buff* skb = NULL;
- struct nlmsghdr* nlh = NULL;
- printk("net_link: data is ready to read.\n");
- while((skb = skb_dequeue(&sk->sk_receive_queue))!=NULL)
- {
- nlh = (struct nlmsghdr*)skb->data;
- icmp_off = ((OWN *)NLMSG_DATA(nlh))->icmp_off;
- drop_ip = ((OWN *)NLMSG_DATA(nlh))->drop_ip;
- }
- return;
- }
- static int test_netlink(void) {
- nl_sk = netlink_kernel_create(NETLINK_TEST, 0, input, THIS_MODULE);
- if (!nl_sk) {
- printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
- return -EIO;
- }
- printk("net_link: create socket ok.\n");
- return 0;
- }
- unsigned int hook_func(unsigned int hooknum,
- struct sk_buff **skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
- {
- struct sk_buff *sb = *skb;
- struct iphdr *iph ;
- iph = ip_hdr(sb);
- switch(iph->protocol)
- {
- case IPPROTO_ICMP:{
- struct icmphdr _icmph;
- struct icmphdr* ich;
- ich = skb_header_pointer(sb, iph->ihl*4, sizeof(_icmph), &_icmph);
- printk("icmp type %u\n", ich->type);
- if(icmp_off == 1)
- {
- printk("now we drop icmp from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
- return NF_DROP;
- }
- break;
- }
- case IPPROTO_TCP:{
- struct tcphdr* th = NULL;
- struct tcphdr _tcph;
- th = skb_header_pointer(sb, iph->ihl*4, sizeof(_tcph), &_tcph);
- if(th == NULL)
- {
- printk("get tcp header error\n");
- return NF_DROP;
- }
- //unsigned int sip = ntohs(th->source);
- printk("saddr:%d.%d.%d.%d,sport:%u\n", NIPQUAD(iph->saddr),ntohs(th->source));
- printk("daddr:%d.%d.%d.%d,dport:%u\n", NIPQUAD(iph->daddr),ntohs(th->dest));
- if(iph->saddr ==drop_ip)
- {
- printk("now we drop tcp from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
- return NF_DROP;
- }
- break;
- }
- default:
- break;
- }
- return NF_ACCEPT;
- }
- static int __init hook_init()
- {
- printk("insmod hook test!\n");
- test_netlink();
- nfho.hook = hook_func;
- nfho.hooknum = NF_IP_LOCAL_IN;
- nfho.pf = PF_INET;
- nfho.priority = NF_IP_PRI_FIRST;
-
- nf_register_hook(&nfho);
- return 0;
- }
- static void __exit hook_exit()
- {
- printk("rmmod hook test!\n");
- nf_unregister_hook(&nfho);
- if (nl_sk != NULL){
- sock_release(nl_sk->sk_socket);
- }
- }
- module_init(hook_init);
- module_exit(hook_exit);
-
复制代码
用户态:
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/types.h>
- #include <string.h>
- #include <asm/types.h>
- #include <linux/netlink.h>
- #include <linux/socket.h>
- #include <getopt.h>
- #include "hook.h"
- #define MAX_PAYLOAD 1024 /* maximum payload size*/
- struct sockaddr_nl src_addr, dest_addr;
- struct nlmsghdr *nlh = NULL;
- struct iovec iov;
- int sock_fd;
- struct msghdr msg;
- struct option longopts[] =
- {
- {"icmp",no_argument, NULL, 'i'},
- {"help",no_argument, NULL, 'h'},
- {"drop",required_argument, NULL, 'd'},
- {0,0,0,0}
- };
- void print_help(char* str)
- {
- fprintf(stderr,"%s --icmp(-i)\n",str);
- fprintf(stderr,"%s --drop(-d)\n",str);
- fprintf(stderr,"eg:\n%s -i -d 202.114.85.105\n",str);
- }
- void init_own(OWN** own)
- {
- *own = (OWN*)malloc(sizeof(OWN));
- (*own)->icmp_off = 0;
- (*own)->drop_ip = 0;
- }
- int main(int argc, char* argv[])
- {
- int c;
- OWN* own = NULL;
- init_own(&own);
- while((c=getopt_long(argc, argv, "hid:", longopts, NULL))!=-1)
- {
- switch(c)
- {
- case 'i':
- {
- own->icmp_off = 1;
- break;
- }
- case 'd':
- {
- own->drop_ip = inet_addr(optarg);
- break;
- }
- case 'h':
- {
- print_help(argv[0]);
- return -1;
- }
-
- default:
- break;
- }
- }
-
- sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
- memset(&msg, 0, sizeof(msg));
- memset(&src_addr, 0, sizeof(src_addr));
- src_addr.nl_family = AF_NETLINK;
- src_addr.nl_pid = getpid(); /* self pid */
- src_addr.nl_groups = 0; /* not in mcast groups */
- bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
- memset(&dest_addr, 0, sizeof(dest_addr));
- dest_addr.nl_family = AF_NETLINK;
- dest_addr.nl_pid = 0; /* For Linux Kernel */
- dest_addr.nl_groups = 0; /* unicast */
- nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
- /* Fill the netlink message header */
- nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
- nlh->nlmsg_pid = getpid(); /* self pid */
- nlh->nlmsg_flags = 0;
- /* Fill in the netlink message payload */
- printf("%d, %d\n", own->icmp_off, own->drop_ip);
- memcpy(NLMSG_DATA(nlh),own ,sizeof(OWN));
- iov.iov_base = (void *)nlh;
- iov.iov_len = nlh->nlmsg_len;
- msg.msg_name = (void *)&dest_addr;
- msg.msg_namelen = sizeof(dest_addr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- printf(" Sending message. ...\n");
- sendmsg(sock_fd, &msg, 0);
- close(sock_fd);
- free(own);
- return 0;
- }
复制代码
Makefile 头文件
- hook.h
- #define NETLINK_TEST 21
- typedef struct my
- {
- int icmp_off;
- unsigned int drop_ip;
- }OWN;
- makefile:
- obj-m += hook.o
- KDIR := /lib/modules/$(shell uname -r)/build
- all:
- make -C $(KDIR) M=$(shell pwd) modules
- gcc -Wall -o user user.c
- clean:
- make -C $(KDIR) M=$(shell pwd) clean
- rm -f *odule* user
复制代码
usage:
1.make
2. insmod hook.ko (建议tail -f /var/log/messages查看是否success尤其是netlink create是否成功)
3.默认你是可以ping, 和tcp得(我实验室只有两台机子A 202.114.85.105)
4. ./user -i -d 202.114.85.105 (A机不能ping和ftp B)
5../user (取消限制了,可以ping和ftp B)
再次试验成功上传代码:
[ 本帖最后由 ubuntuer 于 2009-9-9 20:23 编辑 ] |
|