lighthouse

可能是一份比较新的n2n编译指南

趁着我现在还没忘赶紧写下来。。

n2n是一个实用的p2p VPN程序。当两台机器在同一网络环境下互相通讯会自动直连,不同网络环境下会通过中间节点(supernode,需要有公网ip)进行中转。和zerotier是一样的东西,只是配置起来可能会稍微简单一点(——当然如果你知道我付出了多大努力才让它在我的所有设备上运行之后,可能你会心灰意冷)。前几天无意中发现了这个东西,但是我当时发现现在网上还能找到的能用的东西似乎只有那个第三方维护的branch了。其他找到的的东西基本无法和那个branch内的所有程序进行工作。这里给出一个我踩了一圈地雷才得到的编译的正确方法。哪不对也别找我了我不想折腾了太难受了

劝退部分

首先你需要知道,这个东西可能远没有你想象中的那么好,下面是我实际测试的结果

  1. 原作者早就不更新了(还在维护的branch在这里
  2. 节点直连可能速度会比直接连(不走n2n)慢,这个慢的范围大概在40%左右。windows下直连测试的结果。
  3. 走中转速度慢得要命,我手里有个乱折腾的安卓机,拿linux deploy装了ubuntu,平时做脱机下载用,开了smb,我测试了一下中转下的速度,自己用的手机拿ES文件浏览器连smb走中转连接那台机子,传输速度10k。我也不知道为什么。也可能是我那个机器有问题。
  4. windows下客户端连接之后网络属性显示速度10mbps。网络设备名显示的是tap tun win32,查了一下资料是openvpn的东西,驱动最后更新是在2011年左右。我不知道这个速度是协商出来的还是写死的。
  5. 安卓平台上google play中的那个n2n客户端已经没法和github上的那个branch的版本互相连接了。想玩基本需要自己编译出binary,然后拿终端在手机上跑。因为需要用到tun所以说手机需要root,并且需要更改路由表来确保可以正常使用
  6. iOS没法用,没客户端,当然说你要是会把那个binary移植过去的话随便。反正c写的。
  7. 编译太费劲了,太费劲了!

你为什么不用zerotier?如果嫌zerotier中转节点慢的话可以自己搭。那个东西官方称作moon,可以自己找资料。

Windows端的编译

如果上面那堆东西还没成功劝退你的话那你是不是抖m啊亲,下面我就来说一下如何征服这只猛兽。

其实作者有给出一个编译的说明,但是无奈好像年代久远,一些编译器和依赖早就已经无法正常找到了。linux端的话没得说那个方法是可以的,但是windows端的话,如果你想在Ubuntu上交叉编译就必须需要mingw的工具链,说明中并没有完整给出编译器所在的toolchain包名称。其实叫mingw-w64。你可以在ubuntu下通过apt来安装。这篇文章中给出了关于使用mingw编译器的两个例子。

单有这个也是不行的,你还需要去cmake/CMakeToolchainFileMingw32.cmake这个路径下修改第5、6行来使其支持你安装的编译器。

修改后的该文件

# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)

# which compilers to use for C and C++
# SET(CMAKE_C_COMPILER i686-mingw32-gcc)
# SET(CMAKE_CXX_COMPILER i686-mingw32-g++)
SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH ${HOME}/win_n2n/mingw32/)

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search 
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

ubuntu下mingw-64这个包编译器本身就是在PATH中的,所以说源说明中export PATH="$PATH:$HOME/mingw32/bin"这行不用运行了。直接跑cmake输出Makefile就可以。

我这边测试的情况是supernode(中转节点)和edge(客户端)可以正常输出,link走到70%左右断了,最后的那几个n2n_test之类的没输出出来,不过并无大碍。

Android平台的编译

Android上的编译可能是我经历过的最折腾,也是最体现我个人折腾精神的一件事情。我以前只听说过交叉编译,不懂NDK,不懂任何相关知识。提到arm平台交叉编译立刻有大佬指导说用linaro,折腾上之后binary扔到手机上之后死活无法运行,这才想起来安卓平台好像不能用这套唉然后就去折腾NDK,编译器折腾好之后代码报错,改了好几处地方勉强能跑了。

总结下来有三个难点

  1. NDK的配置
  2. 改cmake文件
  3. 找android平台能用的openssl库
  4. 修改代码

首先,事先说明一点,我个人不写cpp,我完全就是在凭经验乱拼,代码虽然能跑但是可能会有点难看。

第一步是需要部署NDK,下载好文件之后官方有一份文档来帮助我们部署实际需要的toolchain。其实是使用了一个叫make-standalone-toolchain.sh的脚本,你可以根据提示来构建出自己需要的工具链。比如说我的手机是aarch64(arm64)平台的,我对应的输出命令应该是

make-standalone-toolchain.sh \
--toolchain=aarch64-linux-android-4.9 \
--install-dir=$HOME\android_ndk

这样就自动将你需要的toolchain输出到主目录下的android_ndk文件夹了

然后修改CMakeList.txt,在第六行下添加使用ndk编译器的相关配置。

# Android 5.0 以上需要在此处设置 PIE
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")

# 配置使用 NDK Standalone Toolchain 编译
# NDK路径,这里注意修改
set(NDK_STANDALONE_TOOLCHAIN /home/vpcuser/app/ndk_toolchain)

set(CMAKE_SYSTEM_NAME AndroidARM)
set(CMAKE_SYSTEM_VERSION 3)
set(CMAKE_C_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-gcc)
set(CMAKE_CXX_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/arm-linux-androideabi-g++)
set(CMAKE_FIND_ROOT_PATH ${NDK_STANDALONE_TOOLCHAIN})

# 使用 NDK 提供的头文件
add_definitions("--sysroot=${NDK_STANDALONE_TOOLCHAIN}/sysroot")

然后便是寻找安卓平台能用的openssl库,虽说系统自己带openssl-del、libssl-dev之类的东西,但是可能是由于平台不同的缘故这里没有办法正常使用。这部分内容分为两部分,第一是两个库,github上有一个repo的readme上有这个的预编译版本下载,或者用某些linux的发行版的对应平台软件包软件包拆出来好像也可以,我好像就是这么干的,反正运行起来没什么问题。第二是一堆头文件,这个可以在这里找到。

然后接着改CMakeList.txt,在上面那步加上下面这几行

include_directories( < 填那堆头文件的路径 > )
link_directories( < 填那两个库的路径 > )

以为到这里就结束了吗?还没结束哦

生气了吗

生气了吗

生气了吗

然后你会发现它依然无法正常过编译。原因是有几个函数已经废弃了但是它还在用并且这套编译环境里没有,你需要自己替换一下。C: Differences between strchr() and index()

还需要修改tuntap_linux.c的第97、105、110行,这东西运行是要有ifconfig的,起到的作用是启配置ip启动对应网络设备。因为现在安卓机多数都没自带busybox,并且即使有bzbox的话ifconfig估计也绝对不会在那个路径,所以说请将/sbin/ifconfig直接替换成ifconfig

我要是没记错的话至少编译能正常过了吧,后面n2n_test那块可能还会没法编译,不过无伤大雅。

然后把binary传到安卓平台上,安卓端推荐装一个NeoTerm,很方便的一个东西,并且还有debian的apt包管。

binary传好,然后chmod +x,然后./edge -h运行一下,没啥问题的话应该就会有帮助消息了,前面会有一行警告,那是编译上的问题,同样无伤大雅。别着急运行,你还需要准备一个ifconfig给它用,如果你用了NeoTerm,直接apt install net-tools就可以,和ubuntu是一样的。如果没用nt的话,找一个busybox装上,当然说并不一定非得是apk形式的一键安装器,不想折腾(?)的话可以搞一份arm平台的预编译busybox然后写个alias给edge用。

正常来讲到这里就可以正常启动网卡并且连中转节点了。

当然说现在还是不能运行的,因为Android的路由表机制和别的不一样,默认表的路由默认情况下一点用都没有,你需要手动把默认路由删掉加到其他表里。

ip r del 10.0.0.0/24
ip r add 10.0.0.0/24 dev edge1 table legacy_network

我这里配置的客户端ip段是10.0.0.0/24,根据情况自己修改

正常来说到这里就能正常运行了吧

预编译版本分享

过几天再说。。