使用netfilter框架在OUTPUT链中实现DNAT

问题描述 投票:0回答:1

我正在尝试在 OUTPUT 链中实现 DNAT,但数据包未到达目标目的地。我想做的是,例如如果消息发送到192.168.56.17,我将其更改为192.168.56.1,并且该ip在我的网络中,因此应该发送。

代码是:

#include <linux/module.h>       //needed for every module
#include <linux/kernel.h>

#include <linux/types.h>        //u_int && co
#include <linux/skbuff.h>       //struct sk_buff
#include <linux/in.h>           //basic internet shiat
#include <linux/ip.h>           //protocol headers
#include <linux/tcp.h>
#include <linux/netfilter.h>        //need this for register_ 
#include <linux/netfilter_ipv4.h>   //..
#include <linux/netdevice.h>        //struct net_device 

#define NR_OF_VLANS 3
#define MAX_UNIQUE_ADDRS 16
#define IFACE0 "vboxnet0"
#define IFACE1 "eth0"
#define IFACE2 "eth0.1"
#define INIT_ADDR 0x0038A8C0

MODULE_AUTHOR("tomak");
MODULE_DESCRIPTION("dnat");

static struct nf_hook_ops NF_hook_out;

static int change_ip_out(struct iphdr* iph)
{
    //examine last byte of dest ip addr
    __be32 daddr = iph->daddr;
    //Note: big endian => we need first byte of the structure
    __be32 offset = daddr - INIT_ADDR;
    //printk(KERN_INFO "be32 offset %pI4\n", &(offset));
    __u32 uOffset = be32_to_cpu(offset);
    //printk(KERN_INFO "offset: %d", uOffset);
    __u32 uRemainder = uOffset % MAX_UNIQUE_ADDRS ;
    __be32 remainder = cpu_to_be32(uRemainder);
    //printk(KERN_INFO "remainder is: %pI4\n", &remainder);
    int division = (int)(uOffset / MAX_UNIQUE_ADDRS);

    //change ip and put on right iface
    iph->daddr = INIT_ADDR + remainder;
    printk(KERN_INFO "OUT changed daddr to %pI4\n", &(iph->daddr));

    if (division == 0) {
        return NF_ACCEPT;
    }
    return NF_REPEAT;
}

u_int hook_fcn_out( u_int hooknum,          //the hook number  (linux/netfilter_ipv4.h)
                struct sk_buff **skpp,      //pointer to a pointer with an sk_buff(mad ****) (linux/skbuff.h)
                const struct net_device *in,    //only valid for recieved
                const struct net_device *out,   //only valid for outgoing  (linux/netdevice.h)
                int (*okfn)(struct sk_buff *))  //called from net/core/netfilter.c ??
{   
    int result;
    int i = 0;
    int max_addrs = MAX_UNIQUE_ADDRS * NR_OF_VLANS;
    __be32 test_addr[max_addrs];                        //addresses to check
    struct iphdr* iph = ip_hdr(skpp);                   //getting ip header

    //addresses for detection
    __be32 addr = INIT_ADDR;
    for(i = 0; i < max_addrs; i++){
        test_addr[i] = addr;
        addr = addr + 0x01000000;     //+1
    }
    //detecting ips
    for(i = 0; i < max_addrs; i++){
        if(memcmp(&(iph->daddr),&test_addr[i], sizeof(test_addr[0])) == 0) {
            printk(KERN_INFO "OUT detected message to address %pI4\n", &(iph->daddr));
            printk(KERN_INFO "OUT message detected to interface %s\n", out->name);
            result = change_ip_out(iph);
            return result;
        }
    }
    /* printk(KERN_INFO "Detected output message to daddr: %pI4\n", &(iph->daddr));
    printk(KERN_INFO "Message detected for interface: %s\n", out->name); */

    return NF_ACCEPT; 
}

int init_module(void)
{   
    printk(KERN_DEBUG "nat_up\n");

    NF_hook_out.hook = hook_fcn_out;
    NF_hook_out.hooknum = NF_INET_LOCAL_OUT;
    NF_hook_out.pf = PF_INET;
    NF_hook_out.priority = NF_IP_PRI_NAT_DST;

    //register hook functions
    nf_register_hook(&NF_hook_out);

    return 0;
}

void cleanup_module(void)
{   
    printk(KERN_DEBUG "nat_down\n");
    nf_unregister_hook(&NF_hook_out);
}

有谁知道问题出在哪里。我的猜测是优先级,但即使 NF_INET_PRI_FIRST 也不起作用。

非常感谢您的评论和帮助。

托马斯

hook nat netfilter
1个回答
0
投票

你解决了吗?我也有同样的问题

© www.soinside.com 2019 - 2024. All rights reserved.