端口映射内网穿透方案探索

前言

最近要开始搞持续构建,已经买了一台黑苹果主机放在公司当服务器,接下来需要穿透内网,做端口映射。之前实现过 SSH 反向隧道穿透 NAT,但太简陋了,也很慢,就算用 autossh 还是很容易断,需要探索新的方案。

花生壳

官网 http://www.oray.com

网上很多人说的都是说花生壳的内网穿透,这也从侧面说明花生壳的内网穿透使用起来应该是比较容易的。但这个实在没意思,傻瓜式操作。重点是,花生壳已经收费了,每个月还限制流量1G。对于网站来说,1个G能干什么,卖萌么。

如果对于穿透原理不是很执着,又不想操这个心自己折腾,花生壳内网版会是个很不错的选择。

n2n

Github:

n2n 是在数据链路层实现的一套 P2P 协议,包括 super node 和 edge node。它是开源的,遵循 GPL v3 协议,可运行于 Linux,Windows,Android,甚至是 Openwrt 之上。

我在 CentOS 上编译完 N2N,创建了 super node。但在 MacOS 上编译失败了,遇到了一个 openssl 的报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ make
Scanning dependencies of target scm
[ 3%] Building C object CMakeFiles/scm.dir/unix-scm.c.o
[ 6%] Linking C static library libscm.a
[ 6%] Built target scm
Scanning dependencies of target doc
[ 10%] Generating doc/edge.8.gz
[ 13%] Generating doc/supernode.1.gz
[ 17%] Generating doc/n2n_v2.7.gz
[ 17%] Built target doc
Scanning dependencies of target n2n
[ 20%] Building C object CMakeFiles/n2n.dir/n2n.c.o
/Users/bingo/Desktop/n2n/n2n_v2/n2n.c:458:65: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
snprintf( out, N2N_SOCKBUF_SIZE, "%hu.%hu.%hu.%hu:%hu", (a[0] & 0xff),
~~~ ^~~~~~~~~~~~~
%d
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/secure/_stdio.h:57:62: note: expanded from macro
'snprintf'
__builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
^~~~~~~~~~~
/Users/bingo/Desktop/n2n/n2n_v2/n2n.c:459:17: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
(a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), sock->port );
^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/secure/_stdio.h:57:62: note: expanded from macro
'snprintf'
__builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
^~~~~~~~~~~
/Users/bingo/Desktop/n2n/n2n_v2/n2n.c:459:32: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
(a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), sock->port );
^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/secure/_stdio.h:57:62: note: expanded from macro
'snprintf'
__builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
^~~~~~~~~~~
/Users/bingo/Desktop/n2n/n2n_v2/n2n.c:459:47: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
(a[1] & 0xff), (a[2] & 0xff), (a[3] & 0xff), sock->port );
^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/secure/_stdio.h:57:62: note: expanded from macro
'snprintf'
__builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__)
^~~~~~~~~~~
4 warnings generated.
[ 24%] Building C object CMakeFiles/n2n.dir/n2n_keyfile.c.o
[ 27%] Building C object CMakeFiles/n2n.dir/wire.c.o
[ 31%] Building C object CMakeFiles/n2n.dir/minilzo.c.o
[ 34%] Building C object CMakeFiles/n2n.dir/twofish.c.o
[ 37%] Building C object CMakeFiles/n2n.dir/transform_null.c.o
[ 41%] Building C object CMakeFiles/n2n.dir/transform_tf.c.o
[ 44%] Building C object CMakeFiles/n2n.dir/transform_aes.c.o
/Users/bingo/Desktop/n2n/n2n_v2/transform_aes.c:12:10: fatal error: 'openssl/aes.h' file not found
#include "openssl/aes.h"
^
1 error generated.
make[2]: *** [CMakeFiles/n2n.dir/transform_aes.c.o] Error 1
make[1]: *** [CMakeFiles/n2n.dir/all] Error 2
make: *** [all] Error 2

即使我用 Homebrew 安装了最新版本的 OpenSSL,并且 link 让 shell 默认使用 Homebrew 安装的 OpenSSL,确定环境没问题后,依然还是报这个错误。

谷歌无果,查到的资料基本都是关于 iOS 使用 CocoaPods 安装 openssl 依赖的时候出现的错误。

很搞笑的是,百度用「n2n macOS」作为关键词,搜出来的结果居然只有两三条相关的,一条是 「有人在 OS X 下编译 n2n 成功的么? - V2EX」,还有一条是「有在osx系统下使用n2n vpn的没?」,而且时间是在2013和2014年,也就是三四年过去了,都没有人用了?

也许它只是不支持 MacOS 而已,不满足我的需求,我选择放弃 n2n。

localtunnel

官网: https://localtunnel.github.io/www/
Github: https://github.com/localtunnel/localtunnel

安装

1
2
3
$ npm install -g localtunnel
/usr/local/bin/lt -> /usr/local/lib/node_modules/localtunnel/bin/client
+ localtunnel@1.8.3

使用

1
2
lt --port 8888
your url is: https://nlatvemdpo.localtunnel.me

评论

每次跑起来,域名主机名都是随机的,不能自定义域名,只支持 HTTP 协议的隧道,并且很慢,时不时502报错,直接淘汰。搞不懂 star 数为什么会有五千多,看来写 js 的群体人数真的不少啊,抱团点赞,维护 js 的生态圈?

PageKite

官网 http://pagekite.net/

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ curl -s https://pagekite.net/pk/ |sudo bash
+ curl https://pagekite.net/pk/pagekite.py
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 169k 100 169k 0 0 60694 0 0:00:02 0:00:02 --:--:-- 60686
+ chmod +x /usr/local/bin/pagekite.py
+ '[' '' '!=' '' ']'
~~~~'~~~~~,~~~~~~'~~~~</>
Welcome to PageKite!
PageKite has been installed to /usr/local/bin/pagekite.py !
Some useful commands:
$ pagekite.py --signup # Sign up for service
$ pagekite.py 80 NAME.pagekite.me # Expose port 80 as NAME.pagekite.me
For further instructions:
$ pagekite.py --help |less

使用

1
$ pagekite.py 8888 dankal.pagekite.me

评论

稍微比较稳定,支持 HTTPS。去到官网后台管理才发现,原来是收费的!那我要你何用?各种限制,平均一个月也要二三十块,我还不如用花生壳呢。

ngrok

官网 https://www.ngrok.cc
控制台 https://www.ngrok.cc/user.html

有免费版和收费版

免费版 收费版
服务器 香港免费服务器 香港200M VIP服务器
内存 16G 16G
硬盘 32G 32G
地区 香港 香港
带宽 10M 200M

安装

客户端下载 https://www.ngrok.cc/#down-client,选择对应的平台下载。

1
2
# Mac OSX 64Bit版本
$ wget http://hls.ctopus.com/sunny/darwin_amd64.zip

使用

需要先在控制台新建隧道

1
2
3
4
5
6
7
隧道域名: dankal
自定义域名: build-app.dankal.cn
隧道端口: -
http验证用户名: -
http验证密码: -
开通日期: 2017-09-09 14:56:12
服务器地址: server.ngrok.cc(路由器链接的时候填写,请不要暴露此地址,避免服务器遭受攻击,谢谢)

拿到对应隧道的 ID 后,使用客户端目录下的 sunny 脚本执行:

1
2
3
4
5
6
7
8
9
$ ./sunny clientid e807a9ffdd555f09
Sunny-Ngrok 官 网 www.ngrok.cc (Ctrl+C 退 出 )
隧 道 状 态 在 线
版 本 2.1/2.1
转 发 http://build-app.dankal.cn -> 127.0.0.1:8888
Web界 面 127.0.0.1:4040
# Conn 36
Avg Conn Time 22906.71ms

评论

很稳定,支持自定义域名,但自定义域名会比前缀域名速度慢很多,暂时不支持 https。免费版勉强可以用,但是带宽感觉会不够用。收费版的话,又不想花钱。

能不能自己搭建?答案是肯定的。但是,ngrok 1.x 已经不再开源,而 2.x 已经商业化不开源。而且 1.x 有 bug,比如内存泄漏,其功能也较少。所以,评估过后,我决定不踩进去了,直接跳过,继续选择其它方案。

frp

frp 是一个高性能的反向代理应用,可以轻松地进行内网穿透,对外网提供服务,支持 TCP、UDP、HTTP、HTTPS 等协议类型,并且 web 服务支持根据域名进行路由转发。

frp

Github: https://github.com/fatedier/frp
Releases: https://github.com/fatedier/frp/releases

安装

可以直接下载编译好的压缩包,在上面的 Releases 页面中找到对应平台的压缩包,解压后就可以直接使用,或者自己用 GO 语言编译。

使用

关于 frp 的配置,我会再写一篇文章详细介绍。这里先略过 ini 文件的配置,直接启动 frp 服务。

服务端

1
$ ./frps -c frps.ini

客户端

1
$ ./frpc -c frpc.ini

评论

frp 是我目前发现最合适的端口映射方案,免费,稳定。配置灵活方便,支持的功能也很多,这正是我想要的!

后话

经过一段时间的摸索和评估,最终我采用了 frp 来做端口映射穿透内网。无论是公司的黑苹果主机服务器,还是我的树莓派服务器,都会使用 frp 来做端口映射。

  • 本文作者: Bingo
  • 本文链接: https://blog.bingo.ren/54.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!