n2n是在数据链路层实现的一套P2P协议,包括super node 和 edge node。之前一直使用zerotier-one进行穿透,只是最近一直穿透不成功,因此就想试试n2n如何,这个n2n跟zerotier-one一样,可以实现把分布在全球各地的计算机穿透防火墙连接成一个局域网,这样可以把家里、公司等等的设备连接起来,达到互相访问的效果(局域网的体验)。

具体原理可以参看作者的论文http://www.n2n.org.cn/doc/n2n.pdf。而且最重要的是n2n是开源的,遵循GPL v3协议,可运行于Linux,Windows,Android,甚至是Openwrt之上。
在公司和家里研究了一天,编译、配置、部署,问题解决等,真是无语。
原生系统
搭建super node:搭建super node需要公网IP,但好在搭建super node 并不是必须的,我们也可以使用公用的super node,且不用担心使用公用super node 的安全性问题,因为两个edge的通信数据并不经过super node,具体原理参看论文及源码。
原版的n2n作者已经没有在维护,好在软件开源。全世界还有人在不断地维护着n2n,我在github上面找到一个维护得比较新的版本[github仓库],这个版本修改了V2,不同的是这里的V2为V2.1,大幅修改了n2n协议,不再与之前的n2n兼容,作者目的为了n2n v3做准备,也许不久的将来可以看到n2n v3的出现。
n2n v2.1编译过程
实验环境为ubuntu 18.04 LTS
$ sudo apt-get install git build-essential libssl-dev |
然后也可以在super node的服务器上建立 edge node,命令格式如下:
$ edge -d [tun name] -a [Local_IP] -c [net name] -k [key] -u 1000 -g 100 -l [supernode IP]:[supernode port] |
所有同一个n2n网络的net name和key必须一样,这样才能连接在一起。
一个实例:
$ edge -d edge0 -a 10.9.9.1 -c wisfern_n2n2s -k 12345 -u 1000 -g 100 -l n2n.lucktu.com:10088 -r |
搭建启动命令
搭建edge node:搭建过程与super node相同,只是最后启动edge node时配置好自己的IP就行
$ edge -d edge1 -a 10.9.9.10 -c wisfern_n2n2s -k 12345 -u 1000 -g 100 -l n2n.lucktu.com:10088 -r
$ ifconfig此时在此电脑上应该会看到类似下面的信息
edge1 Link encap:以太网 硬件地址 xx:xx:xx:xx:xx:xx
inet 地址:10.0.0.10 广播:10.0.0.255 掩码:255.255.255.0
inet6 地址: xxxx::xxxx:xxxx:xxxx:xxxx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1400 跃点数:1
接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
发送数据包:38 错误:0 丢弃:0 过载:0 载波:0
碰撞:0 发送队列长度:1000
接收字节:0 (0.0 B) 发送字节:6463 (6.4 KB)此时可以在edge所在的电脑上 ping 10.0.0.1 , 测试连通性。
搭建其他edge node :方法同上,注意配置不同的ip。然后edge间就可以没羞没躁地穿透层层NAT愉快地玩耍啦。
服务化
为了在linux上常驻,可以借助systemd或者supervisord,记录一下systemd的服务化过程。
编译好后的edge复制到/opt/edge,然后编写n2n.service文件。
# cat > /opt/n2n.service |
编写完成之后,部署到cp /opt/n2n.service /etc/systemd/system/,然后运行命令初始化和启动
# systemctl daemon-reload |
后续有精力再弄成deb包。
Docker容器
用docker的话,也有套路,找个位置记录下。
Dockerfile
FROM ubuntu:18.04 |
镜像构建
docker build -t docker_n2n:v2.1 . |
注意后面的.(点),表示当前目录。
构建完之后,可以把镜像推送到云容器镜像服务站(自行解决)。
启动方法
edge节点
# 1st edge node |
每个edge节点,-a后面的ip地址都不同,代表不同的本地网卡ip地址。-f表示前端输出。-r 表示数据转发。
超级节点必须部署在有公网的计算机上,并且放开 -l 后面指定的udp端口。
docker 容器
$ sudo docker ps |
网络信息
$ ip addr |
可能问题
连接后,ping得edge节点,但ping不通edge节点后面的内网机器。这里有两种可能的原因,一个是本机路由没有配置正确,第二个是防火墙和NAT转发没有配置正确。防火墙主要加入这样的两句到防火墙里面去。其中XXX是在edge后面带 -d 参数设置的网卡名。
iptables -t nat -A POSTROUTING -j MASQUERADE &
iptables -I INPUT -i XXX -j ACCEPTroute add -net 192.168.11.0/24 gw 10.0.0.11 &
帮助参考
$ sudo route add
Usage: inet_route [-vF] del {-host|-net} Target[/prefix] [gw Gw] [metric M] [[dev] If]
inet_route [-vF] add {-host|-net} Target[/prefix] [gw Gw] [metric M]
[netmask N] [mss Mss] [window W] [irtt I]
[mod] [dyn] [reinstate] [[dev] If]
inet_route [-vF] add {-host|-net} Target[/prefix] [metric M] reject
inet_route [-FC] flush NOT supportedwindows路由的添加有些不同,原理一样。
怎么设置 supernode 为我所独用?
假设自己使用的 n2n 是这样运行的(以n2nabc 账号)
edge -d edge0 -c n2nabc-k pwd -a 10.10.10.1 -l ip:10082
那么在 supernode 服务器上增加一条防火墙,监视 10082端口通过的字符串,只准账号中含有 n2nabc 字符的通过即可。
iptables -I INPUT 1 -pudp --dport 10082 -m string ! --string "n2nabc" --algo bm -jDROP