发现问题
这两天我们宿舍楼的ipv6连接颇不稳定,持续的ipv6连接(telnet bbs和ssh等)时不时中断,浏览ipv6web服务器提供的网页,体验更是糟糕。于是我开始寻找原因。
ipv6小知识
ipv6是ipv4的下一代ip协议,特点是地址极大丰富。一般获取ipv6地址的方式包括原生(native)和隧道(tunnel)两种。为了能让ipv4和ipv6用户互访,可以使用双栈、隧道、代理、vpn等接入方式。详见wikipedia ipv6词条。
疑点重重
首先在cmd命令行里使用ping -t命令持续ping一个ipv6服务器,发现周期性地超时。tracert -d这个服务器,发现路由第一跳是一个2002开头的ipv6地址。
#两条命令检查连通性和路由路径
ping -t bbs6.sjtu.edu.cn
tracert -d bbs6.sjtu.edu.cn
2002?这不是通过6to4隧道分配到的ipv6地址吗?RFC3056里说,IANA为6to4隧道永久分配了2002::/16前缀。
#RFC 3056里关于6to4地址前缀的说明
The IANA has permanently assigned one 13-bit IPv6 Top Level Aggregator (TLA) identifier under the IPv6 Format Prefix 001 [AARCH, AGGR] for the 6to4 scheme.Its numeric value is 0x0002, i.e., it is 2002::/16 when expressed as an IPv6 address prefix.
但是且慢,本机没有设置使用隧道呀,甚至为了充分利用native的ipv6接入,我一直禁用ip helper服务。
#本机已禁用隧道,却得到了2002地址
netsh interface ipv6>show addresses
接口 1: Loopback Pseudo-Interface 1
地址类型 DAD 状态 有效寿命 首选寿命 地址
--------- ----------- ---------- ---------- ------------------------
其他 首选项 infinite infinite ::1
接口 11: 本地连接
地址类型 DAD 状态 有效寿命 首选寿命 地址
--------- ----------- ---------- ---------- ------------------------
公用 首选项 29d23h53m21s 6d23h53m21s 2001:da8:8000:f023:b981:ca13:dcf:b91e
公用 首选项 29d23h53m21s 6d23h53m21s 2002:3b4e:3611:c:b981:ca13:d
netsh interface ipv6>show teredo
Teredo 参数
-------------------------------------------
类型 : client
服务器名称 : something
客户端刷新间隔 : 60 秒
客户端端口 : 34567
netsh interface ipv6 isatap>show router
路由器名称 : isatap.sjtu.edu.cn
用中继 : default
解析间隔 : default
netsh interface ipv6 isatap>show state
ISATAP 状态 : enabled
netsh interface ipv6 6to4>show routing
路由状态 : disabled
用 SiteLocals : disabled
netsh interface ipv6 6to4>show state
6to4 服务状态 : disabled
服务终止时撤消 : enabled
net stop iphlpsvc
没有启动 IP Helper 服务。
#微软对于ip helper服务的描述
使用 IPv6 转换技术(6to4、ISATAP、端口代理和 Teredo)和 IP-HTTPS 提供隧道连接。如果停止该服务,则计算机将不具备这些技术提供的增强连接优势。
没有设置开启隧道,没有开启ip helper服务,在这种情况下我绝无可能通过隧道获取ipv6地址。但我却偏偏得到了2002地址,这让我大惑不解。
柳暗花明
那么,有没有可能我的2002地址并非由隧道获得呢?这时我认为,首先应当找出这个地址到底是谁分配的。我找到了RFC3056中关于6to4地址转换的说明。关于这一段,还有一个更通俗的说法如下。
#Nick's 6to4 page里的说法
6to4 uses a special IPv6 prefix: 2002::/16. The IANA has set aside this address space just for 6to4. The 6to4 specification states that the 32 bits after 2002::/16 are the IPv4 address of the gateway machine for the network in question. This is how the packets know to find their way to your network -- the IPv4 address of your gateway is right in them!
按照上述说法,我们把2002:3b4e:3611:c:b981:ca13:d里的3b4e:3611换算成ipv4地址,也就是将16进制转换成10进制,3b=>59, 4e=>78, 36=>54, 11=> 17。59.78.54.17,这ipv4地址正好与我处于同一子网内!
原来在同一子网内有人在不断广播路由,我的电脑自动使用这个路由,加上学校提供的2001路由和地址,我的电脑有了两条路由路径和两个ipv6地址。那么操作系统在这种情况下会使用哪一条路由呢?我们运行以下命令,看看Windows操作系统的默认策略。
netsh interface ipv6>show prefixpolicies
查询活动状态...
优先顺序 标签 前缀
---------- ----- --------------------------------
50 0 ::1/128
40 1 ::/0
30 2 2002::/16
20 3 ::/96
10 4 ::ffff:0:0/96
5 5 2001::/32
可以看到,Windows 7默认优先使用2002::/16前缀,这逻辑一般不会有太大问题:如果有其他选择,人们一定不会使用6to4隧道;如果使用了6to4隧道,也就是说使用2002::/16前缀的话,一定是迫不得已,也就是说,一定是因为无法使用2001::/32前缀。
但是当有人使用6to4隧道获取ipv6地址,再将本机作为路由在子网内广播呢?其他机器在这种策略的指引下,一定会优先使用2002前缀,导致2001前缀被屏蔽。
解决问题
明白了以上内容,问题的解决就很容易了,运行以下命令,将2001::/32的优先级提高,从而屏蔽2002::/16前缀。这样虽然还是会获得2002地址,但默认优先使用2001::/32前缀,不会让2002地址影响用户的网络体验。
netsh interface ipv6 set prefixpolicy 2001::/32 35 1 persistent
netsh interface ipv6>show prefixpolicies
查询活动状态...
优先顺序 标签 前缀
---------- ----- --------------------------------
50 0 ::1/128
40 1 ::/0
35 1 2001::/32
30 2 2002::/16
20 3 ::/96
10 4 ::ffff:0:0/96
深入思考
我遇到的问题固然得到了解决,但其根源在哪?ISP提供了ipv6接入网关,恶意用户在同一子网内进行路由广播,会导致其他用户同时获取两个ipv6地址,在某些情况下,由于操作系统的默认策略,用户甚至会优先使用恶意的ipv6地址。如果两个地址的上网体验相近的话,由于常人无法理解ipv6地址的语义,大多数用户根本不会意识到恶意行为的存在。
虽然RFC中强制规定ipv6节点必须支持ipsec,却并没有规定必须开启ipsec,如果操作系统默认不使用ipsec的话,那么RFC的这些规定无疑形同虚设。而作为一个比一般用户高级的Windows用户,我至今也没能搞定ipsec over ipv6。
如此看来,ipv6的安全性建设仍然任重道远。 |