本文将介绍两种应用场景的SSH端口转发,分别是SSH本地转发以及SSH远程转发。
简介
SSH(Secure Shell)是一种网络协议,顾名思义就是安全的shell,主要用于安全的远程登录和计算机间加密传输。早期,互联网通信都是基于明文通信,一旦被截获,内容就暴露无遗。1995年,芬兰学者设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界范围内获得推广,目前已成为Linux系统的标准配置。SSH的主要目的是用来取代传统的telnet 和 R 系列命令(rlogin, rsh, rexec 等)远程登录和远程执行命令的工具,实现对远程登录和远程执行命令加密,防止由于网络监听而密码泄露问题。SSH是一种加密协议,不仅在登陆过程中对密码进行加密传送,而且对登陆后执行的命令的数据也进行加密,这样即使别人在网络上监听并截获了你的数据包,他也看不到其中的内容。
SSH协议目前有SSH1和SSH2两个主流版本,SSH2协议兼容SSH1,强烈建议使用SSH2版本,因为双方主机协议选择安全的MAC方式。OpenSSH是SSH协议的开源实现, CentOS默认会安装。
简单介绍一下SSH端口转发。SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是, SSH 还能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务。这一过程也被叫做“隧道”,这是因为 SSH 为其他 TCP 链接提供了一个安全的通道来进行传输而得名。例如,Telnet、SMTP以及 LDAP 这些 TCP 应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传输。而与此同时, 如果工作环境中的防火墙限制了一些网络端口的使用,但是允许SSH的连接,也能够通过将 TCP 端口转发来使用 SSH 进行通讯。
SSH 端口转发能够提供两大功能:1、加密 SSH Client 端至 SSH Server 端之间的通讯数据;2、突破防火墙的限制完成一些之前无法建立的 TCP 连接。
SSH端口转发:本地转发
如下图所示,外部主机A想访问企业内部的C,telnet server,但是telnet是不安全的协议,所以企业的防火墙策略上会禁止这种行为,但是防火墙允许外部机器通过22端口访问B,SSH server ,这时候我们在主机A上可以通过SSH端口转发,用SSH这种安全协议来封装telnet这种不安全的协议,类似把SSH server B当做跳板,来实现对C,telnet server的访问。
模拟实验的过程如下:
1、实验准备
192.168.1.7(centos7)、192.168.1.8 (centos7)和192.168.1.6(centos6)三个虚拟机分别充当上面的外部主机A,SSH server B 以及telnet server C。
2、在192.168.1.6(C机器)上
# 查询是否安装了telnet-server服务
rpm -ql telnet-server
# 查询是否telnet设置为开机启动
chkconfig --list telnet
# 发现telnet不是开机启动,设为开机启动
chkconfig telnet on
# 重启xinetd服务,telnet是非独立服务,依赖于xinetd
service xinetd restart
# 看看23端口是否开启
ss -ntl
# 拒绝192.168.1.7的访问
iptables -vnL # 没有做防火墙策略
iptables -A INPUT -s 192.168.1.7 -j REJECT
3、在192.168.1.7(主机A)上
# 直接连接192.168.1.6是被拒绝的(Connection refused)
telnet 192.168.1.6
# 打开本机的9527端口,建立隧道
ssh -L 9527:192.168.1.6:23 -Nf 192.168.1.8
# -N 在这里就表示建立了隧道之后,不打开远程shell,就在本机待着,处于等待状态
# -f 后台启用(不然的话,这里建立的隧道会占用一个终端)
# 查看一下隧道是否已经建立
ss -nt
#发现192.168.1.7:39078和192.168.1.8:22 建立了连接
# 连接到telnet服务器上
telnet 127.0.0.1 9527
# 注意连接的时候
# 如果基于用户名和密码的验证方式,则只能以对方主机非root身份去连接
# 如果基于key的验证方式则可以以其他身份去连接
至此,主机A就可以实现对telnet server C的远程访问了。
当主机A访问本机的9527的端口时,被加密后转发到ssh server:22,就是B的22端口,然后B就会解密,然后B再充当telnet的client端,将解密的数据转发到telnet server:23,最终就到达了目标服务器C。大致的流程如下:
data <------> 主机A localhost:9527 <------> 主机A localhost:XXXXX <------>
B ssh server:22 <------> B ssh server:YYYYY <------> C telnet server:23
上面的XXXXX和YYYYY表示端口号,主机A localhost:XXXXX充当的是ssh的client端,B ssh server:YYYYY充当的是telnet 的client端。
4、在192.168.1.7(主机A)上
# 退出连接
exit
# 关闭隧道(桥)
ps aux
killall ssh
ps aux
# 查看9527端口是否还在
ss -ntl
# 发现现在无法连接了
telnet 127.0.0.1 9527
退出连接之后,需要在192.168.1.6上把对应防火墙策略取消。
SSH端口转发:远程转发
还是上面的图,如果此时防火墙策略上禁止外部主机通过tcp的22端口访问企业内部,但是允许内部主机出去,比如访问外部的SSH的22端口,此时就应该使用远程转发。注意:内部用户通过防火墙主动出去的,就意味着可以再进来,这不需要在防火墙上做什么策略,因为防火墙有自动的链路记录功能。远程转发,我们用访问邮件服务器的实验来演示,此时角色发生了一些变化,主机A充当的是ssh server,而服务器B充当的是ssh client,服务器C充当的是smtp server。模拟实验的过程如下:
1、实验准备
192.168.1.6(centos6)、192.168.1.8 (centos7)和192.168.1.7(centos7)三个虚拟机分别充当上面的外部主机A(SSH server),服务器B(SSH client) 以及服务器C(smtp server)。
2、在192.168.1.7(C机器)上
# 查询smtp server能否接受远程用户的访问
ss -ntl
# 发现无法接受,修改相关设置
vim /etc/postfix/main.cf
inet_interfaces = all # 将前面的#去掉,表示本机的所有IP,
# 这样才可以接受远程用户的访问
#inet_interfaces = localhost # 这表示绑定在本机127上的,注释掉
# 重启一下服务,查看
systemctl restart postfix
ss -ntl # 有*:25表示成功(本机所有ip的25端口)
# 查看防火墙策略
iptables -vnL # 发现没有做防火墙的策略
# 如果有的话,就采用下面的命令
systemctl disable firewalld
systemctl stop firewalld
iptables -F
# 拒绝192.168.1.6的访问
iptables -A INPUT -s 192.168.1.6 -j REJECT
3、在192.168.1.6(主机A)上
# 确保防火墙是关闭的
chkconfig --list iptables
iptables -vnL
# 确保selinux是关闭的,如果没有关闭,使用下面的命令
sed -i '/^SELINUX/c\SELINUX=disabled' /etc/selinux/config
setenforce 0
# 当在192.168.1.7机器上做了防火墙策略之后,Connection refused
telnet 192.168.1.7 25
4、 在192.168.1.8(B机器)上
# 确保防火墙和selinux都是关闭的
# 测试连接telnet 192.168.1.7 25,发现是通的
telnet 192.168.1.7 25
# 打开192.168.1.6的9527端口,建立隧道
ssh -R 9527:192.168.1.7:25 -fN 192.168.1.6
# 这里的-fN与上面的相同不再解释
5、在192.168.1.6(主机A)上
# 查看一下连接是否已经建立
ss -nt
# 发现192.168.1.6:22和192.168.1.8:36130建立了连接
# 查看9527端口是否被打开,可以看到9527端口处于监听状态
ss -ntl
# 连接本机的9527端口,发送smtp请求,发邮件的过程不再细说
telnet 127.0.0.1 9527
6、在192.168.1.7(C机器)上
# 发现 192.168.1.8:50524 在连接192.168.1.7:25
ss -nt
# 查看邮件
mail
7、在192.168.1.8(B机器)
# 关闭隧道
ps aux
killall ssh
退出连接之后,需要在192.168.1.7上把对应防火墙策略取消。
至此,我们就实现了SSH端口远程转发。远程转发本质上仍然是A 可以去访问C ,只是由B来建立隧道。建立隧道的命令是:
ssh –R 9527:smtpsrv:25 –N sshsrv
这条命令是让sshsrv侦听9527端口的访问,如有访问,就加密后通过ssh服务转发请求到本机ssh客户端, 再由本机解密后转发到smtpsrv:25。
SSH端口远程转发大致的流程如下:
Data <------> sshsrv:9527 <------> sshsrv:22 <------>
localhost:XXXXX <------> localhost:YYYYY <------> smtpsrv:25
至此,SSH本地转发以及SSH远程转发介绍完了,不足之处,请多多指正。