OpenVZ型VPS安装Teredo接入IPv6
[
2010/04/23 23:35 | by suibing ]
2010/04/23 23:35 | by suibing ]
没有原生提供IPv6的XEN型VPS可以在Hurricane Electric申请一个TunnelBroker接入IPv6,对OpenVZ型VPS,由于目前绝大多数VPS的提供的OpenVZ内核没有打上虚拟sit0设备的补丁,所以不能使用TunnelBroker(已经可用,参阅http://www.lostriver.net/linux-userspace-6to4-tun/)。但如果VPS提供TUN/TAP设备,可以通过Teredo接入IPv6。
Linux上的开源Teredo客户端叫Miredo。对于Ubuntu/Debian,Miredo已经有了deb安装包,开启TUN/TAP后运行apt-get install miredo,再次用ifconfig查看时,名为teredo的TUN/TAP接口已经配置完成,IPv6前缀为2001:0:53aa:64c:。惟一一点遗憾是Miredo占用了约30M内存(是在保存peer list么?),对于小内存VPS有些压力。另外注意每次reboot或者重启Miredo进程后,IPv6地址将会改变。
Teredo也可以为位于IPv4 NAT内的主机提供IPv6接入(6to4必须要客户端有public IPv4 address),完整的Teredo接入需要客户端、Teredo Server和Teredo Relay。(Wiki在此)。由于需要bubble packet,国内又没有Teredo Relay(中国CERNET2内,可见的Teredo Relay位于欧洲),第一个IPv6数据包往返可能长达1000ms,后续数据包往返大约在300ms+。
Teredo接入与6to4类似,对于不同的IPv6地址使用不同的中继;不同之处是Teredo Relay在IPv6网络anycast 2001::/32前缀,而6to4 Relay除在IPv6网anycast 2002::/16,还在IPv4网络anycast 192.88.99.1。
CERNET2有线路tein3至欧洲,目前到本站IPv6的Teredo中继是funet.fi(芬兰),延时200ms+,再从芬兰到美国的VPS又加上100ms延时。带宽十分充裕,但在高峰时段丢包率达到25%,v4和v6线路都有丢包。
一般来说同时具有IPv4与IPv6地址的域名,将优先使用IPv6访问。但对于Teredo接入IPv6,系统会优先使用IPv4访问以获得更好的接入质量。所以添加IPv6域名应慎重,对于CERNET用户,系统会优先使用IPv4访问,经过几十秒超时后才使用IPv6,体验极差。
6to4可以在没有原生IPv6接入时构建IPv6 over IPv4隧道。该协议已经被linux内核所支持,内核提供了虚拟设备sit自动配置IPv6隧道。很多ISP也提供免费的TunnelBroker。但如果内核没有支持sit设备(比如现在大多数OpenVZ的VPS的内核时都没有支持sit),则在运行
# ip tunnel add 6to4 mode sit
会出现
ioctl: No such device
搜索了一下,似乎还没有运行于linux的第三方程序能建立6to4隧道,于是只好自己写一个。程序放在了
Please visit http://code.google.com/p/tb-tun/。
RFC3056包含了6to4隧道大多数细节,我只看了数据包封装,十分简单,把IPv6数据包(包括header和payload)直接作为IP数据包的packet body。注意IPv4数据包的协议类型为41(C语言里面定义常数IPPROTO_IPV6)。
程序首先创建TUN设备,并开启SOCK_RAW监听协议41(由于用了原始套接字,运行时必须要有root权限)。然后创建两个线程s2t和t2s,s2t把sock上监听到源地址正确、协议类型为41的IP包去掉包头写入TUN设备,t2s读取TUN设备上的数据并封入IP数据包作为内容发送给Relay Server。
t2s比较容易,惟一疑惑是使用sendto()函数时,远端地址结构体remoteaddr.sin_port不知道如何填写,因为封装的不是TCP或者UDP,没有端口号。填写为htons(IPPROTO_IPV6)没有出现问题。
s2t则出现了一些问题,明明向TUN设备写入了正确的数据包,却无法正确被应用程序识别,tcpdump返回wrong link-layer encapsulationbad-hlen。
重新查看了内核TUN/TAP设备的文档,原来TUN设备模拟点对点链路,也存在链路数据包头。通常创建TUN/TAP设备时使用了flag IFF_NO_PI缺省了链路层包头,内核自动把协议字填写为IP数据包。与实际的IPv6不符导致错误。
flag IFF_NO_PI没有设置时,链路附加包头为:
struct tun_pi {
unsigned short flags;
unsigned short proto;
};
flag仅在接收数据包时有效,这里向TUN设备写入,即发送数据包,这一字可以置0,proto应该填写htons(ETH_P_IPV6)。
向TUN写入时,需要在从sock读取的IPv6数据包前加入4个字节的上述结构体。t2s函数也要进行相应修改,除去上述的4个字节链路包头。
如何配置6to4 tunnel参阅Google Code上的HOWTO。试验了一下资源占用,内存占用约0.5M,CPU使用为wget的2倍。没有测试过兼容性,代码也显然还有很大改进空间
Linux上的开源Teredo客户端叫Miredo。对于Ubuntu/Debian,Miredo已经有了deb安装包,开启TUN/TAP后运行apt-get install miredo,再次用ifconfig查看时,名为teredo的TUN/TAP接口已经配置完成,IPv6前缀为2001:0:53aa:64c:。惟一一点遗憾是Miredo占用了约30M内存(是在保存peer list么?),对于小内存VPS有些压力。另外注意每次reboot或者重启Miredo进程后,IPv6地址将会改变。
Teredo也可以为位于IPv4 NAT内的主机提供IPv6接入(6to4必须要客户端有public IPv4 address),完整的Teredo接入需要客户端、Teredo Server和Teredo Relay。(Wiki在此)。由于需要bubble packet,国内又没有Teredo Relay(中国CERNET2内,可见的Teredo Relay位于欧洲),第一个IPv6数据包往返可能长达1000ms,后续数据包往返大约在300ms+。
Teredo接入与6to4类似,对于不同的IPv6地址使用不同的中继;不同之处是Teredo Relay在IPv6网络anycast 2001::/32前缀,而6to4 Relay除在IPv6网anycast 2002::/16,还在IPv4网络anycast 192.88.99.1。
CERNET2有线路tein3至欧洲,目前到本站IPv6的Teredo中继是funet.fi(芬兰),延时200ms+,再从芬兰到美国的VPS又加上100ms延时。带宽十分充裕,但在高峰时段丢包率达到25%,v4和v6线路都有丢包。
一般来说同时具有IPv4与IPv6地址的域名,将优先使用IPv6访问。但对于Teredo接入IPv6,系统会优先使用IPv4访问以获得更好的接入质量。所以添加IPv6域名应慎重,对于CERNET用户,系统会优先使用IPv4访问,经过几十秒超时后才使用IPv6,体验极差。
6to4可以在没有原生IPv6接入时构建IPv6 over IPv4隧道。该协议已经被linux内核所支持,内核提供了虚拟设备sit自动配置IPv6隧道。很多ISP也提供免费的TunnelBroker。但如果内核没有支持sit设备(比如现在大多数OpenVZ的VPS的内核时都没有支持sit),则在运行
# ip tunnel add 6to4 mode sit
会出现
ioctl: No such device
搜索了一下,似乎还没有运行于linux的第三方程序能建立6to4隧道,于是只好自己写一个。程序放在了
Please visit http://code.google.com/p/tb-tun/。
RFC3056包含了6to4隧道大多数细节,我只看了数据包封装,十分简单,把IPv6数据包(包括header和payload)直接作为IP数据包的packet body。注意IPv4数据包的协议类型为41(C语言里面定义常数IPPROTO_IPV6)。
程序首先创建TUN设备,并开启SOCK_RAW监听协议41(由于用了原始套接字,运行时必须要有root权限)。然后创建两个线程s2t和t2s,s2t把sock上监听到源地址正确、协议类型为41的IP包去掉包头写入TUN设备,t2s读取TUN设备上的数据并封入IP数据包作为内容发送给Relay Server。
t2s比较容易,惟一疑惑是使用sendto()函数时,远端地址结构体remoteaddr.sin_port不知道如何填写,因为封装的不是TCP或者UDP,没有端口号。填写为htons(IPPROTO_IPV6)没有出现问题。
s2t则出现了一些问题,明明向TUN设备写入了正确的数据包,却无法正确被应用程序识别,tcpdump返回wrong link-layer encapsulationbad-hlen。
重新查看了内核TUN/TAP设备的文档,原来TUN设备模拟点对点链路,也存在链路数据包头。通常创建TUN/TAP设备时使用了flag IFF_NO_PI缺省了链路层包头,内核自动把协议字填写为IP数据包。与实际的IPv6不符导致错误。
flag IFF_NO_PI没有设置时,链路附加包头为:
struct tun_pi {
unsigned short flags;
unsigned short proto;
};
flag仅在接收数据包时有效,这里向TUN设备写入,即发送数据包,这一字可以置0,proto应该填写htons(ETH_P_IPV6)。
向TUN写入时,需要在从sock读取的IPv6数据包前加入4个字节的上述结构体。t2s函数也要进行相应修改,除去上述的4个字节链路包头。
如何配置6to4 tunnel参阅Google Code上的HOWTO。试验了一下资源占用,内存占用约0.5M,CPU使用为wget的2倍。没有测试过兼容性,代码也显然还有很大改进空间



