使用 Nebula 搭建点对点的虚拟私有网络
Nebula 是一款可扩展的叠加网络( Overlay Networking )工具,专注于性能、简洁性和安全性,是一个基于 Noise 协议框架 的相互认证的对等(Peer-to-Peer, P2P)软件定义网络。它使用 UDP 打洞技术,可以在多数防火墙或网络地址转换(NAT)之后建立连接,也就是可以进行内网穿透。通俗来说,Nebula 可以将多台异地的主机组建为一个虚拟网络,使它们互相连通。
Nebula 是来自于 Slack 的开源软件,使用 Go 语言编写,是跨平台的。在 Linux、Windows、macOS、Freebsd等平台,可直接在其 Github Releases 页面下载可执行文件,然后在命令行配置和使用。对于移动端,需要从 Google Play 和 App Store 下载应用。
Nebula 的官方文档有一篇 快速上手指南,是初次使用 Nebula 的首选文档。以下介绍在 Linux 服务器和 macOS 上使用 Nebula 搭建私有网络。
前提要求 🔗
在使用 Nebula 时,需要有一台叫做 Lighthouse (灯塔)的服务器,它是可被其他设备访问的。通俗来说,如果是在公网搭建叠加网络,那么这个 Lighthouse 需要有一个公网的 IP,并且在防火墙打开 4242/UDP
端口。
其他主机作为普通节点,可以位于NAT之后(即内网之中)。
下载可执行文件 🔗
首先从 Github Releases 下载并解压平台对应的可执行文件压缩包。然后解压,得到 nebula-cert
和 nebula
两个可执行文件,前者用于生成签名文件,后者用于运行 Nebula。将这两个文件移动到 PATH
中的某个目录里,即让系统可以查找到这两个可执行文件。
准备证书颁发机构(CA) 🔗
创建一个目录,用于存储证书等配置信息。比如 $HOME/.nebula
,然后在该目录下创建证书和密钥(新创建的证书和密钥文件分别为 ca.crt
和 ca.key
):
nebula-cert ca -name "CSZ, Inc" -encrypt -duration 17531h
其中:
-name
执行证书机构(certificate authority)-encrypt
可给密钥增加密码保护,这样每次给新的主机签名时,都会被要求输入密码-duration
指定了证书的有效期,默认为1年。17531h
代表两年。
ca
子命令的更多的选项可使用 --help
选项查看:
nebula-cert ca --help
搭建 Nebula 网络 🔗
创建密钥和证书 🔗
参考 Nebula 的文档,假定有三台主机,分别叫做 lighthouse1
,laptop
和 server
。于是创建三个组:
nebula-cert sign -name "lighthouse1" -ip "192.168.100.1/24"
nebula-cert sign -name "laptop" -ip "192.168.100.5/24" -groups "laptop,ssh"
nebula-cert sign -name "server" -ip "192.168.100.9/24" -groups "servers"
其中:
-name
是证书的名字,通常是主机名。
在运行以上命令时,会使用前面创建的 ca.crt
和 ca.key
进行签名,生成三组证书和密钥,分别以 .crt
和 .key
为文件名后缀。
获取配置示例 🔗
Nebula 的源码里提供了一个配置示例,可作为 Lighthouse 和其他节点的配置起点。以下命令从 Github 下载配置示例,并复制为 config-lighthouse.yaml
作为 Lighthouse 的配置;复制为 config.yaml
作为其他主机的配置。
curl -o config.yml https://raw.githubusercontent.com/slackhq/nebula/master/examples/config.yml
cp config.yml config-lighthouse.yaml
cp config.yml config.yaml
配置 Lighthouse 🔗
修改 config-lighthouse.yaml
文件,设置 am_lighthouse: true
。尽管 Nebula 的文档 写到 Lighthouse 不需要配置 static_host_map
。但实际上不配置就会报错。因此也需要配置 static_host_map
:
static_host_map:
"192.168.100.1": ["x.x.x.x:4242"]
lighthouse:
am_lighthouse: true
其中:
x.x.x.x
是 Lighthouse 的可访问 IP。
注意配置模板的注释提到,对于 Lighthouse,lighthouse.hosts
必须为空。
配置主机 🔗
修改 config.yaml
文件,修改 static_host_map
和 lighthouse
:
static_host_map:
'192.168.100.1': ['x.x.x.x:4242']
lighthouse:
am_lighthouse: false
interval: 60
hosts:
- '192.168.100.1'
其中:
x.x.x.x
是 Lighthouse 的可访问 IP。
防火墙配置 🔗
防火墙配置可在 Lighthouse 和普通主机分别配置。在配置示例里,允许所有的出站流量,但只允许特定的入站流量:
firewall:
outbound:
# Allow all outbound traffic from this node
- port: any
proto: any
host: any
inbound:
# Allow icmp between any nebula hosts
- port: any
proto: icmp
host: any
如果需要更多的访问,那么就需要修改防火墙配置。防火墙的更多配置见文档。比如,如果想允许 SSH 访问,那么可以在入站流量中增加:
firewall:
# ...
inbound:
# ...
- port: 22
proto: tcp
host: any
运行 Nebula 🔗
运行 Lighthouse 🔗
- 在 Lighthouse 服务器上下载可执行文件,并添加到系统查找路径中。
- 在 Lighthouse 服务器创建配置目录
/etc/nebula
。 - 将以下文件上传到 Lighthouse 服务器的
/etc/nebula
目录:config-lighthouse.yaml
ca.crt
lighthouse1.crt
lighthouse1.key
- 在
/etc/nebula
目录下,重命名配置文件:
mv config-lighthouse.yaml config.yaml
mv lighthouse.crt host.crt
mv lighthouse.key host.key
- 启动:
nebula -config /etc/nebula/config.yaml
Nebula 默认会监听 4242/UDP
端口,因此需要确保 4242/UDP
端口可被其他主机访问。在 Ubuntu 上,可使用 utw
查看和修改防火墙配置:
ufw status # 查看防火墙配置
ufw allow 4242/udp # 打开 4242/udp
运行主机 🔗
- 同样地,在 Lighthouse 服务器上下载可执行文件,并添加到系统查找路径中。
- 同样地,在 Lighthouse 服务器创建配置目录
/etc/nebula
。 - 将以下文件放在主机服务器的
/etc/nebula
目录:config.yaml
ca.crt
server.crt
server.key
- 在
/etc/nebula
目录下,重命名配置文件:
mv config-lighthouse.yaml config.yaml
mv server.crt host.crt
mv server.key host.key
- 启动:
nebula -config /etc/nebula/config.yaml
注意,需要使用 sudo
运行。
验证 🔗
由于在防火墙配置上打开了 ICMP
,因此可以主机上 Ping 一下 Lighthouse,验证网络配置成功:
ping 192.168.100.1
在 Linux 服务器上以服务形式运行 Nebula 🔗
在 Linux 服务器上,可以使用 systemctl
管理系统服务。需要注意的是, Nebula 需要网络相关的管理员权限,因此需要特殊的设置。尽管可以使用 root
用户运行 Nebula,但基于最小权限原则,尽量不要使用 root
用户。我创建了一个专有的用户 nebula
,用于运行 Nebula:
useradd -r -s /bin/false nebula
然后将配置文件所在目录 /etc/nebula
的所有者修改为 nebula
:
chown -R nebula /etc/nebula
然后创建“单元文件” /etc/systemd/system/nebula.service
。其内容如下所以,注意 CapabilityBoundingSet
和 AmbientCapabilities
(参考链接:https://github.com/slackhq/nebula/issues/300) :
[Unit]
Description=Nebula
Wants=basic.target network-online.target nss-lookup.target time-sync.target
After=basic.target network.target network-online.target
Before=sshd.service
[Service]
CapabilityBoundingSet=CAP_NET_ADMIN
AmbientCapabilities=CAP_NET_ADMIN
Type=notify
NotifyAccess=main
SyslogIdentifier=nebula
ExecReload=/bin/kill -HUP $MAINPID
User=nebula
WorkingDirectory=/etc/nebula/
ExecStart=nebula -config /etc/nebula/config.yml
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
然后使用管理员,运行服务:
systemctl start nebula.service
检查服务进程,确保启动正常:
systemctl status nebula.service
如有异常,可以查看日志:
journalctl -f -u nebula.service
然后将其启用,使 Nebula 在系统启动时运行:
systemctl enable nebula.service
结尾 🔗
搭建 Nebula 还是比较简单和流畅的,但这也需要熟练命令行下的操作。本文参考的是快速上手指南,涵盖的只是 Nebula 配置的很小一部分。在真实场景使用时,还应该阅读更多的文件,查看详细的配置参考。