SD-WAN——使用WireGuard与ipv6实现高速免费异地组网

上周通过了HCIP的数通认证,这周趁热打铁,记录一个数通领域中的干货——SD-WAN组网技能

1. 目标

  1. 公网ipv4场景,实现点到点的内网互联
  2. 无公网ipv4有ipv6场景,实现私有内网远程pc的内网互联
  3. 无公网ipv4有ipv6场景,实现两(多)个不同的内网互联

2. 基础知识回顾

  1. IPv6
  2. SD-WAN
  3. IPv4 over IPv6隧道
  4. WireGuard (over UDP)
  5. 软件路由器

2.1 ipv6

ipv6作为ipv4的替代方案,拥有众多优秀特性,对于普通用户来讲最重要的特性之一则为:ipv6的地址由128 bit构成,可以为全世界的每一粒沙子分配一个公网的ipv6地址,数量的庞大也代表着便捷与免费。
最近几年我国也出台了相关政策,要求各大运营商都要开通IPV6,IPV6到普通家庭的普及也给我们带来了许多便利。
cn-ipv6
查看自己的网络是否支持ipv6,直接查看设备获取到的ip地址可以看出,如发现没有ipv6地址可以根据网上的资料对光猫或路由器进行配置,或寻找运营商工作人员配置即可,细节在本文中不作详细展开。

2.2 SD-WAN

SD-WAN是基于SDN(Software-Defined Networking,软件定义网络)提出的一种新型组网技术,使用软件的方式来组织定义WAN(Wide Area Network,软件定义广域网)。
sd-wan

SD-WAN与传统组网方式相比,具有灵活简单成本低的特点。在专业的SD-WAN企业组网中通常涉及到SDN控制器和实现控制面与转发面分离特有设备,由此衍生出的技术如:OpenFlow、P4、ONOS、OpenDayLight等。

而对于普通用户而言,SD-WAN领域相关的FOSS(Free and Open Source Software,开源软件)有TailscaleZeroTierOneOpenWrtWireGuardOvSFrrouting等,这些开源软件使得让我们普通用户也能体验到SD-WAN组网的便捷,有能力的开发者甚至能进行二次开发打造出一个自己的SD-WAN产品。

SD-WAN涉及到的知识范围也非常庞大,在本文中仅对其概念进行了解。

2.3 IPv4 over IPv6隧道

在IPv4与IPv6双协议的现状中,IPv4目前仍然是主流的协议,目前几乎所有的上网设备都支持IPv4而不一定支持IPv6。
ipv4 over ipv6

在此背景下,为让IPv4演变为IPv6也出现了多种过渡技术,如:双栈、隧道、转化等技术。

对普通用户而言,使用较多的是IPv4 over IPv6隧道技术,也就是使用IPv6网络来传输IPv4的数据包。
比较典型的例子为:在异地的两个网络中均有IPv6,但各自网络中均有部分设备不具备IPv6能力(如家庭摄像头),这时想要实现各自的IPv4内网互通则可以使用IPv4 over IPv6隧道技术来实现。本文中的示例也主要使用这种技术。

IPv4 over IPv6隧道类似的还有IPv6 over IPv4隧道,就是通过隧道技术,使IPv6报文在IPv4网络中传输。

2.4 WireGuard

前面提到IPv4 over IPv6隧道技术,其中的隧道(tunnel)实现技术手段众多,如OpenSSL、GRE、IPsec、WireGuard等。

在本文中用到的为WireGuard,它使用UDP传输,且具备简单、高性能、加密等特点得到了广泛的应用。
关于WireGuard的详细实现细节可参见《WireGuard技术白皮书》
wg

我们作为使用者,可仅需了解WireGuard具有以下特点:

  • 使用UDP协议进行传输
  • 使用公私钥方式进行加解密
  • 支持众多平台的客户端

2.5 软件路由器

路由器作为不同网段通信的基础设施非常重要,而在普通家庭用户中的路由器更是拥有交换、路由、WIFI、拨号、网管等诸多功能于一身,更是啥都要干
fat-router
大多数厂商的家用路由器为了功能的普适性,自带的路由器管理系统中功能一般较为单一,对于一些喜欢折腾的用户则往往会使用支持的软件功能更为丰富的路由器(软路由),即可以纯软件在某些操作系统上运行,也可以在某些设备上更新系统来运行。

软路由中最知名的非OpenWrt莫属,开源且支持的插件众多。其他知名的也还有RouterOS,或者国内的iKuai(爱快),如不想太折腾,如仅想感受一下软路由的功能,选择iKuai则也是一个不错的选择。

在本文的组网示例中,无论使用哪款软路由都行,因它们都对WireGuard有支持,用适合自己的就行,仅配置上有部分差异,原理都是一样的。

3. 点到点内网互联(wg牛刀小试)

3.1 拓扑

p2p

简述:实现右边的家庭网络左边的云服务器Ipv4内网互通

应用场景:

  • 访问云主机未开放的端口
  • 云主机访问家庭网络中的服务(如数据库、http接口、GPU接口)
  • 公司中的主机通过云主机访问家庭中的主机
  • ……

3.2 配置

左边的云主机为ubuntu,右边的pc主机为windows

3.2.1 云主机部署WireGuard-server

先在云主机上安装WireGuard

#安装WireGuard
sudo apt install wireguard
#查看wg命令用法
wg --help
#查看wg-quick命令用法
wg-quick --help

如能正常使用wg --help命令,则代表WireGuard安装成功
wg --help

安装成功后,配置WireGuard

#创建并进入一个存放配置信息的目录,名称任意
mkdir wireguard
cd wireguard
# 生成linux秘钥
name=linux;wg genkey | tee ${name}.key | wg pubkey > ${name}.pub
# 生成Window秘钥,后面PC用到的
name=pc;wg genkey | tee ${name}.key | wg pubkey > ${name}.pub
# 创建配置文件
touch wg1.conf

wg-ll

修改WireGuard配置,WireGuard中的配置参考:wireguard-conceptual-overview

[Interface]
#本机虚拟局域网IP
Address = 10.0.0.1/24
#PrivateKey使用前面生成的私钥
PrivateKey = oLUhpzDmJJao7gXml9WRYbCtdWew2dWIuCJDULhqXWE=
#WireGuard监听的UDP端口
ListenPort = 58161

# 填写客户端对端的信息,可以填多个Peer
[Peer]
# 本机电脑,pc 客户端公钥
PublicKey = OhD0WhjKghccV3gHRfZcdj1aWLQ4zDBNFRwB10gXJk4=
# 允许 10.0.0.12/32 主机访问此节点,如需要访问更多网段,可用逗号分割配置多个网段
AllowedIPs = 10.0.0.12/32
PersistentKeepalive = 25

配置文件准备好后,运行WireGuard

#运行WireGuard
sudo wg-quick up ./wg1.conf
#查看ip运行后地址
ip addr
#查看WireGuard状态
wg show

sudo wg

可使用netstat -anlp|grep 58161命令进行确认,可看到udp端口监听成功
netstat

如需停止WireGuard,可使用wg-quick down ./wg1.conf关闭

服务端配置时,需要确保UDP端口是否被放行
iptables

如觉得linux的命令行操作比较麻烦,也可使用wg-easy的docker镜像运行,有界面操作更便捷。

3.2.2 pc端运行WireGuard

windows端到WireGuard官网下载对应的客户端
pc-wg

WireGuard的安装比较简单,点点点,即可完成安装。

打开WireGuard软件,点击【新建隧道】,【新建空白隧道】,定义一个名称后在配置文件中输入以下信息

[Interface]
#使用之前生成的windows私钥
PrivateKey = oLNDX2llM2T4MuM4L9ql+5s/k2taBziK5OkzPXbNJGk=
#虚拟IP地址
Address = 10.0.0.12/32
#可选项,监听端口随便取一个,如58262
ListenPort = 58262

[Peer]
#linux的公钥
PublicKey = eCzuZwmewUmzhuFGu3BigC7nm+3FFdw1h1Zop8mO+DQ=
#允许的网段,也就是要访问的网段
AllowedIPs = 10.0.0.1/24
#添加linux的公网Ipv4地址
Endpoint = xxx.xxx.xxx.xxx:58161
PersistentKeepalive = 25

pc-wg-conf
之后点【连接】,则可以看到收发数据包都有值
wg-show

查看linux与windwos的IP地址
show ip

3.3 验证

windows上ping服务器的虚拟ip,功能ping通

ping 10.0.0.1
ping test

使用虚拟内网ip访问linux上的nginx上的服务,正常访问

浏览器访问10.0.0.1
web-test

在windows上抓包,可看到有wireguard包通信
pcap-wireguard

在windows上运行一个http服务,在服务器上发起请求,请求成功

curl 10.0.0.12:8181/hello
curl-test

4. 家庭网络与远程PC内网互联

4.1 拓扑

home-2-pc

简述:实现左边的公司PC右边的家庭网络所有设备的Ipv4内网互通,左右两边的网络均已开通IPv6

应用场景:

  • 异地访问家中的NAS
  • 异地访问家中的仅支持IPv4的摄像头
  • 对家中的路由器进行异地管理
  • ……

4.2 配置

  • PC软件,WireGuard
  • 路由器(ikuai/openwrt等均可),本者这里使用的是iKuai-Q3000,通过网线连接在家里的主路由下

4.2.1 iKuai路由器后台设置

进入iKuai路由器后台(异地可使用iKuai云代理访问),进入WireGuard配置界面。

在【接口列表】中添加一个服务接口,本地地址输入一个网段中不存在的内网ip地址,如10.0.9.2/24

wg-intf

公钥与私钥点旁边的按钮随机生成,监听端口填一个未占用的端口,如50000;mtu值一般根据运营商类型填写,为了兼容性更好我这里填的1000
wg-tun

之后在【隧道列表】中添加一个邻居,填入的信息为对端PC上WireGuard的信息。

  • 对端IP地址/域名填PC的实际ipv6地址(有条件的建议使用ddns域名避免ipv6地址频繁变更)
  • 对端端口为对端监听的WireGuard端口
  • 对端公钥填对端PC上WireGuard的公钥
  • 允许目标网段填写对端PC上的虚拟ip地址,如后面我配置的为10.0.9.101/32

wg-show
此时下行数据显示0,等待PC端的WireGuard上线

4.2.2 pc端WireGuard配置

WireGuard的安装过程略,前文有介绍。

直接看配置内容:

[Interface]
PrivateKey = oLNDX2llM2T4MuM4L9ql+5s/k2taBziK5OkzPXbNJGk=
ListenPort = 58262
Address = 10.0.9.101/24

[Peer]
PublicKey = kXdoOpMrIQqpuy6gk+KzYYyB68SeKYFl7A1rZXjoFBk=
AllowedIPs = 10.0.9.2/32, 192.168.31.0/24
Endpoint = [2409:8a62:efd:b340:a9e:4bff:fe13:7af7]:50000
PersistentKeepalive = 10
  • [Interface] 中填写的是Windows主机侧的信息

    • 监听端口任意,需要与前面路由器的配置相对应,如58262
    • 虚拟ip与前面路由器配置的ip在同一个网段
    • 私钥与前面路由器配置的公钥是一对的
  • [Peer] 中填写的是路由器的WireGuard信息

    • 公钥填写的是路由器WireGuard的公钥
    • Endpoint填写的是路由器的IPv6地址WireGuard端口IPv6地址可在iKuai的IPv6设置中查看
    • AllowedIPs为希望互通的网段,192.168.31.0/24为家里主路由的网段

截图说明下:
conf-list

当路由器与PC都配置完后,PC端点连接,就可以正常访问家中内网了。iKuai路由器中的隧道上下行统计也都会有数值显示。
wg-stat

4.3 验证

4.3.1 联通性验证

公司网络使用IPv4访问家里的主路由器192.168.31.1
web-home-router

ssh方式,访问家中的NASssh 192.168.31.168:22
telnet-nas

使用VLC+RSTP访问家里的摄像头
在vlc中打开:rtsp://192.168.31.170:554/stream1
vlc-web-cam

查看WINDOWS的路由表,route PRINT
windows-route

抓包验证,WIRESHARK可看到大量WireGuard数据包,并使用IPv6传输
wg-pcap-trans

查看路由器的路由表,可看到路由器生成了对应的直连路由记录
router-static
通信成功,完美~

4.3.1 SpeedTest速率验证

此部分的网络访问速率遵从短板原理,为了验证速率可安装SpeedTest验证一下。

为了方便直接在家里的NAS上用docker运行SpeedTest,命令如下:

sudo docker run -e MODE=standalone -e WEBPORT=8999 -e restart=always --net=host ghcr.io/librespeed/speedtest

之后在Windows中打开浏览器访问:http://192.168.31.168:8999
speed-test
从测试结果来看还行,毕竟免费的,日常普通需求基本满足。
ikuai-show
SpeedTest页面上显示的192.168.31.34为iKuai路由器的内网地址,由此也可以看出:异地向家里发起请求后,会通过家里的iKuai节点进行中转,即:iKuai节点为最后一跳

5. 多个内网互联

5.1 拓扑

net-2-net

简述:实现左边的公司内网右边的家庭网络所有设备的Ipv4内网互通,左右两边的网络均已开通IPv6

应用场景:

  • 连接WIFI实现内网互联
  • 用户无需安装客户端,静默内网互联
  • 企业异地组网,高速且免费
  • ……

5.2 配置

此部分的配置与前面介绍的 “家庭网络与远程PC内网互联” 大体一致,区别在于不需要安装WireGuard客户端,仅在需要组网的路由器中配置WireGuard隧道即可。

组网前,需要注意的点:

  1. 所需组网路由器均有IPv6地址
  2. 所需组网路由器支持WireGuard隧道
  3. 为避免网段冲突,所需联通网段位于不同的网段

这里为了方便,仍使用两台iKuai-Q3000举例。

5.2.1 路由器1配置

路由器1对应的主路由网段为:192.168.32.0/24
与前面 “家庭网络与远程PC内网互联” 类似的,在WireGuard接口配置中添加一个接口
r1-wg-intf

  • 本地地址使用10.0.9.1/24
  • 并生成公钥和私钥
  • 监听端口任意,为了区分这里使用19999
  • mtu填1000,与前文一致(tips:mtu填小点可避免一些设备mtu不兼容问题)

之后添加隧道邻居,填入对端的WireGuard配置信息
wg-tun-conf
具体字段前面有说明,允许目标网段中填的192.168.31.0/24为要互联的对端网段
wait-wg-online
此时累计下行为0,因为另一个节点的隧道还没有配置好

5.2.2 路由器2配置

路由器2对应的主路由网段为:192.168.31.0/24

路由器2的WireGuard接口沿用 “家庭网络与远程PC内网互联” 部分的配置,仅需添加隧道邻居。
r2-wg
允许目标网段中填的192.168.32.0/24为对端路由器1的网段,10.0.9.1/32为对端路由器1的主机地址。

待路由器2添加隧道邻居完毕后,iKuai的WireGuard页面中会显示有上下行数据,则代表握手已成功。
wg-tun-list

5.3 验证

路由器2中访问路由器1网段中的192.168.32.1
trace-route
通过路由追踪工具可以看出网络已可达

查看路由器1中的路由表
router-static
可以看出在路由表中自动添加了192.168.31.0网段的路由

6. 总结

在本文中,通过免费的WireGuardIPv6,再结合价格低廉的路由器完成了主机到主机,网段到网段的组网,算是SD-WAN组网的一种实践与体验。

从本文也可以看出,WireGuard+IPv6这种组网方式对于各种组网场景几乎都能应对,与高昂的专线组网相比,这种方式的组网也带来了极大的便利性。

网络真奇妙,为WireGuard各大运营商点赞。