- 论坛徽章:
- 0
|
linux 64位下的netfilter 与 32位下的netfilter 有什么不同
在写一个基于netfilter 进行端口nat的程序。在32位的系统上可以正常使用。但在64位的系统就没法实现功能。应用环境如下
client----->server[(80端口)-----(81端口)]
在32位上可以实现client nc server 80 数据被转到81端口。即server的81端口可与和client通迅。
但在64位系统上只能实现 client 向server的81发数据包。而server81没法向client回送数据包。
程序如下:
请大家帮忙看看。
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/checksum.h>
#include <net/tcp.h>
#include <net/ip.h>
MODULE_LICENSE("GPL");
static char * markdip= "192.168.0.155";
static unsigned short markdport=80;
static unsigned short markdport2=81;
module_param(markdport,ushort,S_IRUSR);
module_param(markdport2,ushort,S_IRUSR);
module_param(markdip,charp,S_IRUSR);
#define PRINT(fmt,args...) printk("Marker: " fmt, ##args)
unsigned int hook_mark_packet_in(unsigned int hookunm,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
struct tcphdr *tcph;
int datalen;
iph=(struct iphdr *)(*skb)->nh.iph;
tcph=(struct tcphdr*)((__u32 *)iph+iph->ihl);
/*PRINT("IP: [%u.%u.%u.%u]:%U-->[%u.%u.%u.%u]",NIPQUAD(iph->saddr),NIPQUAD(iph->daddr));*/
if(iph->daddr == in_aton(markdip))
{
if(iph->protocol==6)
{
if(ntohs(tcph->dest) == markdport)
{
tcph->dest = htons(markdport2);
ip_send_check(iph); /*重新计算IP包头校验和,这一步貌似并不需要,因为IP包校验和只与IP包头有关*/
datalen = (*skb)->len - iph->ihl*4;
tcph->check = 0;
/*重新计算TCP包头校验和,这一步很需要,否则会被接收端丢弃,TCP包校验和不仅涉及包头也包括payload*/
tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr,
csum_partial((char *)tcph, datalen, 0));
PRINT("IN: [%u.%u.%u.%u]:%u-->[%u.%u.%u.%u]:%u, %u, tcp_check:%u\n",
NIPQUAD(iph->saddr),ntohs(tcph->source),NIPQUAD(iph->daddr),ntohs(tcph->dest), ntohs(tcph->res1),ntohs(tcph->check));
}
}
}
return NF_ACCEPT;
}
unsigned int hook_mark_packet_out(unsigned int hookunm,struct sk_buff **skb,
const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
struct tcphdr *tcph;
int datalen;
iph=(struct iphdr *)(*skb)->nh.iph;
tcph=(struct tcphdr*)((__u32 *)iph+iph->ihl);
if(iph->protocol==6)
{
if(ntohs(tcph->source) == markdport2)
{
tcph->source = htons(markdport);
ip_send_check(iph); /*重新计算IP包头校验和,这一步貌似并不需要,因为IP包校验和只与IP包头有关*/
datalen = (*skb)->len - iph->ihl*4;
tcph->check = 0;
/*重新计算TCP包头校验和,这一步很需要,否则会被接收端丢弃,TCP包校验和不仅涉及包头也包括payload*/
tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr,
csum_partial((char *)tcph, datalen, 0));
}
}
return NF_ACCEPT;
}
static struct nf_hook_ops nfho_in;
static struct nf_hook_ops nfho_out;
static int init_marker(void)
{
nfho_in.hook=hook_mark_packet_in;
nfho_in.hooknum=NF_IP_LOCAL_IN;
nfho_in.pf=PF_INET;
nfho_in.priority=NF_IP_PRI_LAST;
nf_register_hook(&nfho_in);
nfho_out.hook=hook_mark_packet_out;
nfho_out.hooknum=NF_IP_LOCAL_OUT;
nfho_out.pf=PF_INET;
nfho_out.priority=NF_IP_PRI_FIRST+6;
nf_register_hook(&nfho_out);
return 0;
}
static void exit_marker(void)
{
nf_unregister_hook(&nfho_in);
nf_unregister_hook(&nfho_out);
}
module_init(init_marker);
module_exit(exit_marker); |
|