Hom's Blog


P2P网络-n2n穿墙

今天想把家里的网络弄成能在外部开放, 想利用路由器的DDNS和虚拟服务器功能来构建一个能在公网访问的功能. 然而, 多次尝试后不成功.

TPLINK注册用户后可以利用路由器动态DNS(DDNS)功能将固定IP地址绑定在用户名的网址上, 例如 username.tpddns.cn, 或者用内置的花生壳的功能也可以绑定在某个网址上. 通过最后的端口映射, 就是将局域网内某台电脑的分配IP固定起来后, 将其某个端口和这个公网IP的端口绑定, 外网访问该公网IP的端口就可以相当于和局域网某电脑通讯.

DDNS绑定的该网址可以被ping通, 然而, 这个网址对应的IP却和真正拨号的IP不一致! 用ip138查询获得的IP和ping的一致. 这说明这个DDNS绑定的IP是公网透明IP, 而我们的真正的网络IP相当于一个分配绑定的”局域网”IP. 而这个真正IP可以在本机访问, 在外网却ping不通. 经查询可以知道是一个保留地址, 是NAT(Network Address Translation)网络掩蔽后的共享地址. NAT是一种在IP封包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有IP地址访问因特网的私有网络中。192.168.x.x和10.x.x.x 都属于这类IP.

另外路由器还有一个功能叫DMZ主机, DMZ主机又叫对外网络(边界网络)主机, 其物理上处于局域网内网(例如路由器内), 所有端口可被外网访问, 而通过在DMZ主机上设置端口转发, 外网也能和局域网内其余主机通讯. DMZ主机可以被外网和内网访问. 严格的DMZ主机是无法直接访问内部网络的, 和内部网络分开, 保证了安全性. 但路由器的DMZ主机往往是以一种简单的方法将所有端口转发到另外的防火墙或NAT设备上。由于本路由器被NAT了, 因此这个DMZ功能也自然被NAT了.


为了解决NAT的问题, 办法就是实现NAT穿透, 也就是内网穿透(NAT-DDNS). 花生壳提供新花生壳软件穿透, 也提供如花生棒来实现硬件穿透, 当然, 也就不是免费的罗(即使免费肯定也一堆限制). 另一个办法就是申请固定IP而不是NAT的IP, 但这也是要额外收费的…

看到知乎上一个帖子如何远程登录家里的Ubuntu电脑(命令行模式)?, 里面提到另一种策略: P2P(peer-to-peer)的穿网. 另外有一种类似的, 通过第三方来进行通讯转发实现的策略. 这类都属于 TCP hole punching

TCP hole punching实现内网穿透.

  • P2P策略: 直接将两台主机连接通信, 不通过第三方中介. 例如这里介绍的N2N, 以及ZeroTier
  • 第三方中介策略: 利用第三方将两个网络接入后通信, 例如TeamViewer, VPN(两个网络都接入同一个VPS的VPN), ngrok.comn. ngrok就是其网站服务器作为第三方, 提供端口绑定不同计算机不同端口, 就是端口对端口, 觉得不安全也可以通过自己构建服务器.

ZeroTier 提供一个公网群, 任何计算机可以连接进去再和别的计算机直接沟通起来. 如果安全性不考虑的话, 还是很方便好用的, 也可以创建网络, 免费可以支持最多100设备连入(足够使用了吧…). 如果不是大公司, 这个方法基本就是免费咯. 但缺点就是毕竟有第三方, 所以不确认是否完全安全. 支持多个平台(win,osx,linux,ios,安卓), 客户端开源. 有空试用一下~ 因为我自己在外面有VPS, 所以使用N2N自己搭建更加安全些.


好了, 开始介绍这个N2N技术.

2008年,ntop的作者Luca Deri推出全新p2p VPN产品 – N2N。相对于hamachi,n2n最大的优势在于:

  1. 开源,任何人都可以检查代码,看看是否有猫腻,而hamachi是闭源的,LogMeIn是否会截获密钥不得而知,一旦截获密钥,就可以对流经hamachi服务器的数据包进行解码。n2n的加解密过程由edge node实现,只有两端的用户知道协商好的共享密钥,super node无从知晓。
  2. 灵活性,n2n允许用户在Internet上自行创建super node,也可以利用任何一个公开的super node。hamachi用户则必须登录到LogMeIn服务器才能创建隧道。

n2n支持的OS也非常广,Linux、FreeBSD、MAC OSX、甚至windows,不过由于n2n只提供源代码,需要用户自行手工编译。

n2n工作原理是如下图, 服务器端中心节点(supernode) 用于交流, 相当于一个”路由器”, 而边界节点(edge)就是每一台在网络中(可以是内网中)的主机. edge通过和supernode沟通后, 进入某个组的”局域网”, 当有同”局域网”(同组)的主机进行连接时, 两台主机就直接连接起来, 就像局域网内的两台主机一样. 在两台主机连接后, supernode任务完成, edge断开中心节点, 实现P2P的加密通信. 因此supernode并不参与两台主机间直接通信, 只是起到媒人的作用.

源代码和程序可以从其github库和官方svn库获得.

这个东东分两个版本, 两个版本核心处理不同, 因此不通用, 用apt安装的是1.x版本, 所以推荐客户端和服务器端都使用1.x版本.

PS: 不同发布版本的 n2n 可能也不通用. 所以要使 n2n 能成功, 第一要素是使用同一版本v1/v2 的n2n, 另一要素是使用相同发行版的n2n, 后面会提到

安装

APT傻瓜式安装

最简单ubuntu安装方法是:

sudo apt install n2n

如果使用sudo apt来安装, 安装后有 /usr/bin/supernode/usr/sbin/edge 两个文件新生产, 且生成两个相关文件 /etc/default/n2n/etc/init.d/n2n , 前者是配置参数, 后者是服务文件.

PS:

  • 使用apt安装的版本是 n2n v.1.3.2 for x86_64 (2016.9.19)
  • 使用apt安装的版本编译时间是2014年, 对后面的Window下GUI客户端兼容
  • 使用apt安装, 在我测试的vps中的Ubuntu14并没有自动加载服务的东东, 而自己安装的Ubuntu16上具有

源码安装 from SVN

另外也可以svn或github获得源码来安装. 官方的提供原处是SVN库. SVN库版本是官方发布版, 对市面上的GUI客户端兼容较好.

缺点是, 由于太旧了, 我在ubuntu16上面编译n2n_v2后的edge不能正常使用. 如果你能正常编译后, 使用./edge --help没有出现segmentation fault, 那恭喜你~

sudo apt-get install subversion cmake build-essential libssl-dev
svn co https://svn.ntop.org/svn/ntop/trunk/n2n
## or use github
# git clone https://github.com/meyerd/n2n.git
cd n2n/n2n_v2
make
### If you want to install it to /usr/bin, use following
# sudo make install

Github上也有一些老的库是folk的SVN版本. 可自行搜索.

另外, 官方还有以下一篇BlogHow to enable broadcast and multicast support on Amazon (AWS) EC2介绍安装使用n2n. 里面和传统做法不同的是, 取消了内容加密(n2n_v2下Makefile中修改为N2N_OPTION_AES=no)和内容压缩(n2n_v2下n2n.h中修改为#define N2N_COMPRESSION_ENABLED 0). 不知道取消加密和压缩后能不能解决上述问题, 但不推荐这样做, 不安全且流量大.

从github下载安装v2版本

meyerd的库是有更新的, 里面修正得也更好, n2n_v2 在 Ubuntu16中使用gcc5+ 编译也没问题. 因此强烈推荐.

git clone https://github.com/meyerd/n2n.git
### for fatal error: openssl/aes.h: No such file or directory : to install libssl-dev
sudo apt install cmake libssl-dev
cd n2n/n2n_v2
mkdir build
cd build
cmake -build . ..
make

# Install tunctl to create virtual tun device
sudo apt install uml-utilities
sudo tunctl -t tun0
./edge -d n2n0 -c community -k encryptme -u 99 -g 99 -m MAC_address_01:02:03:04:05:06 -a 10.1.2.1 -l 88.86.108.50:86
# 2N_KEY=encryptme ./edge -d n2n0 -c community -u 99 -g 99 -m MAC_address_01:02:03:04:05:06 -a 10.1.2.1 -l 88.86.108.50:82

对于Unix类系统, 使用github这个库编译安装问题并不大. 问题在于Window版本.

在市面上流行的window n2n客户端(包括n2nedgeguin2nguien)使用的都是内核为官方旧版的n2n edge, 如果使用github上最新版编译的supernode和旧版的进行通信, edge 会die掉, 无法进行通信. 因此, 如果使用github新版本编译的supernode作服务中心, 那么window上客户端也需要重新编译edge版本.

Window下源码安装编译n2n

我这里使用的是github 新版本的n2n, 更稳定.

下载新版本的源代码. 解压后得到n2n-master 文件夹. 再在该文件夹下操作. 这里以n2n_v2 为例. 官方的安装说明可以参考这里

第一步, 很重要, 安装cmake. 这里根据自己需求来下载啦, 例如CMAKE-V3.6.2 的32位win版本安装器点这里. 这里注意, 必须要先卸载掉旧版本的cmake才能安装新版本. 如果使用VS编译, 可以使用64位的cmake, 这里我主要使用mingw, 所以采用32位.

第二部, 采用编译工具编译, 例如Visual Studio或者Mingw.

VS由于我个人不太喜欢 (太大启动太慢), 所以电脑没有安装, 因此就没有测试, 官方以VS 2010版本的为例:

C:\n2n> mkdir build
C:\n2n> cd build
C:\n2n\build> cmake -G "Visual Studio 10" --build .\ ..\
-- Check for working C compiler using: Visual Studio 10
-- Check for working C compiler using: Visual Studio 10 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler using: Visual Studio 10
-- Check for working CXX compiler using: Visual Studio 10 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/n2n/build

这里重点使用mingw, 这里和官方安装指导方法不同.

  • 先安装好mingw, 下载后是GUI安装器(很小), 运行后会先安装mingw-get用于安装组件, 随后会让你选择要安装的内容. 确保安装mingw-basse和gcc-g++等也就够了. 这个缺了的话还是可以通过安装器再次安装和更新的.
  • 运行mingw中msys的bash shell, 例如默认安装位置下是C:\MinGW\msys\1.0\msys.bat. 推荐创建桌面快捷方式.
  • 尝试运行cmake, 直接敲cmake回车. 如果已经安装cmake还说没有, 请将cmake路径加入到搜索路径当中 (右键我的电脑, 属性, 高级系统设置, 环境变量, 双击编辑用户变量中的PATH, 加入cmake路径(例如32位是C:\Program Files (x86)\CMake\bin)). 请确保解决cmake可以直接执行.
  • 跑到解压后的n2n_v2 文件夹, 例如cd /c/Users/Username/Desktop/n2n/n2n_v2. 或者更简单使用下面msys here的方法到达文件夹.
  • 执行cmake -G "MSYS Makefiles" --build ./ ../, 使用MSYS编译链配置来进行cmake编译. (网上有说用MINGW Makefiles, 但我试过失败, 参见最后的附录部分). 如果成功的话有下面类似的配置编译内容. 完成后make来编译, 并./edge --help 来测试一下即可.
$ cmake -G "MSYS Makefiles"  --build ./ ../
-- The C compiler identification is GNU 5.3.0
-- The CXX compiler identification is GNU 5.3.0
-- Check for working C compiler: C:/MinGW/bin/gcc.exe
-- Check for working C compiler: C:/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done

CMake Warning (dev) at CMakeLists.txt:95 (add_executable):
#  Policy CMP0037 is not set: Target names should not be reserved and should
#  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
#  details.  Use the cmake_policy command to set the policy and suppress this
#  warning.
#  The target name "test" is reserved or not valid for certain CMake features,
#  such as generator expressions, and may result in undefined behavior.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/zhaozx/Desktop/n2n-master/n2n_v2/build

PS : 配置右键可以运行msys的shell并转到该文件夹目录:

第一步, 创建一个文件txt, 改名例如叫msys.reg. 一定要.reg 作后缀. 编辑文件内容(右键编辑), 黏贴以下内容并保存后, 双击加载该注册表文件即可将msys here加入右键.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\Background\shell\msys]
@="Open msys Here"

[HKEY_CLASSES_ROOT\Directory\Background\shell\msys\command]
@="C:\\MinGW\\msys\\1.0\\msys.bat"

第二步, 直达文件夹. 默认下右键打开的shell是到~用户目录下. 要修改其配置文件(默认安装时位置): C:\MinGW\msys\1.0\etc\profile

在最后一行, 注释掉cd "$HOME"#cd "$HOME". OK, enjoy.

Mac

在10.10 Yosemite和10.9的系统应该没问题 (10.10 我测试成功过). 经测试 (2016.10.25), 暂时Mac不能在El Capitan正常使用edge.

这里介绍在苹果系统里的安装:

  • 装上 brew (自行百度)
  • 复制github源码git clone https://github.com/meyerd/n2n.git
  • 安装 openssl 安全通讯: brew install openssl
  • 编辑n2n_v2/CMakeLists.txt 文件, 找到set(CMAKE_C_FLAGSset(CMAKE_CXX_FLAGS 两行
  • 在这两行的里面括号里面的部分, 加入编译参数-I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib
  • n2n_v2 创建 build 文件夹, cmake .. 来创建Makefile, 然后make
  • brew cask install tuntap 安装tuntaposx
  • ./edge -c community -k passwd -l 12.34.56.78:86 -a 10.2.2.22 尝试连接一下. 如果成功, 可以复制cp ./edge /usr/local/bin 后续可以参考Ubuntu等的执行教程.

然而, 在El Capitan 执行 edge的时候, 始终无法创建虚拟网卡 : ERROR: Unable to open tap device. 这个问题在Yosemite里面可以通过安装tuntaposx来实现 (上述过程直接brew cask install tuntap安装), 但是只支持10.9和10.10, 不支持10.11的El Capitan.

经研究, 即使关闭那个10.11新的System Integrity Protection (SIP)服务 (重启cmd+R进入网络恢复, 然后命令行输入csrutil disable), 依然不行, 尝试启动tuntaposx的扩展服务, 报错:

$ sudo ifconfig tap0 up
$ ifconfig: interface tap0 does not exist
$ sudo ifconfig tap0 create
$ ifconfig: SIOCIFCREATE2: Invalid argument

/dev/tap0里是有tap0道15, tun0到15的, 但是却依然不识别. 再进一步考察, 其实是以下两个kext并没有真正加载

/Library/Extensions/tap.kext
/Library/Extensions/tun.kext
# Check the shasum of installed files.
find /Library/Extensions/{tap,tun}.kext/ -type f | xargs shasum
# Load the kext
/sbin/kextload /Library/Extensions/tap.kext

…. *.kext failed to load - (libkern/kext) not privileged tuntap

最后确认是作者并没有在新系统对程序进行签名所导致..

最后只能卸载咯..

brew cask uninstall --force tuntap
# Delete the installed file if it exists.
sudo rm -rf /Library/Extensions/tap.kext
sudo rm -rf /Library/Extensions/tun.kext
sudo rm -rf /Library/LaunchDaemons/net.sf.tuntaposx.tap.plist
sudo rm -rf /Library/LaunchDaemons/net.sf.tuntaposx.tun.plist

配置服务器端

安装好后, 直接运行supernode -l port 就可以了, port就是服务器端口号, 就是后面用的822. 如果要详细信息就用-v选项.

Ubuntu参考手册: supernode - n2n supernode daemon

配置服务器端的背景服务 (自己仿改的, 需要自己修改SNPORT端口部分, 貌似那些stop什么的不好使..停掉就ps -ef | grep supernode 再手动kill吧..)

更新:请勿参考!! 另外, 可以参考附录1, 创建这个supernode可执行文件, 放到/etc/init.d/supernode, 然后sudo update-rc.d supernode defaults 就可以创建各种级别服务了 开启服务: sudo service supernode start. 但貌似还是有点问题.

不喜欢创建的话, 可以找一些公共中心节点也是可以的(理论上也是安全的, 但有时候udp打动不通会通过supernode来转发, 那就不知道咯), 例如remoteqth.com:82. 不过可能由于版本问题, 时间问题等原因, 很多都挂了. 最好还是自己搭建吧.

服务器端命令是比较简单的, 但如果想要获得服务运行的信息, v1和v2是不同的, v2 中只有加入-f选项才能获得运行信息. 以下是v2版本, 创建一个可执行sh文件来背景运行supernode.

#! /bin/bash

/usr/bin/nohup /home/user/n2n/n2n_v2/build/supernode -l 86 -v -f > /home/user/supernode.log 2>&1 &

配置客户端

客户端的核心程序是edge. 该程序在n2n_v1和v2两个版本里除了核心不同外, 其余运行基本相同. 除了一个-f选项差异.

  • 在v1里, -f 选项用于背景运行程序. 没有输出. 要看输出, 不要-f即可,
  • 在v2里, -f 选项用于取消背景运行. v2的edge默认是背景运行的. 要看输出就要-f选项

另外, 有些选项window和unix系统是不同的, 例如win下没有-d来指定虚拟网卡, -u, -g来指定执行用户和组ID. 参考下面两个版本的参数:

$ hom@localhost:~$ ~/n2n/n2n_v2/build/edge --help
# Welcome to n2n v.2.1.0 for Linux-2.6.32-042stab108.2
# Built on Sep 18 2016 12:48:29
# Copyright 2007-09 - http://www.ntop.org
# 
# edge -d <tun device> -a [static:|dhcp:]<tun IP address> -c <community> [-k <encrypt key> | -K <key file>] [-s <netmask>] [-u <uid> -g <gid>][-f][-m <MAC # address>]
# -l <supernode host:port> [-p <local port>] [-M <mtu>] [-r] [-E] [-v] [-t <mgmt port>] [-b] [-h]
# 
# -d <tun device>          | tun device name
# -a <mode:address>        | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'
# -c <community>           | n2n community name the edge belongs to.
# -k <encrypt key>         | Encryption key (ASCII) - also N2N_KEY=<encrypt key>. Not with -K.
# -K <key file>            | Specify a key schedule file to load. Not with -k.
# -s <netmask>             | Edge interface netmask in dotted decimal notation (255.255.255.0).
# -l <supernode host:port> | Supernode IP:port
# -i <local_ip>            | Add local ip to bypass between same nat problem
# -b                       | Periodically resolve supernode IP
#                          : (when supernodes are running on dynamic IPs)
# -p <local port>          | Fixed local UDP port.
# -u <UID>                 | User ID (numeric) to use when privileges are dropped.
# -g <GID>                 | Group ID (numeric) to use when privileges are dropped.
# -f                       | Do not fork and run as a daemon; rather run in foreground.
# -m <MAC address>         | Fix MAC address for the TAP interface (otherwise it may be random)
#                          : eg. -m 01:02:03:04:05:06
# -M <mtu>                 | Specify n2n MTU of edge interface (default 1400).
# -r                       | Enable packet forwarding through n2n community.
# -E                       | Accept multicast MAC addresses (default=drop).
# -v                       | Make more verbose. Repeat as required.
# -t                       | Management UDP Port (for multiple edges on a machine).
# 
# Environment variables:
#   N2N_KEY                | Encryption key (ASCII). Not with -K or -k.

$ ./edge.exe --help
# Welcome to n2n v.2.1.0 for Windows
# Built on Sep 19 2016 19:48:54
# Copyright 2007-09 - http://www.ntop.org
# 
# edge -a [static:|dhcp:]<tun IP address> -c <community> [-k <encrypt key> | -K <key file>] [-s <netmask>] [-m <MAC address>]
# -l <supernode host:port> [-p <local port>] [-M <mtu>] [-r] [-E] [-v] [-t <mgmt port>] [-b] [-h]
# 
# -a <mode:address>        | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'
# -c <community>           | n2n community name the edge belongs to.
# -k <encrypt key>         | Encryption key (ASCII) - also N2N_KEY=<encrypt key>. Not with -K.
# -K <key file>            | Specify a key schedule file to load. Not with -k.
# -s <netmask>             | Edge interface netmask in dotted decimal notation (255.255.255.0).
# -l <supernode host:port> | Supernode IP:port
# -i <local_ip>            | Add local ip to bypass between same nat problem
# -b                       | Periodically resolve supernode IP
#                          : (when supernodes are running on dynamic IPs)
# -p <local port>          | Fixed local UDP port.
# -m <MAC address>         | Fix MAC address for the TAP interface (otherwise it may be random)
#                          : eg. -m 01:02:03:04:05:06
# -M <mtu>                 | Specify n2n MTU of edge interface (default 1400).
# -r                       | Enable packet forwarding through n2n community.
# -E                       | Accept multicast MAC addresses (default=drop).
# -v                       | Make more verbose. Repeat as required.
# -t                       | Management UDP Port (for multiple edges on a machine).
# 
# Environment variables:
#   N2N_KEY                | Encryption key (ASCII). Not with -K or -k.

具体常用到的选项有:

-l : supernode的IP和端口, 格式是IP:port -a : 客户端在虚拟局域网中的IP -c : 虚拟局域网名 -k : 密码 -f : v1中为背景运行, v2中为取消背景运行. win下没有该选项. -m : 可选, 指定物理mac地址, 为了固定mac地址.

UBuntu 客户端配置

编辑配置文件: vi /etc/default/n2n:

  • 网络组名 N2N_COMMUNITY, 相连的主机要在同一个组
  • 沟通密码 N2N_KEY , 要能连接两个主机必须用相同的组名和密码
  • 服务器端IP和端口: N2N_SUPERNODEN2N_SUPERNODE_PORT , 这个和服务器端设置的端口和服务器的IP一致
  • 该主机在网络中的IP: N2N_IP 每台主机设置不同的IP才可以, 用于区分不同主机
  • N2N_EDGE_CONFIG_DONE 该行要去注释, 去掉以后就可以用/etc/init.d/n2n 来开启服务, 否则不能使用服务.
# Config file for the n2n edge node daemon.

# Sets the n2n community name. All edges within the same community appear on
# the same LAN (layer 2 network segment). Community name is 16 bytes in length.
N2N_COMMUNITY="Ubuntu_n2n_Groupname"

# Sets the twofish encryption key from ASCII text. All edges communicating must
# use the same key and community name.
N2N_KEY="Your_password"

# Sets the n2n supernode IP address and port to register to.
N2N_SUPERNODE="12.34.56.78"
N2N_SUPERNODE_PORT="822"

# Sets the n2n virtual LAN IP address being claimed. This is a private IP
# address. All IP addresses in an n2n community typical belong to the same /24
# net‐ work (ie. only the last octet of the IP addresses varies).
N2N_IP="10.1.2.2"

N2N_DAEMON_OPTS=""

# Uncomment this to get edge node started.
N2N_EDGE_CONFIG_DONE="yes"

#TODO
# add routing option
# sudo ip route add 192.168.1.0/24 via 10.1.2.1

这个配置文件和下面的网上流行的openwrt配置文件不太一样, 因为我没有这种路由器不太方便调试, 上述是本人的ubuntu16的配置.

好了, 现在只要 sudo service n2n start 就可以开启客户端的服务了. stop/restart 都是支持的.

要永久开启服务, 就用sudo sysv-rc-conf 来配置2345项开启就好了. 不明白sysv-rc-conf可参考Ubuntu开机服务

除了使用服务, 还可以直接用命令行运行 (如果报错, 检查是否之前开了服务, 先sudo service n2n stop):

sudo edge -a 10.1.2.2 -c Ubuntu_n2n_Groupname -k Your_password -l 12.34.56.78:822

或者避免密码显露使用

$N2N_IP=Your_password sudo edge -a 10.1.2.2 -c Ubuntu_n2n_Groupname -l 12.34.56.78:822

这时会出现大量通信信息. 更多参数可以参考Ubuntu参考手册: edge - n2n edge node daemon

另外可以将信息保存在类似于上面的/etc/default/n2n文件里, 然后

source /etc/default/n2n
export N2N
/usr/sbin/edge -f -a $N2N_IP -c $N2N_COMMUNITY -l $N2N_SUPERNODE:$N2N_SUPERNODE_PORT -u $(id -u nobody) -g $(id -g nobody)

如果服务器端/客户端都在一个内网, 反而ping值会很卡… 通过公网连接会好很多. 如果连接特别慢可以把MTU调到1300 (编辑/etc/init.d/n2n 修改 ifconfig edge0 mtu 1300 #修改MTU为1300). MTU是最大传输单元, 就是每个包的大小.

在不同的主机配置好edge客户端后, 就可以ping 10.1.2.3 去看看是否相通 (这里面可能要等一会儿才能通)

启动后, 可以ifconfig 发现多了一个”网卡”:

edge0     Link encap:Ethernet  HWaddr aa:aa:aa:aa:aa:aa  
          inet addr:10.1.2.2  Bcast:10.1.2.255  Mask:255.255.255.0
          inet6 addr: 1111::1111:1111:1111:1111/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1400  Metric:1
          RX packets:140 errors:0 dropped:0 overruns:0 frame:0
          TX packets:145 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:17251 (17.2 KB)  TX bytes:21087 (21.0 KB)

openwrt 客户端配置(没经测试)

# 安装
opkg install http://downloads.openwrt.org/snapshots/trunk/brcm63xx/packages/n2n_3875-1_brcm63xx.ipk
# 编辑配置文件
root@Openwrt:~# cat /etc/config/n2n 
config edge
        option ipaddr           '10.111.11.1'
        option supernode        '12.34.56.78'
        option port             '82'
        option community        '你自己建立的组'
        option key              '密码'
        option route            '1'
# 开启服务
root@Openwrt:/home# /etc/init.d/n2n start

Window/Android 客户端配置

去下载 n2nedgegui 或者 n2nguien: http://www.vpnhosting.cz/n2nguien.exe. (都是vpnhosting.cz 开发, 前者使用SF托管的, 经测试是n2n_v2的, 使用v1版supernode不能通, 后者可以在Advanced里面设置为n2n_v1从而解决问题,如果用n2n_v1请使用后者)

界面图形化, 比之前的配置就是Advanced多了一个版本选择(记得服务器,各个edge都要版本一致)

使用自己编译的edge

这很重要. 由于supernode可能使用不同发行版本, 因此会出现edge崩溃的问题. 而上述GUI的客户端都是使用某个旧版本编译出来的, 使用GITHUB上的新代码注定崩. 因此可以参考上面的Window下安装方法编译出来的edge.exe去替换掉GUI版本里相应的edge.exe文件. 这里, n2nedgegui使用的是V2版的,只有一个edge.exe. 直接替换即可. 而n2nguien使用的是V1和V2均有, 对应的文件是edge.exeedge2.exe. 做相应替换即可.

安卓客户端可以去google play搜索n2n 来安卓下载: google play 下载

这些图形界面的配置介绍可以参考ref 1.

PS: Win端可能ping不通, 因为默认下win7 以上处于安全考虑不允许外部主机对其进行ping 测试. 运行ICMP 回显, 设置: 控制面板 -> 防火墙 -> 高级设置 -> 入站规则 -> 找到文件和打印机共享(回显请求-ICMPv4-in, 有两个), 右键启用规则即可. PS: 如果开有多个版本有多个虚拟网卡时, 可以用ping -I tun0 ip 这样去指定ping(例如我在客户端同时开有多个edge)

附录

supernode 启动服务写法参考
#!/bin/sh                                                                                     
### BEGIN INIT INFO
# Provides:          n2n
# Required-Start:    $network $remote_fs $local_fs
# Required-Stop:     $remote_fs $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start or stop the n2n VPN
# Description:       This script controls the n2n VPN service.
#                    It is called from the boot, halt and reboot scripts.
#                    So far, only 1 PVN is supported by this script.
#                    More can be started via the command line.
### END INIT INFO

set -e

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC='n2n P2P VPN Supernode'
NAME=supernode
DAEMON=/usr/bin/supernode
SNPORT="82"
DAEMON_ARGS="-l $SNPORT"      # Arguments to run the daemon with
#PIDFILE=/var/run/$NAME-edge.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
. /lib/lsb/init-functions

# Function that starts the daemon/service
#
do_start()
{
    #if [ -r /sys/class/net/edge0 ]; then
    # echo edge node is already running.
    # exit 0
    #fi
    
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --user nobody --exec $DAEMON --test > /dev/null \
        || return 1
    export N2N_KEY
    start-stop-daemon --start --quiet --user nobody --exec $DAEMON -- \
         $DAEMON_ARGS \
        || return 2 &
}
#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user nobody --exec $DAEMON
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    start-stop-daemon --stop --signal 1 --quiet --name $NAME
    return 0
}

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
    do_start
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
    do_stop
    case "$?" in
        0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
        2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
    esac
    ;;
  status)
    status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
  #reload|force-reload)
    #
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
  restart|force-reload)                                                                       
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" "$NAME"
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
        # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    N=/etc/init.d/$NAME
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
    exit 3
    ;;                                                                                        
esac

exit 0
win下mingw进行cmake记录
## First, I modify CMakeToolchainFileMingw32.cmake, change compiler to gcc and g++, but fail.
$ cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/CMakeToolchainFileMingw32.cmake --build ./ ../
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
CMake Error at CMakeLists.txt:1 (project):
  The CMAKE_C_COMPILER:

    cl

  is not a full path and was not found in the PATH.

  To use the NMake generator with Visual C++, cmake must be run from a shell
  that can use the compiler cl from the command line.  This environment is
  unable to invoke the cl compiler.  To fix this problem, run cmake from the
  Visual Studio Command Prompt (vcvarsall.bat).

  Tell CMake where to find the compiler by setting either the environment
  variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
  the compiler, or to the compiler name if it is in the PATH.


CMake Error at CMakeLists.txt:1 (project):
  The CMAKE_CXX_COMPILER:

    cl

  is not a full path and was not found in the PATH.

  To use the NMake generator with Visual C++, cmake must be run from a shell
  that can use the compiler cl from the command line.  This environment is
  unable to invoke the cl compiler.  To fix this problem, run cmake from the
  Visual Studio Command Prompt (vcvarsall.bat).

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.
-- Configuring incomplete, errors occurred!

See also "C:/Users/zhaozx/Desktop/n2n-master/n2n_v2/build/CMakeFiles/CMakeOutput.log".
See also "C:/Users/zhaozx/Desktop/n2n-master/n2n_v2/build/CMakeFiles/CMakeError.log".

## Then, I find that I can use -G to assign compiler chain for cmake
## Error when run cmake previous to generate conf file: CMakeCache.txt  CMakeFiles. It cause cmake to still run nmake instead of mingw-make
$ cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=../cmake/CMakeToolchainFileMingw32.cmake --build ./ ../
CMake Error: Error: generator : MinGW Makefiles
Does not match the generator used previously: NMake Makefiles
Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.

$ rm -rf ./*

## Error when use "MinGW Makefiles" to setup 
$ cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=../cmake/CMakeToolchainFileMingw32.cmake --build ./ ../

CMake Error at C:/Program Files (x86)/CMake/share/cmake-3.6/Modules/CMakeMinGWFindMake.cmake:22 (message):
  sh.exe was found in your PATH, here:

  C:/MinGW/msys/1.0/bin/sh.exe

  For MinGW make to work correctly sh.exe must NOT be in your path.
  Run cmake from a shell that does not have sh.exe in your PATH.
  If you want to use a UNIX shell, then use MSYS Makefiles.

Call Stack (most recent call first):
  CMakeLists.txt:1 (project)

CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!

## Indeed, don't need to setup -DCMAKE_TOOLCHAIN_FILE=../cmake/CMakeToolchainFileMingw32.cmake
## Success finally
$ cmake -G "MSYS Makefiles"  --build ./ ../
$ make

## Finally run the program, it works
$ ./edge.exe --help
Welcome to n2n v.2.1.0 for Windows
Built on Sep 19 2016 19:48:54
Copyright 2007-09 - http://www.ntop.org

edge -a [static:|dhcp:]<tun IP address> -c <community> [-k <encrypt key> | -K <key file>] [-s <netmask>] [-m <MAC address>]
-l <supernode host:port> [-p <local port>] [-M <mtu>] [-r] [-E] [-v] [-t <mgmt port>] [-b] [-h]

-a <mode:address>        | Set interface address. For DHCP use '-r -a dhcp:0.0.0.0'
-c <community>           | n2n community name the edge belongs to.
-k <encrypt key>         | Encryption key (ASCII) - also N2N_KEY=<encrypt key>. Not with -K.
-K <key file>            | Specify a key schedule file to load. Not with -k.
-s <netmask>             | Edge interface netmask in dotted decimal notation (255.255.255.0).
-l <supernode host:port> | Supernode IP:port
-i <local_ip>            | Add local ip to bypass between same nat problem
-b                       | Periodically resolve supernode IP
                         : (when supernodes are running on dynamic IPs)
-p <local port>          | Fixed local UDP port.
-m <MAC address>         | Fix MAC address for the TAP interface (otherwise it may be random)
                         : eg. -m 01:02:03:04:05:06
-M <mtu>                 | Specify n2n MTU of edge interface (default 1400).
-r                       | Enable packet forwarding through n2n community.
-E                       | Accept multicast MAC addresses (default=drop).
-v                       | Make more verbose. Repeat as required.
-t                       | Management UDP Port (for multiple edges on a machine).

Environment variables:
  N2N_KEY                | Encryption key (ASCII). Not with -K or -k.

## Indeed, edge need as administrator 
$ ./edge.exe -l 11.11.11.11:86 -c Helloworld -k Helloworld -a 10.1.2.3
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:2495] Starting n2n edge 2.1.0 Sep 19 2016 19:48:54
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:2500] supernode 0 => 11.11.11.11:86
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:2500] supernode 1 =>
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:2547] ip_mode='static'
Open device [name={742EF053-CF5D-4511-BC68-9A85D4173001}][ip=10.1.2.3][ifName=Ethernet 2][MTU=1400][mac=01:02:03:04:05:06]
Setting Ethernet 2 device address...
请求的操作需要提升(作为管理员运行)。

WARNING: Unable to set device Ethernet 2 IP address [netsh interface ip set address "Ethernet 2" static 10.1.2.3 255.255.255.0]
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:2614] edge started
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c: 416] Chose new tx_transop_idx=1
19/Sep/2016 19:53:03 [c:/Users/zhaozx/Desktop/n2n-master/n2n_v2/edge.c:1935] Rx REGISTER_SUPER_ACK myMAC=01:02:03:04:05:06 [11.11.11.11:86] (external 123.123.123.123:16313). Attempts 2

Reference

  1. 组建N2N VPN网络实现内网设备之间的相互访问
  2. 作者的paper: N2N: A Layer Two Peer-to-Peer VPN


◆ 本文地址: http://platinhom.github.io/2016/09/03/n2n-p2pnet/, 转载请注明 ◆

前一篇: Autodock
后一篇: Ubuntu使用小结


Contact: Hom / 已阅读()
Source 类别: IT  标签: Internet  Proxy