今天讲远程连接,所有代码案例在:
https://github.com/suchocolate/test/tree/master/remote
本文仅适用于无可控防火墙的场景,如有自己的防火墙和无限制IP,请忽略本文。
1.简单分析
机房拓扑如下
众所周知,一般FW只允许内对外发起访问,禁止外对内发起访问。
在这种场景下,想要远程,就需要一个在公网的代理节点帮忙。(实际这种由公网通过代理节点访问私网的连接方式应该叫做反向代理,为了便于理解本文简称代理)
如何实现:首先由内网机发起到代理节点的连接并保持连接,而后远程client访问代理节点,代理节点从隧道转发给内网机,这样就实现了远程连接。
因此想实现远程连接需要2个素材:
一个带公网IP的代理节点。
合适的转发方式。
2.我用过的转发方式
我用过5种转发方式(都是基于SSH隧道):
接下来我为大家一一介绍,条件有限,我用3台虚拟机和物理机模拟:
内网机:192.168.70.138 u41
代理:192.168.70.135 u42_proxy 192.168.137.21(假如这是公网ip)
client:192.168.137.1(就是我的物理机)
A主机:192.168.70.151 a_host
3.SSH:基础的端口转发
端口转发是SSH自带的功能,仅用SSH命令就可以实现。
1)远程转发
以图为例,首先内网机使用如下命令发起远程(R)端口转发,就能将代理上的15022端口转发到内网机的22端口上:
ssh -fCNR 15022:localhost:22 [email protected]
# f:程序放到后台
# C:数据压缩,压缩节省流量
# N:这不是一条远程SSH命令
# R:远程转发,将远程15022端口发到本地的22端口
可以看到在后台运行了一个SSH远程转发的进程。
接下来只要在代理节点上使用如下命令就可以访问内网机了。
ssh -p 15022 root@localhost
# p:端口15022
# root:内网机的账号
# localhost:登陆的主机
# 意思就是登陆本机的15022端口,又因为这个映射成了远端的内网机的22端口
# 所以当登陆这个端口时,就是登陆内网机的22端口。
成功登陆到了内网机。
2)本地转发
仅远程转发没有预期的方便,这个远程方式需要我们先登陆到代理节点,才能SSH访问内网机。能不能实现client不登录代理,就能登陆内网机?当然可以,我们先看一下代理节点的监听端口:
可以看到,代理节点上监听的是环回口的15022,所以只能在代理节点上访问。如果想实现不登录代理就转发,我们还得在代理上开一个本地转发,监听任意地址,流量转给15022:
接下来在代理节点运行本地(L)转发命令:
ssh -fCNL *:15023:localhost:15022 root@localhost
# L:本地转发命令,将15023转发到本地的15022端口
# root:这里的root是代理自己的账号和密码
可以看到,代理节点运行了SSH后台本地转发进程,并且在监听0.0.0.0:15023端口了。
我们在client上新建一个到代理节点公网地址:192.168.137.21:15023的SSH会话,登陆验证一下:
果然成功连上了u41内网机,流量经过代理做了一次本地转发,而后经过代理和内网机的隧道做了一次远程转发,实现了远程连接:
3)SSH转发的总结
SSH的优点是不需要安装额外软件,只需执行SSH命令即可。缺点是连接不稳定,容易受到网络影响,使用时需要两端任意一方设置保持连接的配置:
# 内网机端
vi /etc/ssh/ssh_config
ServerAliveInterval 60
ServerAliveCountMax 3
# 代理机
vi /etc/ssh/sshd_config
ClientAliveInterval 60
ClientAliveCountMax 3
不过即使设置,也有可能因为系统的故障断连,这时需要使用Autossh。
4.Autossh:稳定的端口转发
Autossh是一个用来保持SSH程序的软件,它能够在SSH程序Down掉后重启SSH程序。
1)安装方法
apt-get install autossh # debian系操作系统
yum install autossh # redhat系操作系统
2)必要设置
Autossh和SSH一样都会在后台工作,但Autossh在放到后台工作后,不会弹出输入密码的提示,我们无法输入密码,因此只有免密登陆才能让Autossh顺利工作。免密方法如下:以下案例是内网机免密登陆代理机。
ssh-keygen # 3个回车即可
ssh-copy-id [email protected] #root想登陆的节点的账号和密码
3)内网机开远程转发
autossh -M 10060 -f -CNR 15022:localhost:22 [email protected]
# -M:autossh从10060端口发检测消息,对端发回给+1端口就是10061
# -f:程序放到后台
# -CNR:就是SSH的参数
可以看到Autossh其实就是帮我们开启了远程转发,另外它有自己的保活机制,可以在网络或系统异常时帮我们重启转发。
4)代理生成key并copy给自己
接下来就是在代理上做本地转发,本地转发时要代理节点ssh登陆自己,这个过程正常也需要输入密码,因此为了让Autossh正常工作,也得让代理节点生成key并copy给自己。
ssh-keygen
ssh-copy-id root@localhost # 账号名和主机都是代理自己的
5)代理节点运行Autossh本地转发
autossh -M 10070 -f -CNL "*:15023:localhost:15022" root@localhost
可以看到代理节点开启了本地转发,我们通过client再次验证一下结果:
成功转发到到了内网机上。
6)Autossh的总结
Autossh虽然稳定,但是和SSH转发一样两个节点都需要配置,如果用的人多,大家都要在代理上加配置,有安全隐患。我们可以使用frp简化配置增强安全。
5.frp:稳定的应用自动转发
frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。
frp分frps端和frpc端,代理节点运行frps,内网机运行frpc。
1)frp架构图:
2)frp的工作机制
frpc和frps使用单独的端口通信(本例指定7000),业务端口由frpc指定,frps自动开始监听。当有流量时开始转发,不需要额外配置,配置文件中也无需指定账号密码,降低了安全风险。
3)frp的下载:
下载地址:https://github.com/fatedier/frp/releases/
无需安装,只需找到相应系统对应软件,下载解压即可运行。
4)frps的配置和运行
下载后,首先修改代理节点的配置:frps.ini
vi ./frps.ini
[common]
bind_port = 7000 # frps监听的,用来和frpc交互的端口
运行:frps
nohup ./frps -c frps.ini> nohup.out 2>&1 &
# hohup:后台运行
# frps:frps上的主程序
# frps.ini:frps的配置
# > nohup.out:log
# 2>&1:报错也输出到log
# &:后台运行
5)frpc的配置和运行
修改内网机上的配置:frpc.ini
vi ./frpc.ini
[common]
server_addr = 192.168.70.135 # frps的地址
server_port = 7000 # frps监听的,用来和frpc交互的端口
# frpc想让frps转发的应用,如果有多个frpc都想让frps转发,那么其他
# frpc需要在ssh后面加序号,如[ssh2][ssh3]
[ssh]
type = tcp
local_ip = 127.0.0.1 # 转发到本地的地址
local_port = 22 # 转发到本地22端口
remote_port = 15800 # frps监听转发的端口
use_encrytion =true # 数据加密
use_compression =true # 数据压缩
内网机运行:frpc
nohup ./frpc -c frpc.ini > nohup.out 2>&1 &
查看代理上的端口已经在监听15800端口了,而且用的不是SSH的转发。
6)frp的验证
在client新建到192.168.137.21:15800的SSH会话,并登陆:
成功登陆内网机。
7)frp的总结
frps只需指定与frpc会话端口,不需要指定业务端口,配置省事。
frpc无需登陆frps,业务端口由frpc指定,安全自由。
8)frp的扩展
另外frp还支持http,https,dns,socket等的转发,详细的配置大家可以到github页面查看。最后frps上还可以配置dashboard,用GUI监控frps上连接的情况:
vi ./frps.ini
[common]
dashboard_port = 7500
# dashboard 用户名密码,默认都为 admin
dashboard_user = admin
dashboard_pwd = admin
6.SecureCRT:Windows上的端口转发
1)场景假设
前3种都是在linux系统上的转发,这第4种是在Windows系统上转发,它适用于以下场景:(本节用另外的虚机192.168.70.151模拟A主机,物理机模拟Windows内网机)
假如内网有台A主机不能上网连公网的代理节点,而有一台Windows系统的内网机电脑可以连A主机的同时,还可以上公网,那么这台Windows内网机就可以用SecureCRT转发。(可以把Windows内网机想象成一个路由器)
2)先让Windows内网机建立到代理的SSH会话
3)在这个会话中设置远程端口转发
启动SSH会话,可以看到代理节点已经在监听15022,此时代理到内网机的隧道已经建立。
注意:这个转发是将代理的15022端口转到A主机的22端口,而SSH的案例中R转发是将代理的15022端口转到本地的22端口。
3)隧道的保持
SecureCRT的SSH会话也有可能断连,我们可以让SecureCRT运行一个脚本,来保持这个连接:keep.vbs
#$language = "VBScript"
#$interface = "1.0"
crt.Screen.Synchronous = True
' This automatically generated script may need to be
' edited in order to work correctly.
Sub Main
crt.Dialog.MessageBox("Script is running")
i=1
do while i>0
crt.Screen.Send "date" & chr(13)
crt.Sleep 1500000
loop
End Sub
CRT运行脚本的方法:【脚本】-【运行】在弹出的对话框中选择keep.vbs。
4)先验证:A主机<---内网机<---代理
在代理上验证一下:
代理能够登陆A主机。
5)client的转发
按照SSH转发的思路,接下来就需要在代理节点开本地转发了,但其实还有另外的方法,即外部client与代理再建一个隧道。
接下来让client建立与代理的隧道,并利用这个隧道,client上做本地转发,即可免去代理上配本地转发:
6)client上建立与代理的ssh会话
7)之后在这个会话中建立本地转发:
8)启动这个会话
此时从client到A主机的两条隧道拼接完成。
9)接下来client再建立一个SSH会话:
IP指向127.0.0.1,端口15022。
10)登陆验证
成功跨越2个隧道,到达A主机。
11)简单分析
ssh client将流量发给client的端口15022。
15022是CRT的本地转发,转发透过SSH隧道传到代理的15022上。
代理的15022是另外一个CRT的远程转发,代理透过SSH隧道转给内网机。
这个远程转发是直接转给A主机的,流量发给A主机。
7.Socket:自识别应用的转发
以上4种方法只是展示了转发SSH的应用,实际上还可以转发其他端口应用,比如HTTP 80,DNS 53,VNC 3900等等。但无论转发哪种,都需要一定的配置,而Socket转发就可以免去设置多种端口的麻烦,只要有SSH隧道,就能Socket转发。
1)Scoket转发过程:
首先client建立到内网机的隧道
其次client内的软件设置代理:
效果
这样client就可以直接访问内网机能访问的资源了,效果如同client就置身于内网机中:
2)模拟案例展示:frp(基础SSH代理)+CRT(socket)
我用frp实现内网机的ssh,配置参考frp案例。这样client直接ssh15800就是内网机。
之后在A主机运行了http server,只接受内网机的访问,其他IP禁止访问http端口。用iptables实现:
iptables -I INPUT 1 -p tcp --dport 80 -s 192.168.70.138/32 -j ACCEPT
iptables -I INPUT 2 -p tcp --dport 80 -j DROP
3)client 上在这个ssh会话中配置socket转发
登陆ssh会话,可以正常登陆到内网机,这样隧道和socket转发环境就搭建好了,接下来是client设置代理。
4)各种client设置代理
首先浏览器设置代理:firefox为例
登陆网站验证:可以登陆A主机了。
VNC设置代理:
Mobaxterm的远程桌面也支持设置代理
只是Moba并没有用CRT做的socket转发,而是自己利用了SSH隧道。
总之只要有SSH隧道,所有支持设置代理的client都可以利用socket实现转发,不用添加其他端口转发等配置。
8.实际应用
综合实际的情况,我选择了frp保持隧道,只用ssh连接节点,只在需要访问内部网页时透过ssh隧道做socket转发。
另外所有的转发都是通过SSH隧道完成的,所有数据被压缩,在另一端解压缩,传输效率并不高(直连80mb/s,透过代理40mb/s)。尤其像使用阿里云或百度云主机时,默认带宽只有1mb/s,传文件是很不划算的。
另外建议使用autossh或frp时设置开机自启动,避免节点重启后失效。