标签:
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; }
我使用一个nat_entry来保存每一条规则:
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]; };
我比較喜欢使用procfs作为用户接口,由于它方便shell操作:
echo +192.168.1.1 9.24.100.1 >/proc/net/nat
上面的命令运行后,将会在两块网卡共享的hash表中加入一个nat_entry,key1为192.168.1.1。key2为9.24.100.1。在SNAT网卡设备中,将会用skb的iph->saddr做hash后查表匹配其key1,取出key2作为要转换的IP地址,在DNAT网卡设备中,将会用skb的iph->daddr做hash后查表匹配key2,取出key1作为要转换到的IP地址。
假设想删除一条规则,那么就运行:
echo -192.168.1.1 9.24.100.1 >/proc/net/nat
策略路由规则例如以下:
ip rule add iif $内网口 table snat
ip rule add iif $外网口 table dnat
ip route add 0.0.0.0/0 dev snat0 table snat
ip route add 0.0.0.0/0 dev dnat0 table dnat
依靠路由来做是否要进行NAT的推断,是不是更加高效些呢?而不再须要通过Netfilter模块去匹配每个数据包了。也不须要折腾低效率的ip_conntrack了。值得注意的是,sdnat设备的xmit函数终于运行了一个netif_rx_ni这相当于将数据包又一次注入其本身,此时数据包的iif将不再是内网口或者外网口了,而是实实在在的sdant虚拟网卡设备,因此数据包再次到达路由模块的时候将不会再次进入sdnat设备。
我以前写过几篇关于在路由项中保存信息。然后通过查路由表的方式获取信息的技巧。当中使用了自定义的“路由表”。查询方式依旧是最长前缀匹配法,仅仅是路由项中保存的东西变了。在本文中,我给出的是使用Linux原生的路由表(不是自定义的)+自定义的虚拟网卡设备实现数据包过滤的思想,依照这种思想,iptables的每个target就是一个虚拟网卡设备,每一系列的matches就是一条路由。该路由的路由项就是将数据包导入相应的虚拟网卡设备,路由的方式来匹配数据包将比Netfilter的方式高效,由于它使用了hash/trie这类高效的数据结构。而不是像Netfilter那样遍历好几层的链表。
其实,这种思想非常新吗?不!
路由项不是有unreachable或者blackhole吗?它们不正是iptables的REJECT和DROP么?
标签:
原文地址:http://www.cnblogs.com/mengfanrong/p/5212580.html