Linux Stateless无状态NAT-使用TC来配置
如果想在Linux上配置NAT,那么大家众所一言的就是使用iptables的NAT表来配置,iptables提供了灵活丰富的配置来配置SNAT和DNAT,然而我们知道iptables的NAT依赖了ip_conntrack,也就是说,凡是一个命中了NAT表规则的流就会有一条连接追踪生成,由于ip_conntrack追踪了所有的数据包,因此当有大量连接经过了本地设备时,ip_conntrack空间将被撑满,这个在接入区特别容易重现,在骨干网反而不容易重现,然而骨干网却又几乎不可能使用Linux。
如果Linux支持无状态的NAT就好了,这样就不怕conntrack爆满了,也不会因为conntrack查找而深深影响效率。然而如此的无状态NAT也有自己的缺点,那就是你必须为返回流量显式配置NAT规则,这样配置规则就整整增加了一倍,毕竟是无状态的嘛,NAT工作在无状态的IP层,而IP层是单向的。iptables正是依赖了ip_conntrack才能自动的转换返回包的地址信息的,因为ip_conntrack根据五元素追踪了每一个IP流。
本文不准备详述Linux的TC机制,仅仅解析其配置NAT的方法。具体来讲,NAT分为SNAT和DNAT,如果应用在网络接口即网卡上而不是应用在协议栈的Netfilter链上的话,SNAT将绑定在egress方向,而DNAT将绑定在ingress方向。需要注意的是,由于基于TC的NAT是无状态的,因此当你配置了ingress的DNAT之后,必须在相反的egress方向显式配置SNAT,你的配置量因此将增加一倍。以下我们先来配置ingress上的DNAT规则,效果是将访问本机的一个网卡上的一个IP装换为该网卡上的另一个IP地址。
IP地址规划:eth2上的两个IP:192.168.40.249/24 12.12.12.5/24
和往常一样,首先建立一个规则队列,也就是qdisc:
tc qdisc add dev eth2 ingress handle ffff