背景
在iptable/ip6table上可以在nat table上完成SNAT和DNAT操作。SNAT指将匹配ip包的源地址进行修改,DNAT指将匹配ip包的目的地址进行修改。
- SNAT 当在内网主机需要访问公网(internet)时刻,在防火墙上就会进行SNAT操作,出防火墙时刻ip报文的源地址被转换为防火墙的地址。
- DNAT 同样如果公网要访问内网的主机,它只能访问到防火墙,防火墙完成DNAT转换,将IP报文目标地址转换为防火墙在内网的地址再将ip包转发到小网上。
在iptables命令上,SNAT书写规则需要写下SNAT转换的目标地址,这里必须明确写出自己需要转换成的地址
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j snat –to-source 192.168.5.3-192.168.5.5
但是在某些场合,iptable规则编写的时候源ip地址并不固定或可获取。那么此时Linux引入了masquerade动作,这个规则的意思就是Ip包从哪个interface出去,那么src ip就转换为此interface的ip地址。
那么当一个interface上有多个ip地址的时候怎么办呢?例如下面的接口eth0有两个相同网段的ip地址,那么masquerade会选择哪一个ip作为源ip地址呢?例如下面的情况
$iptables -t nat -A POSTROUTING -o eth0 -j masquerade
$ip addr show dev eth0
eth0:<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 00:e0:4c:9c:13:b7 brd ff:ff:ff:ff:ff:ff
inet 192.168.120.156/23 brd 192.168.120.255 scope global eth0
inet 192.168.120.157/23 brd 192.168.120.255 scope global eth0
多ip时刻masquerade 源ip选择规则
总体上来讲,masquerade在选择源ip地址时刻的选择规则其实和路由选择的源地址选择是一致的。最简单的获取masquerade源地址的方法是通过下面命令:
ip route get <dstip>
这在Linux源码上看得更清楚,下面是ipv4场景下masquerade选源路由的方法
unsigned int
nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
const struct nf_nat_range2 *range,
const struct net_device *out)
{
......
newsrc = inet_select_addr(out, nh, RT_SCOPE_UNIVERSE);
if (!newsrc) {
pr_info("%s ate my IP address\n", out->name);
return NF_DROP;
}
nat = nf_ct_nat_ext_add(ct);
if (nat)
nat->masq_index = out->ifindex;
/* Transfer from original range. */
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
newrange.min_addr.ip = newsrc;
newrange.max_addr.ip = newsrc;
newrange.min_proto = range->min_proto;
newrange.max_proto = range->max_proto;
/* Hand modified range to generic setup. */
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
}
上表中inet_select_addr(out,nh,RT_SCOPE_UNIVERSE)就是根据out,路由,选择源ip地址的过程。
ipv6场景下masquerade源ip地址的选择
在ipv4场景上,masquerade 源地址选择和路由源地址选择是也就是一致的,但是在ipv6场合就有一定的区别了。
ipv6场景下masquerade动作的执行函数为:
nf_nat_masquerade_ipv6(struct sk_buff *skb,const struct nf_nat_range* range,
const struct net_device *out)
{
......
if( ipv6_dev_get_saddr(dev_net(out),out, &ipv6_hdr(skb)->daddr,0,&src) < 0)
return NF_DROP;
......
}
可见它的核心函数为ipv6_dev_get_saddr(),此函数执行的就是ipv6地址协议规定的源地址选择逻辑。而ipv6路由选择源地址函数实现为:
int ip6_route_get_saddr(struct net*net,struct rt6_info *rt,const struct in6_addr *daddr,
unsigned int prefs,struct in6_addr *saddr)
{
......
if(rt->rt6i_presrc.plen)
*saddr=rt->rt6i_prefsrc.addr;
else
err=ipv6_dev_get_saddr(net,dev?idev->dev:NULL,daddr,prefs,saddr);
return err;
}
可以看到在ipv6 路由选择源地址中,并不是第一选择ipv6_dev_get_saddr()函数的。而是先选择ipv6 route 表中选路结果是否设置了prefsrc。上述函数中入参rt表示的是ipv6 route 路由表选择的entry。ipv6路由选择具体由ip6_route_output()—>fib6_fule_lookup查询而来。
是否设置了ipv6路由的prefer src可以通过ip -6 route list 命令查看到,例如:
$ip -6 route list
......
2001::/64 dev eth0 src 2001::dbc:71 metric 15
......
可以看到针对2001::/64网段的dest ip,选路是eth0,prefer src为 2001::dbc:71
设置路由entry的prefer src命令为:ip -6 route add 2001::/64 dev eth0 scope link src 2001::dbc:71 metric 15
ipv6协议规定的源地址选择
ipv6协议中规定了严格源地址/目标地址选择机制,主要涉及到RFC 3484.也就是说当ipv6源地址尚未确定时刻,按照RFC3484规定的8条规则选择一个源ip地址。这8条规则(rules)是有优先级的,从优先级从高到低排列如下:
- rule1优先选择与目标地址相同的地址
- rule2优先scope与目标scope比较接近的,且scope更大的地址
- rule3优先preferred地址
- rule4优选home地址
- rule5优先和路由出口在同一网卡上的地址。
- rule6优选Label匹配地址
- rule7优选根据系统配置非临时/临时地址
- rule8优选和目标地址最长前缀匹配的地址
rule2
所谓ipv6地址的scope(作用域)分为下面几类:
- fe80::/10 链路本地地址,只出现在二层链路上,不能通过三层设备
- fc00::/7 ULA地址,不能出现在internet上,只能在组织内部。
- 2002::16 ipv6 to ipv4地址
- 全球唯一地址
scope也就是ipv6 地址分类。scope选择约接近的,那么源和目的的物理距离理论上应该更近。scope选择更大的保障了此地址可达性更高。
rule6
ipv6在选择地址时刻,还会进行目的地址和源地址的Label匹配,当匹配到固定的一对label时刻,匹配完成:
1.匹配时刻是按照目标地址最长前缀匹配方式,就是前缀匹配长度最长的label获胜,如此选出一个目标label;
2.按照源地址最长前缀匹配方式,找到一个label,这就是源label;
- 如果只有一个源地址的源label=目标label,查找完成。
- 如果多个源地址都出现匹配,那么选取优先级最高的匹配。
设置ipaddesslabel的方法是通过下面命令:
ip addrlabel add prefix $目标地址网段 label label号
ip addrlabel add prefix $源地址网段 label label号
下面命令可以查看lpv6 address label
ip addrlabel list
总结
单接口上有多个ip地址的时刻,masquerade源地址选择方式如下:
- ipv4场合,masquerade源地址选择和route选择源地址选择一致。
- ipv6场合下,masquerade源地址选择和route选择源地址不完全一致。route选择源地址,优先选择route中配置了prefer src的地址,其次才是ipv6源地址选择8条规则按规则优先级从高到低选择;masquerade选择则完全遵从ipv6 源地址选择的8条规则。
参考
blog.csdn.net/dog250/article/details/87815123