前言

多年前就有使用n2n的经验。
记得公司购买的戴尔R720服务器托管到电信机房,该机房启用了代理人防火墙,只有特定IP才能连接进来。
这样是提升了安全性,但对我们来讲,管理维护非常不便。
应对方案,就是安装n2n,电信机房的服务器可以连接到外部中心节点,通过和指定主机组网,方便运维。
当然,n2n是一个非常有用的软件,还可以实现vpn代理,内外穿透等功能,值得一玩。

supernode的安装启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 下载源代码
git clone https://github.com/ntop/n2n.git

# opensuse 系统,安装编译工具
sudo zypper install autoconf automake

cd n2n
sh autogen.sh
make

# 执行完以上命令,可以看到目录中已经生成了supernode和edge两个可执行文件
sudo cp supernode /usr/bin/
sudo cp edge /usr/bin

# 启动中心节点
supernode -p a-port_number

# 本地树莓派启动边缘节点的命令
sudo edge -c mynetwork -k mysecretpass -a 192.168.100.2 -f -l supernode-ip:supernode:port

很不幸,启动后报错,很明显,连不上supernode

1
07/Jan/2024 01:20:59 [edge_utils.c:1610] WARNING: supernode not responding, now trying [****]

为了排查原因,在supernode节点,执行抓包,之后重新启动edge边缘节点,从始至终,没有看到过来访问的数据包。

1
tcpdump port [supernode-port] 

这就很诡异了,纠结了半天,之后试着改变边缘节点的启动命令

1
2
3
4
5
6
7
8

# 增加S2参数,表示使用Tcp方式通信
sudo edge -c mynetwork -k mysecretpass -a 192.168.100.2 -f -l supernode-ip:supernode:port -S2

# 没想到立即成功了,最后打印
07/Jan/2024 01:27:00 [edge.c:1344] edge started
07/Jan/2024 01:27:00 [edge_utils.c:2596] [OK] edge <<< ================ >>> supernode

终于找到了原因,这套软件默认使用udp通信,中心节点的防火墙,只开放了对应端口的tcp协议,没有放开udp。
坑啊。。。
到这儿,仍然不能让我满意。
如果使用上面的命令组网,暴露在公网上,安全性太差了。
继续查看软件的说明文档,找到很多有价值的信息,对于提高安全和运行效率很有帮助。

Communities

Communities概念,用来指定虚拟网络,如果有多个网络,指定的名称必须不同。
community名称,由19个字节长度的字符和1个零字符结尾,结尾零字符不能是特殊符号(如 * + ? [ ] 等)。
为了充分利用字符空间,可以使用16进制的表达方式(如启动时使用”edge … -c $(echo -en ‘\x3a\x3b\x4a\x6a\xfa’) …”)。
如果写入配置文件,可以按照格式占位填充(如-c :;Jjþ)。
除了-c启动参数和配置文件,community(团体字)也可以赋值给N2N_COMMUNITY环境变量,以避免在命令行泄露。

  • 写入配置文件,如community.list, 一行配置一个,官方给出示例(可以使用#添加注释)。
    使用配置文件时,需增加启动参数 “-c community.list”

    1
    2
    3
    4
    5
    # community.list (a text file)
    -----------------------------------------------------
    myCommunity
    yourCommunity

  • community名称定义,支持正则表达式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    '.' Dot, matches any character
    '*' Asterisk, match zero or more of previous element (greedy)
    '+' Plus, match one or more of previous element (greedy)
    '?' Question, match zero or one (non-greedy)
    '[abc]' Character class, match if one of {'a', 'b', 'c'}
    '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} (feature is currently broken)
    '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z }
    '\s' Whitespace, \t \f \r \n \v and spaces
    '\S' Non-whitespace
    '\w' Alphanumeric, [a-zA-Z0-9_]
    '\W' Non-alphanumeric
    '\d' Digits, [0-9]
    '\D' Non-digits

    下面的配置内容 ,就使用了正则表达。

    1
    2
    3
    # community.list (a text file)
    -----------------------------------------------------
    myCommunity\d\d

正常情况下,community的名称由明文传送,仍然可以被嗅探窃取,此时最好打开Header Encryption, 即标头加密。
加密只对写入配置文件的固定名称的community有效(使用正则表达的community除外)。
打开Header Encryption的方式也很简单,在启动命令里,增加”-H”参数。

加密原理

n2n目前支持4种加密方式,均可以在启动命令中指定。

  • Twofish in CTS mode (-A2)
  • AES in CBC mode (-A3)
  • ChaCha20 (CTR) (-A4)
  • SPECK in CTR mode (-A5)
Cipher Mode Block Size Key Size IV length Speed Built-In Origin
Twofish CTS 128 bits 256 bit 128 bit -..O Y Bruce Schneier
AES CTS 128 bits 128, 192, 256 bit 128 bit O..+ Y Joan Daemen, Vincent Rijmen, NSA-approved
ChaCha20 CTR Stream 256 bit 128 bit +..++ Y Daniel J. Bernstein
SPECK CTR Stream 256 bit 128 bit ++ Y NSA

启动命令中,-k参数,用以提供秘钥,当然也可以使用N2N_KEY设置在环境变量中。

1
sudo N2N_KEY=mysecretpass edge -c mynetwork -a 192.168.100.1 -f -l supernode.ntop.org:7777

如果提供了秘钥,但没有指定加密方式(-A),则默认使用AES.
使用-A1,将放弃加密,明文传送,和省略-k的效果相同。

认证机制

为防止MAC地址欺骗,截止到目前,n2n提供的最新开发(dev)版本中,提供两种类型的认证方案供用户选择。

基于身份的认证方案

边缘节点启动后,首先向中心节点提交注册。
边缘节点随机生成一个唯一ID值,伴随REGISTER_SUPER类型的消息,一起向中心节点传送。
中心节点抽取ID值,和本地缓存的集合做比对,如果发现已经注册过,则返回REGISTER_SUPER_NAK类型的消息,客户端收到后马上报错。
已经注册成功的客户端,出现故障退出的情况,对应的ID值仍然会持续保存,失效时间大概为90s.
边缘节点的MAC地址和ID,并不是一个东西,MAC地址在组网成功的节点之间可以相互看到,但ID只有客户端和中心节点才能识别。
以上可以看出,基于ID值的认证只是一种最基础的方案,对于防范网络攻击和信息安全,作用很小~

基于用户名和密码的认证方案

这是一种高级认证方案,能极大保障通信安全,官方称为”Curve25519”.
用户名和密码充当私钥,使用工具包中提供的”tools/n2n-keygen”命令生成公钥,并将公钥传递给中心节点完成配对。

supernode(中心节点)准备

假设当前配置的用户名为logan,密码为007, 在supernode节点,使用工具生成公钥如下:

1
2
[user@machine n2n]$ tools/n2n-keygen logan 007
* logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG

要将命令执行的输出信息,拷贝到community.list配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# List of allowed communities
# ---------------------------
#
# these could either be fixed-name communities such as the following lines ...
#
mynetwork
netleo
* logan nHWum+r42k1qDXdIeH-WFKeylK5UyLStRzxofRNAgpG
* sister HwHpPrdMft+38tFDDiunUds6927t0+zhCMMkQdJafcC
#
# ... or regular expressions that a community name must fully match
# such as ntop[0-1][0-9] for communities from "ntop00" through "ntop19"
#
ntop[0-1][0-9]

...

上面的配置文件表明,虚拟网络netleo,下面有两个使用秘钥登录的节点,分别是logan和sister.
这样做的好处是,如果logan或者sister用户转移到mynetwork网络,只需要执行简单的剪切、粘贴操作,将这两行配置移位即可实现。

中心节点并不限制边缘节点使用相同的用户名,强烈建议区分使用不同的用户名(使用动态IP地址分配时,分配的IP也是基于用户名)。

当一个边缘节点用户使用新密码,或者被隔离删除,则可以操作community.list配置中对应的行,替换新生成的密码或删除。
操作更改后,需要重新启动超级节点或向管理端口发出”reload_communities”命令,以使超级节点重载配置。

联邦模式下,存在多个中心节点,当修改了一个中心节点的配置,需要同步到其他节点并执行重载动作。

为了在中心节点之间派生、共享私钥,基于用户名和密码的认证方案,需要使用-F参数,给中心节点指定一个联邦别名(也可以N2N_FEDERATION在环境变量中定义)。

Edge边缘节点准备

边缘节点使用-I指定用户名,-J指定密码。

1
[user@host n2n]$ sudo ./edge -l <supernode:port> -c netleo -I logan -J 007 <your additional parameters>

此时已自动开启了标头加密功能,只有流密码在安全性方面能够可靠地与此身份验证方案配合使用。
所以,需要添加额外的启动参数,-A4 (ChaCha20), -A5(SPECK), -k 添加秘钥。

边缘节点需要知道超级节点的公钥。
超级节点的公钥,也是由命令行工具生成,边缘节点使用-P参数,引用该公钥。

1
2
3
# 生成超级节点公钥的命令
[user@host n2n]$ tools/n2n-keygen -F secretFed
-P opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4

到这里,可以确定边缘节点的启动命令为:

1
[user@host n2n]$ sudo ./edge -l <supernode:port> -c netleo -I logan -J 007 -A5 -k mySecretKey -P opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4

以上,可以通过N2N_PASSWORD设置环境变量,防止密码泄露,同时,可以将所有配置参数存放到配置文件,方便管理。

使用配置文件

创建配置文件/etc/n2n/edge.conf, 内容形式如下(可以任意添加)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# automated edge configuration
# created by wisepkg.com
# on2024/01/08

# --community netleo

-c netleo
-k mySecretKey
-a 192.168.100.1
-f
-l supernode.ntop.org:7777
-I logan
-J 007
-A5
-P opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4
-S2

使用配置文件启动边缘节点

1
2
3

sudo edge /etc/n2n/edge.conf

在传入配置文件后,也可以增加其他配置参数

1
sudo edge /etc/n2n/edge.conf -z1 -I myComputer

配置文件也支持=标记,但两边不能有空格。

1
2
3
4
5
6
7
8
9
10
-c=netleo
-k=mySecretKey
-a=192.168.100.1
-f
-l=supernode.ntop.org:7777
-I=logan
-J=007
-A5
-P=opIyaWhWjKLJSNOHNpKnGmelhHWRqkmY5pAx7lbDHp4
-S2