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でさえ機能しませんでした。

あなたのコメントと助けをどうもありがとう。

トーマス

4

0 に答える 0