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でさえ機能しませんでした。
あなたのコメントと助けをどうもありがとう。
トーマス