跳到主要内容

0x4.家庭服务器折腾记|内网穿透方案|Ngork

· 阅读需 10 分钟

家中的电脑,由于没有公网ip,只能在家中用ssh 访问,一旦出门,就无法访问服务器了。这非常不方便,因为可能要从电脑上获取资料,访问数据库,修改代码等等操作,一旦离开本地环境,也太不方便了。

经过百度后发现,需要利用 内网穿透 技术实现。 原因是我们的ip资源是稀缺的,我们普通家庭中使用的ip都是动态分配的ip地址。没有固定的ip的服务器是无法与外网连接的,所以我们至少需要一个公网ip。

内网穿透技术有很多了,我这里选择的是ngrok 这个方案。 我试了一下两种方案,第一个是外国的ngrok,没有尝试成功,而且免费版本每次断开后,生成的url 是随机的。所以没有采用。第二个是国内的Sunny-Ngrok,有免费版的。先尝试一波。

使用Sunny-Ngrok一个很大的好处就是在当你没有服务器和公网ip的时候,它会是一个很不错的解决方案。当然若是你有服务器的话,自己搭一个ngrok未尝不是一个很好的选择。

局域网连接服务器

这里先给出用局域网连接服务器的方法

# linux 查看ip 地址一般是下面三种方法(不同系统不一样)
$ ifconfig
$ ipconfig
$ ip addr # <--manjaro

运行如下

$ 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

局域网中使用

ssh -p 22 ppsteven@192.168.1.l02
# -p 22 也可以省略,因为ssh 的默认端口号就是22

Sunny-Ngrok教程

教程基本上都在 ngrok.cc官方文档 写的很清楚了,但是有一些还是需要注意的。

开通隧道

如果你是想用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

启动ngrok 服务

# 当前目录在linux_amd64 下
$ ./sunny clientid 隧道id # 启动隧道服务
$ setsid ./sunny clientid 743acXXXX & # 在后台启动隧道服务

启动服务后,我们在官网的后端就可以看到结果。 为了让我们的服务器能不断的在后台运行,我们需要登录服务器后,运行第二行的命令

  • & 作用是后台运行程序
  • setsid 作用是当终端关闭的时候命令一直不会关闭

高级教程——开机自动运行

官网中已经给出了 Ngrok开机自启动 的教程,我们这里由于使用的是manjaro,官网的教程无法直接参考,我们这里给出自己的解决方案。

第一步:移动命令,并使之可执行

sudo mv sunny /usr/local/bin/sunny
sudo chmod +x /usr/local/bin/sunny

第二步:编写启动脚本

我们这里直接上手修改官网的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

写完之后,我们需要测试一下

chmod a+x sunny_auto.sh
./sunny_auto.sh # 会输出使用方法
./sunny_auto.sh start
./sunny_auto.sh stop
./sunny_auto.sh restart

测试成功后,我们需要让系统自己启动。我看了一下,目前网上大部分教程都是直接给了代码,并没有解释清楚自启动的原理。我认为这是可以通过查看官方教程一步步讲清楚的。抱着**“授人以鱼不如授人以渔”** 的态度,我准备写的仔细一点。

第三步:自动跑起来

我们的系统是manjaro,是arch linux 的衍生版本,所以我们第一想到的就是去 https://wiki.archlinux.org/ 上找。

archlinux 上,在如下九个方面,我们可以完成"autostart" 操作

  • 开关机
  • 登录登出
  • 插入拔出设备
  • 计时事件
  • 文件系统事件
  • shell登录登出
  • Xorg
  • 桌面环境
  • 窗口管理启动

这里,我们需要第一项开关机 Systemd 作为我们自启动的方式,其实很多教程中也是采用的这个方式。

单元文件

一个服务可以看做是一个unit,每个unit需要编写自己的单元文件。systemd 单元文件的语法来源于 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) 中的EXAMPLES章节。英文不好的同学,有一位热心的大牛,已经写好了中文教程 systemd.index 中文手册

单元文件的地址如下

  • /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

参考资料

有了内网穿透神器 ngrok ,个人电脑也能做服务器