将宣告的subnet通过wireguard分配给客户端使用
折腾routeros有一段时间了,虽然当时给所有的bgp节点换了routeros,但是仍然没找到能与gfw内的设备建立稳定连接的方法(毕竟routeros的连接方式就那几种,大部分已经可以被识别并被封锁),于是最近寻找其它方法来为gfw内的设备提供稳定的ipv6服务,最后选择了ubuntu+bird6+wireguard这套方案,并记录下实现过程.
实现方式和需要准备的东西
本次为在服务器上进行subnet宣告,并通过wireguard将subnet分给客户端使用,这样做的优点是客户端设备不再要求大内存来容纳bgp的表(当然小内存也可以选择不发表给客户端),客户端配置比较简单,缺点是客户端没有了bgp,不能anycast(如果客户端也只有一个上游的话自己宣告和从服务器上宣告并没有太大区别).
本次使用如下乱七八糟的东西
- 支持bgp的服务器一个(也可以普通的vps+he的bgp tunnel)
- 一个/48或者更大的subnt
- wireguard
- bird
- ubuntu 16.04
如果服务器自带/48或者更大subnet可以不宣告直接使用服务器自带的subnet也可以,这样省去自己宣告,可以直接跳过前面宣告部分的步骤直接看后面wireguard部分
宣告部分
bird之类的安装和配置不再讲解(我自己也很菜),直接贴出我现在的配置文件大致说明一下
router id 8.8.8.8;
function net_martian()
{
return net ~ [ 2001:8888:8888::/48+, 2001:8887:80::/44+ ];
}
filter normal_out
{
if proto = "Announce" then accept;
if net_martian() then accept;
if proto = "NA" then reject;
reject;
}
protocol static Announce
{
import all;
route 2001:8887:80::/44 reject; #tunnel
}
protocol direct
{
interface "wg0";
import all;
}
protocol static NA
{
}
protocol kernel
{
scan time 60;
import none;
}
protocol device
{
scan time 60;
}
protocol bgp vultr
{
local as 233333;
source address 2001:2333:2333:4733:5400:02ff:2333:2333;
import none;
export all;
graceful restart on;
multihop 2;
neighbor 2001:19f0:ffff::1 as 64515;
password "2333";
}
其中net_martian
放置的是允许通过的subnet,这个是我给igp准备的,可有可无,然后是Announce
放置的是本机要宣告的subnet
此外direct
是之前测试遗留的东西,也是可有可无的,可以直接删掉这个.
router id
这个东西也不是必须的,有合法的值就行,修改好配置文件之后直接birdc6 config
重载配置,然后去找其他有ipv6的机器路由追踪一下宣告的subnet看看有没有路由,没有的话排查宣告是否有错误,有的话继续wireguard步骤.
wireguard部分
先是安装
add-apt-repository ppa:wireguard/wireguard -y
apt update
apt install wireguard-dkms wireguard-tools
装好之后生产2组公私钥给服务端和客户端用
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee client.key | wg pubkey > client.pub
然后新建并编辑配置文件,vim /etc/wireguard/wg0.conf
,然后填写如下配置.
[Interface]
PrivateKey = 23333333333333333333333333333333333333=
ListenPort = 12345
SaveConfig = false
Address = 10.0.0.1/24,fd86:ea04:1120::1/64
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = 45555555555555555555555555555555555555=
AllowedIPs = 10.0.0.2/32,fd86:ea04:1120::2/128,2001:8887:80::/48
其中Interface的PrivateKey
改为server.key的内容,Peer的PublicKey
改为clinet.pub的内容,AllowedIPs
为客户端的ipv4/ipv6和为客户端分配的subnet
如果只用来给客户端分配ipv6的subnet不需要转发客户端ipv6流量的话可以直接把PostUp
|PostDown
和ipv4部分删掉
另外如果客户端只是用户终端而不是路由器的话,则不需要为客户端分配/48或/64等比较大的subnet,可以直接将fd86开头的换成宣告的subnet,给客户端/128,然后删掉后面的/48即可.
另外,像这样给客户端分配fd86开头时,fd86这段地址只能是客户端和服务端以及同服务器下其它客户端互相通信使用,并不能正常访问互联网资源.
修改好配置文件之后运行wg-quick up wg0
启动wireguard,然后检查下服务器的防火墙是否开放了对应的端口,没有开放的话开一下端口.
然后还需要设置下转发,vim /etc/sysctl.conf
在下面加一行
net.ipv6.conf.all.forwarding = 1
然后运行sysctl -p
生效
客户端(openwrt)设置
先装一下luci-proto-wireguard
,安装时会自动安装wireguard和其它需要的包
装好之后在接口页面添加一个接口,协议选择wireguard,私钥填写刚刚服务器上生成的client.key端口为空,然后ip填写刚刚wireguard服务端配置文件中peer中为客户端设置的ip,此处只设置ipv4和fd86开头的ip不要填写为客户端分配的subnet
然后添加一个peer,其中允许的ip填写服务端wireguard配置文件里Interface的Address
里的ipv4和::/0,这里表示所有的ipv6和服务端使用的那段ipv4流量走本接口
勾选路由允许的 IP
然后下面ip和端口填写服务器ip和wireguard配置里面设置的端口
Keep-Alive内容填写25
然后点击保存并应用,然后回到接口页面,重启下wireguard的接口
这里注意,不要将wireguard的接口添加到wan或者lan组里,否则会出问题
然后编辑lan接口找到 ipv6地址 和 ipv6路由前缀 部分,这里需要将分配给客户端的subnet做进一步的拆分,一部分拆给路由器lan接口本身和路由器下面的客户端(即ipv6地址),一部分拆给路由器下面的客户端的客户端(ipv6路由前缀)也就是ipv6-pd,这里为了方便可以各拆/56,2001:8887:80:100::/56
和2001:8887:80:200::/56
,其实这样还剩下一大部分没有使用的,可以根据自己的需求拆.
然后下面dhcp服务器->ipv6设置,路由通告服务 和 DHCPv6 服务 改成服务器模式,NDP代理 改成混合模式,DHCPv6模式 改成有状态+无状态
拆完之后点击保存并应用,然后路由器下面的设备断开重新连接之后即可获得ipv6和ipv6-pd了