- 论坛徽章:
- 0
|
我是一下系统管理员,对写代码基本是不熟悉。根据网上的例子捣鼓了一个程序,想实现一个功能:
把从192.168.1.148 发到192.168.5.148 的dns请求转发到 192.168.1.24
简单实现一个dnat+snat功能。我只是在prerouting和postrouting的位置修改了ip 地址直接发出去。
通过tcpdump抓包,发现包都转发成功了,但是用dig或者nslookup却得不到dns查询结果。很奇怪。
代码如下:
//nethook.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <linux/udp.h>
//
/* 从192.168.1.148 到 192.168.5.148:53 转到 192.168.1.20:53
struct tcphdr *thead;
thead = (void *) iph + iph->ihl * 4;
*/
static struct nf_hook_ops nfho,nfho2;
__be32 gwip=0x9405A8C0;
__be32 dnsip=0x0101A8C0;
__be32 serverip=0x1801A8C0;
__be32 clientip=0x9401A8C0;
//prerouting
unsigned int hook_func(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph = NULL;
iph = ip_hdr(skb);
struct udphdr *udph;
udph = (void *) iph + iph->ihl * 4;
if (iph->protocol != IPPROTO_UDP)
{
return NF_ACCEPT;
}
if (udph->dest != 0x3500 &&udph->source != 0x3500 )
{
return NF_ACCEPT;
}
// 客户端到服务器
// dstip: 192.168.5.148
// dstport: 53
printk("dnat前%pI4:%x -> %pI4:%x\t",&iph->saddr,udph->source,&iph->daddr,udph->dest);
if(iph->saddr == clientip){
iph->daddr = serverip;
ip_send_check(iph);
printk("dnat后 %pI4:%x -> %pI4:%x\n",&iph->saddr,udph->source,&iph->daddr,udph->dest);
return NF_ACCEPT;
}
// 服务器到客户端
// dstip: 192.168.5.148
// srcport: 53
if(iph->saddr == serverip){
iph->daddr = clientip;
ip_send_check(iph);
printk("dnat后 %pI4:%x -> %pI4:%x\n",&iph->saddr,udph->source,&iph->daddr,udph->dest);
return NF_ACCEPT;
}
printk("dnat 没修改%pI4 -> %pI4\n",&iph->saddr,&iph->daddr);
return NF_ACCEPT;
}
//postrouting
unsigned int hook_func2(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph = NULL;
//192.168.1.20
//192.168.1.20
iph = ip_hdr(skb);
if (iph->protocol != IPPROTO_UDP)
{
return NF_ACCEPT;
}
struct udphdr *udph;
udph = (void *) iph + iph->ihl * 4;
if (udph->dest != 0x3500 &&udph->source != 0x3500 )
{
return NF_ACCEPT;
}
if (iph->saddr == dnsip ||iph->daddr == dnsip){
return NF_ACCEPT;
}
//
printk("snat前 %pI4:%x -> %pI4:%x\t",&iph->saddr,udph->source,&iph->daddr,udph->dest);
if(iph->saddr == clientip||iph->saddr== serverip){
iph->saddr = gwip;
ip_send_check(iph);
printk("snat后 %pI4:%x -> %pI4:%x\n",&iph->saddr,udph->source,&iph->daddr,udph->dest);
return NF_ACCEPT;
}
printk("snat 没修改%pI4 -> %pI4\n",&iph->saddr,&iph->daddr);
return NF_ACCEPT;
}
static int __init init_nethook(void)
{
nfho.hook = hook_func;
nfho.hooknum = NF_INET_PRE_ROUTING;
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST;
nfho2.hook = hook_func2;
nfho2.hooknum = NF_INET_POST_ROUTING;
nfho2.pf = PF_INET;
nfho2.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
nf_register_hook(&nfho2);
return 0;
}
static void __exit exit_nethook(void)
{
nf_unregister_hook(&nfho);
nf_unregister_hook(&nfho2);
}
module_init(init_nethook);
module_exit(exit_nethook);
|
|