User netfilter's kernel module hook that does NAPT in Linux 2.6.
Valery Voevudsky
vvoevudsky at borderware.com
Mon Aug 28 23:11:37 CEST 2006
Hello all:
I have the following challenge that I do not know how to overcome.
I am porting a kernel module from FreeBSD to Linux 2.6 using the
netfilter paradigm.
Actually it is a kernel module with the NF_IP_PRE_ROUTING hook that does
NAPTing on its own: replaces source and destination addresses and ports,
recalculates checksums and returns NF_ACCEPT. A have attached the source
code below.
The ethereal shows that the checksums for the IP/UDP headers are correct
so I would expect that the corrected packet with the new destination
IP:port will be sent accordingly by the netfilter. But actually the
packet does not leave my box (the post-routing hook shows that).
In the log I see something like this:
martian source 10.1.35.110 from 10.1.253.143, on dev eth1
ll header: 00:0a:5e:53:7a:8d:00:0e:08:da:f2:da:08:00
I need your help guys. Actually I need a working tutorial and source
example that does the real NAT/NAPT. Most of tutorial that I've read are
related to Linux 2.4. The documentation for 2.6 is not verbose as I
would expect.
Thanks in advance,
Valery Voevudsky
===========================================================================
This is my version of linux:
~$ uname -a
Linux vvoevudsky-desktop 2.6.15.7-ubuntu1 #2 SMP PREEMPT Mon Aug 28
12:52:32 EDT 2006 i686 GNU/Linux
============================================================================
This is the simplified source code of my module:
int rtp_firewall_init(void)
{
int ret = -1;
pre_netfilter_ops.hook = pre_firewall_hook;
pre_netfilter_ops.owner = THIS_MODULE,
pre_netfilter_ops.pf = PF_INET;
pre_netfilter_ops.hooknum = NF_IP_PRE_ROUTING;
pre_netfilter_ops.priority = NF_IP_PRI_FIRST;
ret = nf_register_hook(&pre_netfilter_ops);
}
unsigned int pre_firewall_hook(unsigned int hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff*))
{
int ret = -1;
struct udphdr * udph = NULL;
struct iphdr * iph = NULL;
sock_buff = *skb;
iph = sock_buff->nh.iph;
udph = (struct udphdr *)
(sock_buff->data + (sock_buff->nh.iph->ihl *4));
if(iph->protocol != IPPROTO_UDP)
{
return NF_ACCEPT;
}
// So this is the UDP protocol
// NAPTing:
iph->saddr = 'new source IP-address';
iph->daddr = 'new destination IP-address';
udph->source = 'new source port';
udph->dest = 'new destination port';
// Re-calculate the checksum for ip header
if (iph->check)
{
iph->check = 0; // required by ip_fast_csum()!
iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);
}
// Re-calculate the checksum for udp header
if (udph->check != 0)
{
udph->check = 'some checksum routine';
}
return NF_ACCEPT;
} // pre_firewall_hook
More information about the netfilter-devel
mailing list