05.内网穿透方案-Ngork
家中的电脑,由于没有公网ip,只能在家中用ssh 访问,一旦出门,就无法访问服务器了。这非常不方便,因为可能要从电脑上获取资料,访问数据库,修改代码等等操作,一旦离开本地环境,也太不方便了。
经过百度后发现,需要利用 内网穿透 技术实现。 原因是我们的ip资源是稀缺的,我们普通家庭中使用的ip都是动态分配的ip地址。没有固定的ip的服务器是无法与外网连接的,所以我们至少需要一个公网ip。
内网穿透技术有很多了,我这里选择的是ngrok 这个方案。 我试了一下两种方案,第一个是外国的ngrok,没有尝试成功,而且免费版本每次断开后,生成的url 是随机的。所以没有采用。第二个是国内的Sunny-Ngrok,有免费版的。先尝试一波。
- ngrok (opens new window)
- ngrok.cc (opens new window) (Sunny-Ngrok)
使用Sunny-Ngrok一个很大的好处就是在当你没有服务器和公网ip的时候,它会是一个很不错的解决方案。当然若是你有服务器的话,自己搭一个ngrok未尝不是一个很好的选择。
# 局域网连接服务器
这里先给出用局域网连接服务器的方法
# linux 查看ip 地址一般是下面三种方法(不同系统不一样)
$ ifconfig
$ ipconfig
$ ip addr # <--manjaro
2
3
4
运行如下
$ ip addr | grep inet
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
inet 192.168.1.102/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp2s0
inet6 fe80::1bd5:9435:6572:ffc7/64 scope link noprefixroute
# ip地址是 192.168.1.102
2
3
4
5
6
局域网中使用
ssh -p 22 ppsteven@192.168.1.l02
# -p 22 也可以省略,因为ssh 的默认端口号就是22
2
# Sunny-Ngrok教程
教程基本上都在 ngrok.cc官方文档 (opens new window) 写的很清楚了,但是有一些还是需要注意的。
# 开通隧道
如果你是想用ssh,开通的就是TCP转发。记得要把本地端口换成22(当然不换也是可以的,只要你最后连ssh 的时候设置好端口就行了)
最后看到的结果是这样的
$ ssh -p 10568 yourname@free.aa.com 就可以连接上你的服务器了
# Ngrok 启动
上图可以看到,在状态栏显示 是否成功开启ngrok
启动的方法,官网教程里面也有写,本人按照流程走一遍。
# 下载客户端
我用的是Mac 下载zip文件,然后上传到服务器的操作。有图形界面的同学,可以直接按照官网操作。
$ scp ~/Downloads/linux_amd64.zip ppsteven@192.168.1.102:~/Documents
$ ssh 192.168.1.102
$ cd ~/Documents
$ unzip linux_amd64.zip
2
3
4
# 启动ngrok 服务
# 当前目录在linux_amd64 下
$ ./sunny clientid 隧道id # 启动隧道服务
$ setsid ./sunny clientid 743acXXXX & # 在后台启动隧道服务
2
3
启动服务后,我们在官网的后端就可以看到结果。 为了让我们的服务器能不断的在后台运行,我们需要登录服务器后,运行第二行的命令
- & 作用是后台运行程序
- setsid 作用是当终端关闭的时候命令一直不会关闭
# 高级教程——开机自动运行
官网中已经给出了 Ngrok开机自启动 (opens new window) 的教程,我们这里由于使用的是manjaro,官网的教程无法直接参考,我们这里给出自己的解决方案。
# 第一步:移动命令,并使之可执行
sudo mv sunny /usr/local/bin/sunny
sudo chmod +x /usr/local/bin/sunny
2
# 第二步:编写启动脚本
我们这里直接上手修改官网的shell语言
sunny_auto.sh
#!/bin/bash -e
### BEGIN INIT INFO
# Provides: ngrok.cc
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: autostartup of ngrok for Linux
### END INIT INFO
NAME=sunny
DAEMON=/usr/local/bin/$NAME
PIDFILE=/var/run/$NAME.pid
# 判断 sunny 是否可执行
[ -x "$DAEMON" ] || exit 0
case "$1" in
start)
# 根据/var/run/sunny.pid 文件判断sunny是否正在运行
if [ -f $PIDFILE ]; then
echo "$NAME already running..."
echo -e "\033[1;35mStart Fail\033[0m"
else
echo "Starting $NAME..."
# start-stop-daemon -S -p $PIDFILE -m -b -o -q -x $DAEMON -- clientid 隧道id || return 2
# 不使用start-stop-daemon,使用常规的方法后台运行
setsid sunny clientid 1cb52410136cfe34 &
echo -e "\033[1;32mStart Success\033[0m"
fi
;;
stop)
echo "Stoping $NAME..."
# start-stop-daemon -K -p $PIDFILE -s TERM -o -q || return 2
# pkill 是 kill 和 pgrep 的结合,删除所有中带sunny的进程
pkill -9 sunny
rm -rf $PIDFILE
echo -e "\033[1;32mStop Success\033[0m"
;;
restart)
$0 stop && sleep 2 && $0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0
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
写完之后,我们需要测试一下
chmod a+x sunny_auto.sh
./sunny_auto.sh # 会输出使用方法
./sunny_auto.sh start
./sunny_auto.sh stop
./sunny_auto.sh restart
2
3
4
5
测试成功后,我们需要让系统自己启动。我看了一下,目前网上大部分教程都是直接给了代码,并没有解释清楚自启动的原理。我认为这是可以通过查看官方教程一步步讲清楚的。抱着**“授人以鱼不如授人以渔”** 的态度,我准备写的仔细一点。
# 第三步:自动跑起来
我们的系统是manjaro,是arch linux 的衍生版本,所以我们第一想到的就是去 https://wiki.archlinux.org/ (opens new window) 上找。
archlinux 上,在如下九个方面,我们可以完成"autostart" 操作
- 开关机
- 登录登出
- 插入拔出设备
- 计时事件
- 文件系统事件
- shell登录登出
- Xorg
- 桌面环境
- 窗口管理启动
这里,我们需要第一项开关机 Systemd (opens new window) 作为我们自启动的方式,其实很多教程中也是采用的这个方式。
# 单元文件
一个服务可以看做是一个unit,每个unit需要编写自己的单元文件。systemd
单元文件 (opens new window)的语法来源于 XDG 桌面项配置文件.desktop
文件,最初的源头则是Microsoft Windows的.ini
文件。
# 单元文件操作
立即激活单元:
# systemctl start <单元>
立即停止单元:
# systemctl stop <单元>
重启单元:
# systemctl restart <单元>
重新加载配置:
# systemctl reload <单元>
输出单元运行状态:
$ systemctl status <单元>
检查单元是否配置为自动启动:
$ systemctl is-enabled <单元>
开机自动激活单元:
# systemctl enable <单元>
设置单元为自动启动并立即启动这个单元:
# systemctl enable --now unit
取消开机自动激活单元:
# systemctl disable <单元>
# 编辑我们的单元文件
单元文件的语法,可以参考系统已经安装的单元,也可以参考 systemd.service(5) (opens new window) 中的EXAMPLES章节 (opens new window)。英文不好的同学,有一位热心的大牛,已经写好了中文教程 systemd.index 中文手册 (opens new window)
单元文件的地址如下
/usr/lib/systemd/system/
:软件包安装的单元/etc/systemd/system/
:系统管理员安装的单元
从网上的教程看下来,大家最喜欢的一个做法就是创建一个rc.local
文件,和一个rc-local.service
服务。然后把我们需要运行的脚本加入rc.local
中。
我认为这样的做法很省事,也比较简单,不过缺点是所有的开机自启服务都放一起了,比较乱不好管理。这里我准备按照自己的想法来创建一个服务,我这里借鉴了docker.service。
sunny.service
[Unit]
Description=ngrok sunny
[Service]
Type=forking
User=ppsteven
# 自动重启服务
# Restart=always
# RestartSec=30
# 执行命令
Restart=on-failure
ExecStart=/etc/sunny.sh start
ExecStop=/etc/sunny.sh stop
# ExecReload=/bin/kill -s HUP $MAINPID
[Install]
WantedBy=multi-user.target
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17