wireguad是一款VPN软件,可以在公网中建立一个隧道,连接两端的私网。例如连接两个办公地点的网络,或者手机、电脑等连接回家里的网络等等。
本例中的场景:家里使用openwrt路由器连接互联网,手机通过wireguad连接到家里的私网。这种连接模式类似IPsec中的easy VPN,就是手机、电脑等单个设备连接到一个私有网络中,不同于Site-to-Site模式。
openwrt路由器和手机都没有公网IPv4地址,获得的是公网IPv6地址,但都是动态IP。wireguard在私网中使用IPv4地址。也就是 使用公网的IPv6建立wireguard隧道,然后传输私网的IPv4流量 。
两端在公网中建立VPN隧道,一般至少有一端是公网IP。如果公网IP是静态的,可以直接使用IP地址来进行VPN连接;如果公网IP是动态的,还需要使用DDNS技术,通过域名来进行VPN连接。我已经配置好了openwrt中的DDNS,这里主要是介绍wireguard的配置。
拓扑图
物理连接拓扑:公网中使用IPv6建立wireguard隧道,两端的内网使用IPv4传输流量。
wireguard连接完成后的等效拓扑:wireguard隧道建立完成后,手机可以看成是直接连接在openwrt上的设备。
openwrt的配置
oepnwrt中需要安装wireguad软件,因为我的固件默认已经有了,可以直接进行配置。
在openwrt命令行创建密钥
两端的wireguard设备之间需要使用一个密钥对(包含一个公钥和一个私钥)来建立隧道,一端需要保存自己的私钥,另一端需要知道本端的公钥。
openwrt安装wireguard后会有一个wg命令,可以在openwrt上使用这个命令创建密钥对。也可以在电脑或手机上的wireguard软件上生成。在wireguard中,一个节点叫做一个peer,需要为每个peer创建公钥私钥密钥对。
根据自己的情况,可以建个目录用来保存密钥。
root@OpenWrt:~# mkdir wireguard
root@OpenWrt:~# ll
drwxr-xr-x 2 root root 3488 Jan 16 13:29 wireguard/
root@OpenWrt:~# cd wireguard/
同时创建一对公钥私钥,它们是以文件的形式保存下来的,文件名可以自己定义。此例中op_privatekey文件是私钥文件,op_publickey文件是公钥文件。
root@OpenWrt:~/wireguard# wg genkey | tee op_privatekey | wg pubkey > op_publickey
查看生成的密钥文件。一对密钥用于一个peer,下面显示的密钥将要用于openwrt路由器。
root@OpenWrt:~/wireguard# ll
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_publickey
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_privatekey
再创建一对密钥对,用于手机的。
root@OpenWrt:~/wireguard# wg genkey | tee android1_privatekey | wg pubkey > android1_publickey
root@OpenWrt:~/wireguard# ll
-rw-r--r-- 1 root root 45 Jan 16 13:42 android1_privatekey
-rw-r--r-- 1 root root 45 Jan 16 13:42 android1_publickey
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_privatekey
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_publickey
还可以创建一个预共享密钥,但我这里没有将预共享密钥配置到wireguard连接上。
root@OpenWrt:~/wireguard# wg genpsk > op_sharekey
Warning: writing to world accessible file.
Consider setting the umask to 077 and trying again.
出现的提示是说当前目录的权限可能会出现安全隐患,可以使用umask 077改变当前目录的umask。但是不做这些修改也能使用。
root@OpenWrt:~/wireguard# umask 077
root@OpenWrt:~/wireguard# rm op_sharekey
root@OpenWrt:~/wireguard# wg genpsk > op_sharekey
root@OpenWrt:~/wireguard# ll
-rw-r--r-- 1 root root 45 Jan 16 13:42 android1_privatekey
-rw-r--r-- 1 root root 45 Jan 16 13:42 android1_publickey
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_privatekey
-rw-r--r-- 1 root root 45 Jan 16 13:32 op_publickey
-rw------- 1 root root 45 Jan 17 22:31 op_sharekey
这些密钥文件可以使用cat命令查看里面的内容,在之后页面配置wireguard时,将密钥文件中的内容粘贴到相应的地方。
root@OpenWrt:~/wireguard# cat op_privatekey
oLqF2Nx/ghS5hkkls3k35GA3lkncHRUJGdWjnbwG2978
新建wireguard接口
wireguard接口是一个虚拟接口,可以把它看成是openwrt路由器上的LAN接口,都是用于连接内网的设备。wireguad连接完成后,另一端的设备相当于直接连接在openwrt路由器的wireguard接口上,wireguard接口和另一端的设备是同一个网段的,就像电脑连接在openwrt的LAN口时是同一个网段一样。
网络—接口—添加新接口
新接口的名称:自定义,这里填wg0
新接口的协议:选择WireGuard VPN
提交之后生成接口,然后再对接口进行配置。
网络—接口—wg0—基本设置
协议:
私钥:openwrt这端的私钥
监听端口:wireguad监听的端口,另一端连接时就是连接到这个端口
IP地址:wg0接口的IP
私钥填写openwrt路由器这端的私钥。之前已经在openwrt命令行创建用于openwrt的公钥私钥、用于手机的公钥私钥,在命令行中使用cat命令查看密钥文件的内容,然后复制粘贴到页面上的相应位置。查看op_privatekey文件的内容,将内容粘贴到这里。
wireguad接口的IP和LAN口IP的作用一样,作为其他设备的网关,选择一个不冲突的网段就行了。我这里配置为10.255.1.1/24,10.255.1.1是IP,/24是这个IP的掩码。因为wireguard接口将要作为网关使用,其IP的掩码不能是/32。而手机作用一个单独的设备,手机上wireguad接口的IP可能必须配置为/32的掩码。
网络—接口—wg0—高级设置
开机自动运行:
使用内置的IPv6管理:
强制链路:
跃点数:
最大传输单元:即接口的MTU,可按上面的提示配置成1420
防火墙标识:
i> wireguard接口的最大传输单元(MTU)和openwrt的WAN口一样需要做特殊设置,不应该使用默认的1500。openwrt的WAN口需要做PPPoE拨号,wireguard接口需要做隧道连接,它们都不是传输纯以太网数据帧,需要调小它们的MTU,以防止某些应用无法正常使用,如FTP、HTTP流量。但不要设置得太小,要不然会影响传输效率。一般按页面上的提示进行设置即可,如WAN口的MTU设置为1492,wireguard接口的MTU设置为1420。
网络—接口—wg0—防火墙设置
可以将wg0接口加入到openwrt防火墙的lan区域,我这里为wg0接口新建了一个名为wg的防火墙区域。
配置peer
在wg0接口的界面下,有个Peers配置。Peer就是要和本端建立wireguard隧道的对端设备。
默认没有配置Peer,点击下面的“添加“按钮进行添加。
公钥:填写手机端的公钥,在openwrt命令行使用cat命令查看android1_publickey文件的内容
预共享密钥:在openwrt和手机填写的是相同的预共享密钥
允许的IP:填写对端的IP,这些填写的对端的IP才可以通过wireguard隧道进行传输
路由允许的IP:选择后,openwrt会在路由表中为这个peer添加一条路由
端点主机:如果对端设备没有公网IP,或者没有静态公网IP,可以不填写
端点端口:
端点,即end point,指的是对端。站在openwrt的角度看,端点就是手机。
上图中配置了预共享密钥,之后我删除了,也是可以连接的。
i> 在我这个例子中,openwt和手机都获得了公网IP地址,但都是动态IP。openwrt可以使用DDNS技术将域名和IP绑定,当IP改变时,域名解析可以跟着改变,所以openwrt这端的IP可以看成是固定的。而手机的IP是不确定的,因此不能在配置阶段将手机的IP写到openwrt的配置中。因为openwrt不知道手机的IP,所以只能由手机向openwrt发起连接。手机的配置中填写openwrt的域名,在建立wiregurad连接时通过域名可以查询openwrt的IP,对于手机来说,对端的openwrt的IP是已知的。一般在建立VPN时,至少有一端是公网IP,而且是固定IP。
配置openwrt的防火墙
上面已经配置了openwrt上的wireguard监听8101端口(UDP端口),这是对端的wireguard所连接的端口,因此需要在openwrt的公网接口上允许公网可以连接此端口。
网络—防火墙—通信规则—打开路由器端口,新建一个通信规则。名称自定义,协议选择UDP,外部端口使用openwrt上未被占用的端口。
网络—防火墙
我这里使用wireguard的目的就是使远程设备可以访问私网,因此需要配置openwrt防火墙的wg区域和lan区域之间可以互访。在“wg => lan“这个条目中,入站数据、出站数据、转发都配置为”接受“。
点击wg防火墙区域的“修改“按钮可以查看这个条目的详细信息。
允许转发到目标区域:选择lan,表示wg区域可以转发到lan区域
允许从源区域转发:选择lan,表示可以从lan区域转发到wg区域
如果wireguard对端设备需要访问wan区域,就在“允许转发到目标区域”再把wan区域选上。在我的环境中,并不需要手机通过openwrt上网,但需要可以连接到光猫,而光猫是划入wan区域的,因此wg区域配置为可以访问wan区域。
手机的配置
在我的场景中,手机作为一台单独的设备连接回家里的私网,手机在wireguard中可以看成是一个客户端。这种场景类似IPsec中的easy VPN模式。
手机需要下载wireguad软件。可以在应用应用商店搜索,或者到wireguard官网下载。
在手机打开wireguard后,点击右下角的加号,添加一个新的配置。
手动创建连接
默认只有本端(手机端)的接口信息,点击“添加节点”后,再输入对端(openwrt路由器)的信息。
接口/Interface,即手机端的信息
名称:自定义
私钥:手机端的私钥,通过查看上面创建的android1_privatekey文件获得
公钥:输入私钥后,公钥会自动根据私钥生成,无法手动输入
局域网IP地址:分配给手机的IP
监听端口:可以不填
DNS服务器:需要通过对端上网的话,可以填写
MTU:可以不填
节点/Peer,即对端openwrt路由器的信息
公钥:对端openwrt的公钥,通过查看上面创建的op_publickey文件获得
预共享密钥:可以不填,如果填写则要与openwrt上的要一致
连接保活间隔:
对端:对端的公网IP和端口,可以使用域名
路由的IP地址(段):指定哪些IP或者IP地址段会通过wireguard传输
节点/Peer中的“对端”要填写 openwrt的公网IP ,如果对IP做了域名解析,可以填写域名,IP或域名后面加上openwrt监听的端口。因为只有openwrt的公网IP是确定的,所以只能由手机端发起连接。
节点/Peer中的“路由的IP地址(段)”填写 openwrt上存在的IP或网段 ,访问这些IP时,会通过wireguard传输。其他IP会走默认路由,如访问互联网。
建立wireguard连接后,这些IP或网段会被导入到本端的路由表中。如果本端是Windows电脑,可以使用route print命令查看被wiregurad导入的路由。
使用配置文件进行配置
使用配置文件进行配置,需要先写好配置文件,以.conf为扩展名,如abc.conf。以下为配置文件的例子。
[Interface]
#分配给本端的IP
Address = 10.255.1.2/32
#本端的私钥
PrivateKey = ODMi+BbwVxgb5vshvWP6f5Pz3UqVE=
#DNS
DNS = 119.29.29.29
[Peer]
#对端的公钥,这里是openwrt的公钥
PublicKey = miT4cd6SOw9mVdXL8Enjzx2l+BDzyvrg4=
#需要通过wireguard隧道传输的IP或网段
AllowedIPs = 10.255.1.0/24,10.0.16.0/24,10.0.0.0/16
#预共享密钥,两端要一致
PresharedKey = Pu5xBEBmz9ghh7nuLwxJJUgNk3EljFVo=
#对端的公网IP(域名)和端口
Endpoint = abc.com:8101
#连接保活间隔
PersistentKeepalive = 25
创建好配置文件后,将文件保存到手机,在手机的wireguard中新建连接时,选择“导入配置或压缩包”,在手机中找到配置文件,选择后就可以导入配置了。最后保存配置即可。
连接
在手机wireguard中点击连接名称右边的开关即可连接。
查看状态
在openwrt菜单“状态—WireGuard状态“可以看到wireguard连接状态。
如果“上次握手“显示”从不“,已接收和已发送都显示0,有可能是连接没有成功,或者连接成功了,但还没有流量通过wireguard隧道。尝试连接内网中的设备进行测试,有流量通过后就会显示握手时间和发送、接收的流量。
在openwrt命令行中,使用wg命令查看。
root@OpenWrt:~/wireguard# wg
interface: wg0
public key: miT4cd6SOw9Gex2l+BDzyvrg4=
private key: (hidden)
listening port: 8101
peer: /6BTDGDPUKylTc=
endpoint: [240e:453::72e6]:54749
allowed ips: 10.255.1.2/32
latest handshake: 18 seconds ago
transfer: 100.45 KiB received, 272.60 KiB sent