FreeBSD WireGuard快速起步

警告

WireGuard VPN 是VPN协议,只是用来提供加密隧道,但是没有实现伪装。这意味着WireGuard设计时就没有考虑混淆,UDP协议特征明显,导致防火墙非常容易精准识别和阻断。

也就是说 安装部署WireGuard只提供加密通讯,但是无法 越过长城

WireGuard VPN 是一个易于部署和配置加密网络通道的VPN技术,在很多VPN应用中,WireGuard已经逐步取代了IPSec或OpenVPN。

WireGuard同时提供内核和用户空间实现。第一个WireGuard内核实现是在Linux内核提供的,现在也移植到FreeBSD以及其他BSD版本。

在FreeBSD中,WireGuard的内核模式部分通过 wireguard-kmod 软件包获得,而 WireGuard的主要用户空间实现则是一个golang应用,通过 wireguard-go 软件包获得。

备注

macOS 环境通过 Homebrew 也可以安装 WireGuard ,其中客户端名称也是 wireguard-go ,服务端也是 wireguard-tools

WireGuard网络配置由接口(interfaces)和对等点(peers)组成。每个interface由其私钥定义,peers则由公钥和允许使用的地址定义。这样就形成了一个使用加密密钥路由的网络(cryptokey routing)。

安装

  • 服务器端只需要安装 wireguard-tools ,这个软件包包含了 wireguard 软件包以及必要的管理WireGuard接口的 wg , wg-quick :

在服务器端安装 wireguard-tools
sudo pkg install wireguard-tools

配置

WireGuard服务器

备注

这里配置工作执行前, FreeBSD初始化 工作已经完成(创建了具有 sudo 权限的admin账号),以下操作使用 admin 账号完成。

  • 修改 WireGuard /usr/local/etc/wireguard 目录权限,以便 admin 用户(属于 wheel 组)能够读写该目录(该目录属于 root 和组 wheel )

修订 /usr/local/etc/wireguard 目录权限,允许 admin 用户读写
sudo chmod -R 770 /usr/local/etc/wireguard
  • /usr/local/etc/wireguard 目录中创建私钥,然后再根据生成的私钥创建公钥

创建服务器私钥以及对应公钥
cd /usr/local/etc/wireguard

# 创建 server_private.key 是要求文件是 600 属性
(umask 0077; wg genkey > server_private.key)

# 从服务器私钥生成服务器公钥
wg pubkey < server_private.key > server_public.key
  • 创建WireGuard服务器配置 /usr/local/etc/wireguard/wg0.conf

WireGuard服务器配置 /usr/local/etc/wireguard/wg0.conf
[Interface]
Address = 10.10.0.1/24
Address = fd86:ea04:1111::1/64
SaveConfig = true
ListenPort = 51820
PrivateKey = <your server private key here>

参数解释:

  • Address 是使用 10.10.0.0/24 网段的WireGuard接口,使用的服务器地址是 10.10.0.1

  • SaveConfig 设置接口shutdown时候保存WireGuard的运行时配置

  • ListenPort 设置WireGuard接口监听端口

  • PrivateKey 设置WireGuard服务器的私有密钥

WireGuard客户端

  • 配置WireGuard Client:

WireGuard客户端配置激活使用WireGuard服务器接口的公钥和公开IP地址信息来连接WireGuard服务器: 每个WireGuard客户端使用非服务器允许的唯一的公钥来创建tunnel

生成WireGuard Client密钥对,创建的方法和Server密钥对是一样的
cd /usr/local/etc/wireguard

# 创建私钥,我这里是在服务器上执行,保存归档在服务器上
# 实际创建也可以在客户端完成
(umask 0077; wg genkey > client-1_private.key)
wg pubkey < client-1_private.key > client-1_public.key

如果使用macOS上的 WireGuard 图形客户端(可以从App Store安装),则客户端GUI提供了一个自动生成客户端密钥对的功能:

../../../_images/wireguard_client.png

点击 Add Empty tunnel... 按钮

WireGuard 图形客户端会自动生成一个客户端密钥对(也就省却了前述的命令行生成)

../../../_images/wireguard_client-1.png

WireGuard 图形客户端添加Tunnels会自动生成客户端密钥对

  • 配置客户端 /usr/local/etc/wireguard/wg_client.conf

WireGuard客户端配置 /usr/local/etc/wireguard/wg_client.conf
[Interface]
PrivateKey = <client-1_private.key>
Address = 10.10.0.2/32, fd86:ea04:1111::2/128
DNS = 8.8.8.8

[Pvir]
PublicKey = <server_public.key>
AllowedIPs = 0.0.0.0/0
Endpoint = <server_public_IP>:51820
PersistentKvipalive = 30

备注

FreeBSD客户端配置我还没有验证,目前使用的客户端是 macOS 上 WireGuard 图形客户端

如果使用macOS上的 WireGuard 图形客户端,则在填写客户端配置类似如下( 图形客户端能够校验配置语法 非常方便):

WireGuard图形客户端配置
[Interface]
PrivateKey = <client-1_private.key>
Address = 10.10.0.2/32, fd86:ea04:1111::2/128
DNS = 8.8.8.8

[Peer]
PublicKey = <server_public.key>
AllowedIPs = 0.0.0.0/0
Endpoint = <server_publid_IP>:51820

参数解释:

  • PrivateKey : WireGuard客户端私钥

  • Address : 设置客户端使用的私有IP地址和子网,也就是WireGuard Tunnel中使用的地址

  • PublicKey : 设置为 服务器 的公钥

  • AllowedIPs : 指定允许链接到WireGuard VPN连接的IP地址和子网。这个值 0.0.0.0/0 所有IP地址和允许网络接口访问VPN连接

  • Endpoint : 设置为 WireGuard 服务器的公网(Internet) IP地址,也就是客户端将要连接的服务器IP

  • PersistentKvipalive : 每 30秒 发送数据包给WireGuard服务器来保持连接活跃

配置服务器

  • 将上文生成的客户端公钥配置添加到服务器的 /usr/local/etc/wireguard/wg0.conf

/usr/local/etc/wireguard/wg0.conf 添加客户端的公钥配置
[Interface]
Address = 10.10.0.1/24
Address = fd86:ea04:1111::1/64
SaveConfig = true
ListenPort = 51820
PrivateKey = <your server private key here>

[Peer]
# Client 1
PublicKey = <Client-1_public.key>
AllowedIPs = 10.10.0.2/32 , fd86:ea04:1111::2/128

这里的配置修订也可以通过命令行动态添加:

动态添加客户端
wg set wg0 peer <client-1_public.key> allowed-ips 10.10.0.2/32

启动服务器

  • 执行以下命令激活 wg0 以及配置服务器启动时启动 WireGuard :

启动WireGuard
# 设置激活WireGuard服务器接口 wg0
sudo sysrc wireguard_interfaces="wg0"

# 设置WireGuard在操作系统启动时启动
sudo sysrc wireguard_enable="YES"

# 启动WireGuard服务器
sudo service wireguard start

# 检查WireGuard服务状态
sudo service wireguard status

启动后检查状态输出类似:

wireguard 服务状态
interface: wg0
  public key: <server_public.key>
  private key: (hidden)
  listening port: 51820

peer: <client_public.key>
  allowed ips: 10.10.0.2/32

启动客户端

  • 启动客户端命令行:

启动WireGuard客户端
wg set wg0 peer <server_public.key> allowed-ips 10.10.0.0/24 endpoint <server_ip>:51820

此时客户端就会链接到服务器上

检查

  • 在服务器上再次执行 service wireguard status 就会看到状态更新: 显示出客户端的更新状态

wireguard 客户端连接以后的状态变化
interface: wg0
  public key: <server_public.key>
  private key: (hidden)
  listening port: 51820

peer: <client_public.key>
  endpoint: <server_public_IP>
  allowed ips: 10.10.0.2/32
  latest handshake: 6 seconds ago
  transfer: 7.28 KiB received, 124 B sent

这表明VPN连接已经建立

此时在客户端 ping 10.10.0.1 (也就是ping Tunnel的另一端地址),就会看到正常的echo返回,表明VPN工作正常。

警告

现在客户端还不能通过VPN访问Internet,还需要服务器上设置防火墙路由

设置防火墙

  • 修订 sysctl.conf 配置,激活IP forwarding:

启用IP forwarding
# 配置 sysctl.conf 启用IP forwarding
echo 'net.inet.ip.forwarding=1' | sudo tee -a /etc/sysctl.conf

# 使 sysctl.conf 配置生效
sudo sysctl -f /etc/sysctl.conf

# 这里输出会看到
# net.inet.ip.forwarding: 0 -> 1
激活包过滤防火墙
# 激活包过滤防火墙
sudo sysrc pf_enable="YES"

# 激活包过滤日志
sudo sysrc pflog_enable="YES"
  • 检查网络接口,执行 ifconfig ,可以看到如下输出:

ifconfig 输出
vtnet0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
	options=4c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,TXCSUM_IPV6>
	ether 56:00:05:44:d9:d3
	inet 100.68.56.112 netmask 0xffffc000 broadcast 100.68.63.255
	inet6 fe80::5400:5ff:fe44:d9d3%vtnet0 prefixlen 64 scopeid 0x1
	inet6 2001:19f0:c:aa7:5400:5ff:fe44:d9d3 prefixlen 64 autoconf pltime 604800 vltime 2592000
	media: Ethernet autoselect (10Gbase-T <full-duplex>)
	status: active
	nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
lo0: flags=1008049<UP,LOOPBACK,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 16384
	options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
	inet 127.0.0.1 netmask 0xff000000
	inet6 ::1 prefixlen 128
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
	groups: lo
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
wg0: flags=10080c1<UP,RUNNING,NOARP,MULTICAST,LOWER_UP> metric 0 mtu 1420
	options=80000<LINKSTATE>
	inet 10.10.0.1 netmask 0xff000000
	inet6 fd86:ea04:1111::1 prefixlen 64
	groups: wg
	nd6 options=101<PERFORMNUD,NO_DAD>

这里可以看到两个接口,一个是服务器的网卡接口,另一个就是WireGuard接口

  • 配置 /etc/pf.conf :

配置 /etc/pf.conf
ext_if = "vtnet0"
wg_if = "wg0"
set skip on lo

scrub in on $ext_if all fragment reassemble
nat on $ext_if from $wg_if:network to any -> ($ext_if)
pass in on $ext_if proto udp from any to ($ext_if) port 51820
pass quick on $wg_if
pass out keep state
  • 启动pf:

启动pf
# 启动pf
sudo service pf start

# 如果修订了pf配置,则可以动态加载
sudo pfctl -f /etc/pf.conf

参考