Chinaunix
标题:
求助,netfilter实现两块网卡之间的流量转发
[打印本页]
作者:
Backbp
时间:
2015-03-24 16:43
标题:
求助,netfilter实现两块网卡之间的流量转发
情况是这样的,主机上有两块网卡(eth0和eth1),我想实现的功能就是:把从eth0出去的数据包复制一份发给eth1。
遇到的问题是我把hook挂在LOCAL_OUT,然后将eth0的包复制并修改目标MAC,但是总是死机,我试过了,导致死机的就是红色那部分,但是不知道为什么,求告知啊
int copy_forward(struct sk_buff * skb, struct iphdr * iph)
{
int tot_len, iph_len;
struct ethhdr * mach = NULL;
struct net_device * dev = NULL;
int ret = 0;
iph_len = ip_hdrlen ( skb );
tot_len = ntohs ( iph->tot_len );
struct sk_buff * new_skb;
if( !(new_skb = skb_copy(skb, GFP_ATOMIC)) )
{
printk ("skb_copy failed");
return -1;
}
dev = dev_get_by_name ( &init_net, _IF_ETH1_ );
new_skb->dev = dev;
skb_push ( new_skb, ETHALEN );
mach = eth_hdr ( new_skb );
memcpy (mach->h_source, mac_src, ETH_ALEN);
mach->h_proto = __constant_htons (ETH_P_IP);
memcpy ( mach->h_dest, mac_dst, ETH_ALEN );
ret = dev_queue_xmit ( new_skb );
if ( ret < 0 )
{
dev_put ( dev );
return -1;
}
dev_put ( dev );
return 0;
}
unsigned int pkt_filter ( unsigned int hooknum, struct sk_buff * __skb,
const struct net_device * in, const struct net_device * out,
int ( *okfn ) ( struct sk_buff * ) )
{
struct sk_buff * skb;
struct iphdr * iph;
struct tcphdr *tcph;
int tot_len, iph_len, tcph_len;
int payload_len;
unsigned char * payload = NULL;
int mark = NO_ACTION;
skb = __skb;
if ( skb == NULL ) { return NF_ACCEPT; }
iph = ip_hdr ( skb );
if ( iph == NULL ) { return NF_ACCEPT; }
iph_len = ip_hdrlen ( skb );
tot_len = ntohs ( iph->tot_len );
if ( tot_len <= 20 ) { return NF_ACCEPT; }
if( !(memcmp(out->name, _IF_ETH0_, sizeof(_IF_ETH0_)) == 0) )
{
return NF_ACCEPT;
}
switch ( iph->protocol )
{
case IPPROTO_TCP:
{
skb_pull(skb, iph_len);
skb_reset_transport_header(skb);
tcph = tcp_hdr ( skb );
if(tcph->dest == htons(22) || tcph->source == htons(22))
{
skb_push(skb, iph_len);
return NF_ACCEPT;
}
else
{
skb_push(skb, iph_len);
mark = COPY;
}
break;
}
default:
{
break;
}
}
switch ( mark )
{
case COPY:
{
if( -1 == copy_forward(skb, iph) )
{
printk_0 ("Packet copy and forward failed");
}
break;
}
default:
break;
}
return NF_ACCEPT;
}
static int __init init ( void )
{
nfho_filter.hook = pkt_filter;
//nfho_filter.hooknum = NF_INET_PRE_ROUTING;
//nfho_filter.hooknum = NF_INET_POST_ROUTING;
//nfho_filter.hooknum = NF_INET_FORWARD;
nfho_filter.hooknum = NF_INET_LOCAL_OUT;
nfho_filter.pf = PF_INET;
//nfho_filter.priority = NF_IP_PRI_CONNTRACK+1;
nfho_filter.priority = NF_IP_PRI_FIRST+1;
nf_register_hook ( &nfho_filter );
return 0;
}
static void __exit fini ( void )
{
nf_unregister_hook ( &nfho_filter );
}
module_init ( init );
module_exit ( fini );
作者:
魔鬼的惊叹
时间:
2015-03-24 20:25
我说的不一定对,只修改mac地址应该还不行吧,我觉得你还得修改Ip地址,两个网卡,两个IP,另外,如果传输层是udp的话,可能过程会简单些
作者:
nswcfd
时间:
2015-03-26 09:24
本帖最后由 nswcfd 于 2015-03-26 09:39 编辑
local out的位置skb.mac还没有初始化呢。
也就是说,在这个上下文里,eth_hdr返回值是没有意义的。
试试在pull(ETH_ALEN)和eth_hdr()之间加上一句skb_reset_mac_hdr()。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2