在openSuSE上搭建好实验环境之后,继续内核模块的实验。这次做的是一个简单的网络地址转换(NAT)。
在负载均衡器(LB)上,将目的地址是192.168.99.102的数据包(skb)的目的地址改为192.168.99.101。
没有做连接跟踪、没有将192.168.99.101返回的原地址改成192.168.99.102,一切从简!
只能拿ping做实验。
1、源代码:simpNat.c
#include <linux/kernel.h>
#include <linux/tcp.h> /* for tcphdr */
#include <net/ip.h>
#include <net/tcp.h> /* for csum_tcpudp_magic */
#include <net/udp.h>
#include <net/icmp.h> /* for icmp_send */
#include <net/route.h> /* for ip_route_output */
#include <net/ipv6.h>
#include <net/ip6_route.h>
#include <linux/icmpv6.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/ip_vs.h>
MODULE_LICENSE("GPL");
/* This is the structure we shall use to register our function */
static struct nf_hook_ops nfho;
/* IP address we want to Nat*/
static unsigned char *nat_ip = "/xc0/xa8/x63/x65"; /* 192.168.99.101 */
static unsigned char *org_ip = "/xc0/xa8/x63/x66"; /* 192.168.99.102 */
/* This is the hook function itself */
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;
if(!sb) return NF_ACCEPT;
iph = ip_hdr(sb);
if(!iph) return NF_ACCEPT;
if (iph->daddr == *(unsigned int *)org_ip){
iph->daddr= *(unsigned int *)nat_ip;
ip_send_check(iph);
skb->local_df = 1;
printk("Nat: %d.%d.%d.%d To:%d.%d.%d.%d/n",
*org_ip, *(org_ip + 1), *(org_ip + 2),*(org_ip + 3),
*nat_ip, *(nat_ip + 1), *(nat_ip + 2),*(nat_ip + 3));
return NF_ACCEPT;
}else{
printk("Not NAT this ip/n");
return NF_ACCEPT;
}
}
/* Initialisation routine */
int init_module()
{
/* Fill in our hook structure */
nfho.hook = hook_func; /* Handler function */
nfho.hooknum = NF_INET_PRE_ROUTING; /* First hook for IPv4 */
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST; /* Make our function first */
nf_register_hook(&nfho);
pr_info("simpNat install into kernel!/n");
return 0;
}
/* Cleanup routine */
void cleanup_module()
{
nf_unregister_hook(&nfho);
pr_info("simpNat removed from kernel!/n");
}
2、Makefile:
obj-m +=simpNat.o
all:
make -C /lib/modules/`uname -r`/build M=`pwd`
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
install:
/sbin/insmod simpNat.ko
remove:
/sbin/rmmod simpNat
3、编译:
make
4、安装模块:
make install
5、测试:
5.1、在客户端(Client)上
ping 192.168.99.102
返回如下字样:
PING vm02 (192.168.99.102) 56(84) bytes of data.
64 bytes from vm01 (192.168.99.101): icmp_seq=1 ttl=63 time=3.96 ms
64 bytes from vm01 (192.168.99.101): icmp_seq=2 ttl=63 time=0.286 ms
64 bytes from vm01 (192.168.99.101): icmp_seq=3 ttl=63 time=0.271 ms
64 bytes from vm01 (192.168.99.101): icmp_seq=4 ttl=63 time=0.286 ms
64 bytes from vm01 (192.168.99.101): icmp_seq=5 ttl=63 time=0.300 ms
5.2、在负载均衡器(LB)查看/var/log/messages,有如下字样:
Feb 25 14:47:42 vmLB kernel: [ 5700.674794] Nat: 192.168.99.102 To:192.168.99.101
Feb 25 14:47:42 vmLB kernel: [ 5700.674951] Not NAT this ip
Feb 25 14:47:43 vmLB kernel: [ 5701.674823] Nat: 192.168.99.102 To:192.168.99.101
Feb 25 14:47:43 vmLB kernel: [ 5701.674992] Not NAT this ip
6、卸载模块:
make remove