之前遇到了我在使用的某家主机商,因为出现了使用公共DDNS域名导致服务器连续被轮段攻击的情况,所以他们决定撤掉公共DDNS域名,并建议自建DDNS域名。在上一篇文章 使用AliDDNS工具,为DDNS NAT小鸡部署自动更换DDNS IP能力 中,提到了借助阿里云云解析的API实现自动DDNS能力。

但最大的问题在于,更新DNS记录是有缓存的。也就是说,就算TTL设置到1,也不能保证本地马上更新成功。或者说,当前服务器的动态IP正在遭受攻击、或者是更换了IP,同时网站也挂了,无法通过面板获取到最新IP,需要连接到服务器进行配置的情况下,常规的DDNS方案可能未必会是最优解。那么,还有没有什么办法,能尽最大可能避免与自己的动态IP服务器失联呢?

答案是,使用反向穿透技术。

在开始本教程前,你需要准备——
一台具有公网IP的服务器 (反向穿透服务器)
一台需要进行反向穿透连接的服务器 (目标服务器)
SSH客户端

1. What is 反向穿透技术

简单的说下反向穿透的原理。

举个简单的例子,我们使用SSH协议连接到服务器,这个时候,我们的电脑是Client(客户端),服务器是Server(服务端),Client主动向Server发起请求,得到Server的回应后会建立起一条连接通道。

这种情况需要我们知道Server的IP、端口、协议等信息,然后才能连接成功。这种连接方法我们一般叫正向连接。

那么,当我们的服务器A作为客户端,主动连接到能够提供反向穿透服务的服务器B的时候,服务器A就是Client,服务器B就是Server,两台服务器之间建立连接,实现数据通信。这个时候我们的电脑通过连接到服务器B的某个端口,就可以等价于访问服务器A上的某个端口,这样我们通过服务器B,间接连接到服务器A,这种连接方法我们一般叫反向连接。

在正向连接的时候,一般是这个样子的:

客户端<----->目标服务器

在反向连接的时候,一般是这个样子的:

客户端<----->反向穿透服务器<----->目标服务器

2. 配置教程

那么,我们如何实现反向穿透到目标服务器,来在特殊的情况下依然可以正常的连接到服务器上?

首先,登录到反向穿透服务器A上,下载反向穿透工具Frp:

wget https://github.com/fatedier/frp/releases/download/v0.20.0/frp_0.20.0_linux_amd64.tar.gz

Frp客户端和服务端都在一个压缩包中!

之后解压:

tar xvf frp_0.20.0_linux_amd64.tar.gz

进入目录:

cd frp_0.20.0_linux_amd64.tar.gz

我们来看下里面都有什么文件:

frpc frpc_full.ini frpc.ini frps frps_full.ini frps.ini LICENSE

frpc:frp的客户端程序
frpc_full.ini:frp客户端的完整版配置文件
frpc.ini:frp客户端的简易配置文件
frps:frp的服务端程序
frps_full.ini:frp服务端的完整版配置文件
frps.ini:frp服务端的简易配置文件
LICENSE:许可文件,没卵用

接下来,我们编辑用作服务端配置的 frps.ini 文件:

[common]
bind_port = 7000

[common]:基础设置部分
bind_port:frp服务端的控制端口

为了Frp服务器的安全,防止被非法使用,我们可以对frp服务端加上 auth_token ,作为连接到Frp服务器需要的密钥。在配置文件最后追加一行:

auth_token = ilemonrain

然后保存退出。

之后执行命令,启动frp服务端:

./frps -c frps.ini

会得到如下结果,说明frp服务器启动成功。接下来,我们继续配置需要反向穿透连接的服务器。

和配置服务端一样,下载解压frp程序包:

wget https://github.com/fatedier/frp/releases/download/v0.20.0/frp_0.20.0_linux_amd64.tar.gz
tar frp_0.20.0_linux_amd64.tar.gz
cd frp_0.20.0_linux_amd64

然后接下来我们用到的就是frp客户端了。编辑客户端文件 frpc.ini

vim frpc.ini
[common]
server_addr = 127.0.0.1
server_port = 7000
login_fail_exit = false
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
auth_token = ilemonrain

[common]:基础设置部分
server_addr:内网穿透服务器的地址
server_port:内网穿透服务器绑定的控制端口
login_fail_exit: 连接失败后是否退出,建议设置为false,实现掉线自动重连
[ssh]:客户端名称,在内网穿透服务器连接的所有客户端中全局唯一
type:协议类型
local_ip:本地IP地址,默认127.0.0.1即可
local_port:需要映射的端口
remote_port:远程请求进行映射的端口
auth_token:连接密码,请与服务端保持一致

根据实际情况进行修改,完成后保存退出。

接下来,启动frp客户端,使frp客户端与服务端建立连接:

./frpc -c frpc.ini

如果一切顺利的话,客户端将会看到如下信息:

2018/05/31 11:16:24 [proxy_manager.go:300] proxy removed: []
2018/05/31 11:16:24 [proxy_manager.go:310] proxy added: [ssh]
2018/05/31 11:16:24 [proxy_manager.go:333] visitor removed: []
2018/05/31 11:16:24 [proxy_manager.go:342] visitor added: []
2018/05/31 11:16:25 [control.go:246] [0d8b777afd83c4b7] login to server success, get run id [0d8b777afd83c4b7], server udp port [0]
2018/05/31 11:16:25 [control.go:169] [0d8b777afd83c4b7] [ssh] start proxy success

同时服务端也会看到如下信息:

2018/05/31 19:13:20 [I] [service.go:122] frps tcp listen on 0.0.0.0:7000
2018/05/31 19:13:20 [I] [root.go:190] Start frps success
2018/05/31 19:13:23 [I] [service.go:299] client login info: ip [x.x.x.x:45954] version [0.19.0] hostname [] os [linux] arch [amd64]
2018/05/31 19:13:23 [I] [proxy.go:203] [9618f23483372a7c] [ssh] tcp proxy listen port [6000]
2018/05/31 19:13:23 [I] [control.go:335] [9618f23483372a7c] new proxy [ssh] success

此时内网穿透隧道已经打通,新建个SSH客户端窗口,连接到 [你的内网隧道服务器地址]:[客户端请求的端口],本教程中为:

x.x.x.x:6000

会发现SSH连接已经建立,使用上面设置的root密码,以root身份登录,即可完成SSH内网穿透。

3. 验证配置

接下来,我们可以模拟下环境:首先,我们要装作(为什么是装作)不知道服务器的新IP,而且Frp的服务端和客户端均已正常启动,那么,我们开始进行验证:

首先,SSH连接到 x.x.x.x:6000 上 (参考本教程上面的配置部分),连接到目标服务器上。在目标服务器上,执行命令:

curl whatismyip.akamai.com

稍等数秒将会返回一个结果:

123.234.123.234

这个结果就是你服务器现在的IP地址。

如果服务器上没有安装curl,执行命令安装:

CentOS:

yum makecache fast && yum install curl -y

Debian 7/Ubuntu 12.04/Ubuntu 14.04:

apt-get update && apt-get install curl -y

Debian 8+/Ubuntu 16.04+:

apt update && apt install curl -y

注1:此教程(方法)适用于任何需要反向穿透的情境,可以用来穿透多种服务。具体的配置请参考程序压缩包里面的 frpc_full.ini 和 frps_full.ini。
注2:Frp可以多平台使用。具体的适用平台请移步 https://github.com/fatedier/frp/releases/

最后修改:2018 年 06 月 26 日 12 : 52 PM
搞技术/肝文章不易,恳请打赏 OwO