IPv6 tunnel broker with OpenVPN on OpenVZ

I need IPv6 on my MacBook. No ISP cares about it in Spain and a tunnel from HE is a pain in the ass to set up for any kind of dynamic network. Same happens with AICCU and the guys behind the SixXS project are a bunch of arrogant clowns anyway.
So yeah, this is going to get hacky. I got a little OpenVPN server on a VPS of mine in Spain. OpenVPN is great and works nicely to secure my connection wherever I go, while providing me great connectivity from a nice network I trust. Since version 2.3, OpenVPN does support IPv6 via TUN.

The problem

I am always tunneling my traffic through the VPN anyway, so IPv6 addresses would be assigned to each client from the OpenVPN server, just like I assign private IPv4 addresses, yeah?
Well, not so fast. OpenVPN does need at least a routed /112 to work, a /64 is preferred. Since I only got a cheap OpenVZ container and my provider uses SolusVM, I am fucked. Fuck SolusVM, really. You will have this problem if you use any other provider running OpenVZ and SolusVM which sadly is the industry standard. Same happens with bigger ISPs like Voxility, Kimsufi or basically any other idiot which believes that assigning less than a /64 per customer is fine.
然而事实并没这么简单。OpenVPN至少需要一个/112段来工作,最好是/64. 因为我买的是一个廉价OVZ架构的VPS,我的服务商用的是SolusVM面板,我真是日了狗了!狗日的SolusVM! 当你使用pvz架构和SolusVM面板的时候,上面的IPv6分配就会有问题!很遗憾,这种解决方案还是IDC行业的标准方案。同样的问题在一些大的ISP那里也会出现,比如Voxility, Kimsufi 和任何坚信分配给每个用户小于/64的IPv6是没问题的傻子。

The solution

We will tunnel a /48 from Hurricane Electric to your server using tb-tun, a great userspace program to use tunnel brokers on restricted environments. Once the /48 is routed, we will use OpenVPN to assign IPv6 addresses from a /64 for our clients.
我们将使用HE的一个/48到你使用tb-tun的服务器上,tb-tun是一个高效的tunnel brokers软件。一旦你的/48路由弄好,我们将能够使用OpenVPN在一个/64内来给我们的客户端分配IPv6地址。

1. Get your allocation 从HE获取IPv6地址段

Register an account with Hurricane Electric and sign up for a regular tunnel here. Choose the closest tunnel server to your location: they show you the IPv4 addresses of the nodes, so ping them from your server and get the best for you. Request a routed /48 too. The IPv4 endpoint they ask for is your server's IPv4 address.
Hurricane Electric注册一个账户,注册地址为:https://tunnelbroker.net/ ,选择离你最近的地区,他们会给对应的IPv4地址,你可以ping一下哪个合适。申请一个/48。他们询问的IPv4 endpoint就是你的VPS的IPv4地址。

2. Routing the subnet 分配路由子网

Let's ssh to your container and get the tunnel up. 让我们连上SSH,启动tunnel
Get tb-tun and unpack: 获取tb-tun并解压
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/tb-tun/tb-tun_r18.tar.gz
tar xzf tb-tun_r18.tar.gz
Set the tunnel broker up: 设置tunnel broker信息
# = "你在HE申请的tunnel的IPv4地址 Server IPv4 Address" under the "IPv6 Tunnel Endpoints" section.
# = 你自己的VPS的IPv4地址 Your server's IPv4 (Client IPv4 Address under the "IPv6 Tunnel Endpoints" section)
setsid ./tb_userspace tb0 sit > /dev/null
Get the tb0 interface up and bind one of the tunneled IPv6 to the server: 启动虚拟网卡tb0,并将IPv6地址关联上
ifconfig tb0 up
# 2001:470:1234::/48 = 你申请的IPv6的第一个地址 First IPv6 from your routed /48
ifconfig tb0 inet6 add 2001:470:1234::/48
ifconfig tb0 mtu 1480
Use the tunnel broker as the default route for IPv6: 将 tunnel broker作为默认的IPv6路由
route -A inet6 add ::/0 dev tb0
Remove the route with individual IPv6 addresses assigned. Not needed if you didn't got native IPv6 with the container: 删除默认的IPv6路由信息。此步骤并不是必须的,如果你的服务商本身并不提供本地IPv6地址
route -A inet6 del ::/0 dev venet0
And it's done. Ping google over IPv6 to be sure the tunnel broker is working: 这样就设置完了,Ping一下你的IPv6到谷歌看是否工作正常
root@m:~# ping6 google.com
PING google.com(mad01s08-in-x09.1e100.net) 56 data bytes
64 bytes from mad01s08-in-x09.1e100.net: icmp_seq=1 ttl=53 time=41.9 ms
64 bytes from mad01s08-in-x09.1e100.net: icmp_seq=2 ttl=53 time=42.1 ms
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 41.913/42.025/42.137/0.112 ms
If it's working as it should, add the following lines to your /etc/rc.local file so the tunnel broker is set up after each reboot. Edit as needed: 如果它运行正常,将下面这几行放到你的/etc/rc.local 文件内,这样每次重启后,tunnel broker就行自动启动了,注意其中的IPv6和IPv4地址改成你的
setsid /root/tb_userspace tb0 sit > /dev/null &
sleep 3s #ugly, but doesn't seem to work at startup otherwise
ifconfig tb0 up
ifconfig tb0 inet6 add 2001:470:1234::/48
ifconfig tb0 mtu 1480
route -A inet6 add ::/0 dev tb0
route -A inet6 del ::/0 dev venet0

3. Configure OpenVPN to assign and route IPv6 addresses 设置OpenVPN来分配IPv6地址

I won't go through the entire setup of an OpenVPN server here. If you don't have one working, get it set up in one minute with openvpn-install.
OpenVPN 2.3 only supports subnets from a /64 to a /112. Just get a /64 out of your /48 to use it for OpenVPN.
Edit your OpenVPN /etc/openvpn/server.conf and add the following directives: 编辑你的OpenVPN /etc/openvpn/server.conf 文件,增加下面的内容
server-ipv6 2001:470:1234:100::/64 # 你的/64段 your tunneled /64
push "route-ipv6 2000::/3" # 告诉你的客户端,通过VPN路由你的IPv6网络流量 tell the client to route Internet IPv6 traffic through the VPN
Restart OpenVPN to read the new configuration: 重启OpenVPN来获取新的设置
/etc/init.d/openvpn restart
And enable IPv6 forwarding on the system: 启用IPv6转发
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p
Finally, try connecting from your client. You should get a public IPv6 address assigned! 
[Nyr@nyr-macbook:~]$ ifconfig tun0
    inet --> netmask 0xff000000 
    inet6 fe80::225:4bff:feaf:4702%tun0 prefixlen 64 scopeid 0x8 
    inet6 2001:470:1234:100::1:0 prefixlen 64 
    nd6 options=1<PERFORMNUD>
    open (pid 14325)
[Nyr@nyr-macbook:~]$ curl ipv6.icanhazip.com
Now you can enjoy secure, dual stack connectivity wherever you go using just a cheap ass container.