本文及资源最后更新时间 2022-04-04 by sky995
官网:https://www.defined.net/nebula/
程序下载:https://github.com/slackhq/nebula/releases
官方简介:Nebula是一种覆盖网络工具,旨在快速、安全和可扩展。使用可跨任何IP网络工作且无需打开防火墙端口的按需加密隧道连接任意数量的主机。
官方教程:
- 快速开始:https://www.defined.net/nebula/quick-start/
- 共享局域网设备:https://www.defined.net/nebula/unsafe_routes/
我的 Nebula CA 证书过期了,当初没有指定有效期,结果默认是一年……所以现在不得不重新生成证书。顺便把我的过程记录一下供大家参考。
我的网络拓扑:
笔记本位于不特定位置,可以访问互联网。路由器和台式机在家里。hu60.cn云服务器在华为云,并且有静态IP。
需求是:无论笔记本在哪里,都可以通过台式机的局域网IP地址(192.168.31.2)连接到台式机。
其中,192.168.31.*/24
是路由器的内网网段,10.98.76.*/24
是我准备在nebula虚拟局域网中使用的网段。
CA证书
Nebula使用证书进行身份认证,所以需要创建一个根证书,然后由它签发一系列设备证书。和Tinc不同,Nebula不需要把设备证书复制到每个机器上,只需要在自己的机器保留即可,但是CA证书需要复制到每个机器上。如果添加了新设备,只需要用CA密钥签发一个新的设备证书给新设备用,它就能加入网络。
CA证书的密钥(ca.key
)应该保存在最安全的设备上,所以这里选择保留在笔记本上。所有其他设备的证书都由笔记本签发,然后复制到对应的设备中。
笔记本是Linux,x86_64架构,所以我下载nebula-linux-amd64.tar.gz,解压后得到nebula
和nebula-cert
程序,两者都是命令行程序。
打开终端,跳转到nebula-cert
命令所在文件夹,执行以下命令:
./nebula-cert ca -name "hu60" -duration 876000h0m0s
其中,hu60
是证书的名称,可自定义。876000h0m0s
是证书有效期(100年),设长一点防止过期。
设备证书
接着执行命令,签发各个设备使用的证书。签发证书的同时也指定了各个设备的网段:
# hu60.cn云服务器
./nebula-cert sign -name hu60web -ip 10.98.76.1/24
# 小米路由器,注意它比其他设备多了一个子网(-subnets),因为我们要共享这个子网里的设备,所以需要在这里指定
./nebula-cert sign -name miwifi -ip 10.98.76.2/24 -subnets 192.168.31.0/24
# 华硕天选笔记本
./nebula-cert sign -name tianxuan -ip 10.98.76.3/24
命令执行完后,文件夹里有以下文件:
ca.crt ca.key hu60web.crt hu60web.key miwifi.crt miwifi.key nebula nebula-cert tianxuan.crt tianxuan.key
请保管好所有.key
文件,不要外泄,否则虚拟网络可被黑入。
服务发现节点
服务发现节点的作用是帮助各个业务节点创建点对点UDP隧道,它不负责传输实际流量,详见这个帖子中的讨论。
服务发现节点需要公网IP,所以通常使用云服务器来担任。如果你的宽带有公网IP也行,不过要部署DDNS,连接时使用DDNS域名。
本次使用的服务发现节点是hu60.cn所在的云服务器,Linux系统,ARM64架构。使用的证书文件是hu60web.crt
和hu60web.key
。
因为是ARM64架构,所以下载nebula-linux-arm64.tar.gz并解压。x86_64服务器应该下载nebula-linux-amd64.tar.gz。
解压后得到nebula
和nebula-cert
程序,再把我们刚刚生成的证书文件ca.crt
和hu60web.crt
和hu60web.key
复制进去。注意不是ca.key
。
接下来创建一个配置文件hu60web.yaml
,内容如下:
pki:
# 证书文件
ca: ./ca.crt
cert: ./hu60web.crt
key: ./hu60web.key
lighthouse:
# 声明该节点为服务发现节点
am_lighthouse: true
interval: 60
listen:
# 监听IP和端口,主机防火墙/安全组需要放行
host: 0.0.0.0
port: 4242
punchy:
punch: true
tun:
disabled: false
# 虚拟局域网使用的虚拟网卡名称,主机需要支持TUN/TAP设备
dev: nebula
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
unsafe_routes:
# 共享局域网用的路由
- route: 192.168.31.0/24
via: 10.98.76.2
mtu: 1300
# 把距离(跳数、跃点数)设的大一点,这样如果设备在目标局域网里,就不会走Nebula
metric: 100000
logging:
# 日志等级
# panic, fatal, error, warning, info, or debug. Default is info
level: info
format: text
timestamp_format: "2006-01-02 15:04:05"
firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000
# 出方向防火墙(不限制)
outbound:
- port: any
proto: any
host: any
# 入方向防火墙(不限制)
inbound:
- port: any
proto: any
host: any
启动服务:
./nebula -config ./hu60web.yaml
局域网路由节点
因为非Server版Windows缺少路由和NAT能力,所以局域网路由节点只能选用Linux。我是放在小米路由器上的。
因为小米路由器是armv7l架构,所以下载nebula-linux-arm-7.tar.gz并解压。请根据你的设备选择要下载什么版本。
下载并解压,得到nebula
和nebula-cert
程序。不需要nebula-cert
程序,把nebula
程序和ca.crt
、miwifi.crt
、miwifi.key
文件上传到路由器,再编写miwifi.yaml
配置文件:
pki:
# 证书文件
ca: ./ca.crt
cert: ./miwifi.crt
key: ./miwifi.key
static_host_map:
# hu60.cn 代表服务发现节点的公网IP,如果你没有绑定域名,直接写IP也可以
"10.98.76.1": ["hu60.cn:4242"]
lighthouse:
# 声明该节点不是服务发现节点
am_lighthouse: false
interval: 60
hosts:
# 指明要使用的服务发现节点,注意填写的是虚拟局域网IP,不是公网IP,公网IP应该填写在上面的static_host_map里
- "10.98.76.1"
listen:
# 监听IP和端口,可随意设置。通常来说,防火墙不需要刻意放行这个端口,但是因为运行Nebula的本身就是路由器,它默认禁止任何流入流量,所以需要手动放行
host: 0.0.0.0
port: 4242
punchy:
punch: true
tun:
disabled: false
# 虚拟局域网使用的虚拟网卡名称,主机需要支持TUN/TAP设备
dev: nebula
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
logging:
# 日志等级
# panic, fatal, error, warning, info, or debug. Default is info
level: info
format: text
timestamp_format: "2006-01-02 15:04:05"
firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000
# 出方向防火墙(不限制)
outbound:
- port: any
proto: any
host: any
# 入方向防火墙(不限制)
inbound:
- port: any
proto: any
host: any
启动服务:
./nebula -config miwifi.yaml
可以看到,它自动连上了服务发现节点。
在服务发现节点ping一下它:
ping 10.98.76.2
是通的。
试试要共享的局域网IP:
ping 192.168.31.2
不通,说目的端口不可及。
此时就需要在小米路由器上配置防火墙规则了,命令如下:
# 允许IPv4转发,其实不必要,因为它是路由器所以肯定开了。如果你的Linux机器没开,需要执行
sysctl -w net.ipv4.ip_forward=1
# 给来自Nebula的流量启用网络地址转换(NAT)
iptables -t nat -A POSTROUTING -s 10.98.76.0/24 -d 192.168.31.0/24 -j MASQUERADE
# 防火墙放行来自Nebula虚拟网卡的流量
iptables -I FORWARD -s 10.98.76.0/24 -d 192.168.31.0/24 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# 防火墙放行4242端口(因为本身是路由器,默认禁止任何流入流量,所以需要手动放行。如果运行在非路由器的Linux主机上,通常不需要手动放行)
iptables -I INPUT -p udp -m udp --dport 4242 -j ACCEPT
执行完成后,原本ping不通的就能ping通了。注意:Windows默认禁ping,需要关闭Windows Defender防火墙才能ping。
对于小米路由器,把以下代码加入/etc/rc.local
(最后一行exit 0
之前)可以让Nebula开机自启动:
cd /data/nebula
./nebula -- -config ./miwifi.yaml
iptables -t nat -A POSTROUTING -s 10.98.76.0/24 -d 192.168.31.0/24 -j MASQUERADE
iptables -I FORWARD -s 10.98.76.0/24 -d 192.168.31.0/24 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT -p udp -m udp --dport 4242 -j ACCEPT
客户端
笔记本就是我们的客户端啦,在tianxuan.crt
的文件夹下创建tianxuan.yaml
配置文件:
pki:
# 证书文件
ca: ./ca.crt
cert: ./tianxuan.crt
key: ./tianxuan.key
static_host_map:
# hu60.cn 代表服务发现节点的公网IP,如果你没有绑定域名,直接写IP也可以
"10.98.76.1": ["hu60.cn:4242"]
lighthouse:
# 声明该节点不是服务发现节点
am_lighthouse: false
interval: 60
hosts:
# 指明要使用的服务发现节点,注意填写的是虚拟局域网IP,不是公网IP,公网IP应该填写在上面的static_host_map里
- "10.98.76.1"
listen:
# 监听IP和端口,可随意设置,防火墙不需要刻意放行
host: 0.0.0.0
port: 4242
punchy:
punch: true
tun:
disabled: false
# 虚拟局域网使用的虚拟网卡名称,主机需要支持TUN/TAP设备
dev: nebula
drop_local_broadcast: false
drop_multicast: false
tx_queue: 500
mtu: 1300
unsafe_routes:
# 共享局域网用的路由
- route: 192.168.31.0/24
via: 10.98.76.2
mtu: 1300
# 把距离(跳数、跃点数)设的大一点,这样如果设备在目标局域网里,就不会走Nebula
metric: 100000
logging:
# 日志等级
# panic, fatal, error, warning, info, or debug. Default is info
level: info
format: text
timestamp_format: "2006-01-02 15:04:05"
firewall:
conntrack:
tcp_timeout: 12m
udp_timeout: 3m
default_timeout: 10m
max_connections: 100000
# 出方向防火墙(不限制)
outbound:
- port: any
proto: any
host: any
# 入方向防火墙(不限制)
inbound:
- port: any
proto: any
host: any
把笔记本置于其他网络(比如手机流量开热点),启动Nebula:
./nebula -config tianxuan.yaml
呃,没有权限。那我们给它加一个权限:
sudo setcap 'cap_net_admin+ep' ./nebula
然后就能启动了。这样的好处是不用sudo,也不用输入密码。如果setcap
失败,你还可以使用sudo。
ping一下要共享的局域网设备看看:
可以ping通。
连一下远程桌面看看:
连上了,成功达成目标。