使用 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.ymlcp config.yml config-lighthouse.yamlcp 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.yamlca.crtlighthouse1.crtlighthouse1.key
- 在
/etc/nebula目录下,重命名配置文件:
mv config-lighthouse.yaml config.yamlmv lighthouse.crt host.crtmv lighthouse.key host.key- 启动:
nebula -config /etc/nebula/config.yamlNebula 默认会监听 4242/UDP 端口,因此需要确保 4242/UDP 端口可被其他主机访问。在 Ubuntu 上,可使用 utw 查看和修改防火墙配置:
ufw status # 查看防火墙配置ufw allow 4242/udp # 打开 4242/udp运行主机
- 同样地,在 Lighthouse 服务器上下载可执行文件,并添加到系统查找路径中。
- 同样地,在 Lighthouse 服务器创建配置目录
/etc/nebula。 - 将以下文件放在主机服务器的
/etc/nebula目录:config.yamlca.crtserver.crtserver.key
- 在
/etc/nebula目录下,重命名配置文件:
mv config-lighthouse.yaml config.yamlmv server.crt host.crtmv 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=NebulaWants=basic.target network-online.target nss-lookup.target time-sync.targetAfter=basic.target network.target network-online.targetBefore=sshd.service
[Service]CapabilityBoundingSet=CAP_NET_ADMINAmbientCapabilities=CAP_NET_ADMINType=notifyNotifyAccess=mainSyslogIdentifier=nebulaExecReload=/bin/kill -HUP $MAINPIDUser=nebulaWorkingDirectory=/etc/nebula/ExecStart=nebula -config /etc/nebula/config.ymlRestart=alwaysRestartSec=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 配置的很小一部分。在真实场景使用时,还应该阅读更多的文件,查看详细的配置参考。