使用 Nebula 搭建点对点的虚拟私有网络

2024-08-06#VPN#内网穿透#Nebula

Nebula 是一款可扩展的叠加网络( Overlay Networking )工具,专注于性能、简洁性和安全性,是一个基于 Noise 协议框架 的相互认证的对等(Peer-to-Peer, P2P)软件定义网络。它使用 UDP 打洞技术,可以在多数防火墙或网络地址转换(NAT)之后建立连接,也就是可以进行内网穿透。通俗来说,Nebula 可以将多台异地的主机组建为一个虚拟网络,使它们互相连通。

Nebula来自于 Slack 的开源软件,使用 Go 语言编写,是跨平台的。在 Linux、Windows、macOS、Freebsd等平台,可直接在其 Github Releases 页面下载可执行文件,然后在命令行配置和使用。对于移动端,需要从 Google PlayApp Store 下载应用。

Nebula 的官方文档有一篇 快速上手指南,是初次使用 Nebula 的首选文档。以下介绍在 Linux 服务器和 macOS 上使用 Nebula 搭建私有网络。

前提要求 🔗

在使用 Nebula 时,需要有一台叫做 Lighthouse (灯塔)的服务器,它是可被其他设备访问的。通俗来说,如果是在公网搭建叠加网络,那么这个 Lighthouse 需要有一个公网的 IP,并且在防火墙打开 4242/UDP 端口。

其他主机作为普通节点,可以位于NAT之后(即内网之中)。

下载可执行文件 🔗

首先从 Github Releases 下载并解压平台对应的可执行文件压缩包。然后解压,得到 nebula-certnebula 两个可执行文件,前者用于生成签名文件,后者用于运行 Nebula。将这两个文件移动到 PATH 中的某个目录里,即让系统可以查找到这两个可执行文件。

准备证书颁发机构(CA) 🔗

创建一个目录,用于存储证书等配置信息。比如 $HOME/.nebula,然后在该目录下创建证书和密钥(新创建的证书和密钥文件分别为 ca.crtca.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 的文档,假定有三台主机,分别叫做 lighthouse1laptopserver。于是创建三个组:

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.crtca.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_maplighthouse

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 🔗

  1. 在 Lighthouse 服务器上下载可执行文件,并添加到系统查找路径中。
  2. 在 Lighthouse 服务器创建配置目录 /etc/nebula
  3. 将以下文件上传到 Lighthouse 服务器的 /etc/nebula 目录:
    • config-lighthouse.yaml
    • ca.crt
    • lighthouse1.crt
    • lighthouse1.key
  4. /etc/nebula 目录下,重命名配置文件:
mv config-lighthouse.yaml config.yaml
mv lighthouse.crt host.crt
mv lighthouse.key host.key
  1. 启动:
nebula -config /etc/nebula/config.yaml

Nebula 默认会监听 4242/UDP 端口,因此需要确保 4242/UDP 端口可被其他主机访问。在 Ubuntu 上,可使用 utw 查看和修改防火墙配置:

ufw status # 查看防火墙配置
ufw allow 4242/udp # 打开 4242/udp

运行主机 🔗

  1. 同样地,在 Lighthouse 服务器上下载可执行文件,并添加到系统查找路径中。
  2. 同样地,在 Lighthouse 服务器创建配置目录 /etc/nebula
  3. 将以下文件放在主机服务器的 /etc/nebula 目录:
    • config.yaml
    • ca.crt
    • server.crt
    • server.key
  4. /etc/nebula 目录下,重命名配置文件:
mv config-lighthouse.yaml config.yaml
mv server.crt host.crt
mv server.key host.key
  1. 启动:
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。其内容如下所以,注意 CapabilityBoundingSetAmbientCapabilities(参考链接: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 配置的很小一部分。在真实场景使用时,还应该阅读更多的文件,查看详细的配置参考


加载中...