问题描述与解决方案
1.配置两条NAT规则
2.编写一个Netfilter HOOK
3.使用专门的虚拟设备
static netdev_tx_t sdnat_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sdnat_struct *sdnat = netdev_priv(dev);
unsigned int flags = sdnat->flags;
struct nat_entry *entry;
entry = find_sdnat_policy(skb, flags);
if (unlikely(!entry)) {
goto xmit;
}
if (flags & SNAT) {
do_trans_src(entry, skb);
} else if (flags & DNAT) {
do_trans_dst(entry, skb);
}
// 此时skb的dst为将数据包导入NAT设备的dst_entry,
// 为了防止循环路由,将其drop,NAT已经完成,已经没有用了
skb_dst_drop(skb);
// 清除mark,因为一般通过mark策略路由将数据包导入NAT设备
// 这也是为了防止循环路由
skb->mark = 0;
xmit:
netif_rx_ni(skb);
drop:
kfree_skb(skb);
return NETDEV_TX_OK;
}
struct nat_entry {
struct hlist_node hash_list;
__be32 key1; //对于SNAT即原始IP地址,对于DNAT即要转换到的IP地址
__be32 key2; //对于SNAT即要转换到的IP地址,对于DNAT即原始IP地址
__be32 hash; /数据包源IP或者目标IP的jhash_2words值
int flags;
};
static u32 keys_get_hash(__be32 key)
{
return jhash_2words(key, 0x01, 0x0);
}
struct sdnat_struct {
int flags;
struct net_device *dev;
struct hlist_head entrys[1024];
};