安全外壳协议(Secure Shell Protocol,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实现SSH客户端与服务器之间的连接。SSH最常见的用途是远程登录系统,人们通常利用SSH来传输命令行界面和远程执行命令。

SSH 基础知识

以前网络主机之间的通信是采用明文传输(如:Telnet和Berkeley rlogin、rsh、rexec等协议),使用不可靠的密码,容易遭受监听、嗅探和中间人攻击,SSH旨在保证非安全网络环境(例如互联网)中信息加密完整可靠。

SSH以非对称加密实现身份验证。身份验证有多种途径,例如其中一种方法是使用自动生成的公钥-私钥对来简单地加密网络连接,随后使用密码认证进行登录;另一种方法是人工生成一对公钥和私钥,通过生成的密钥进行认证,这样就可以在不输入密码的情况下登录。 任何人都可以自行生成密钥。公钥需要放在待访问的电脑之中,而对应的私钥需要由用户自行保管。认证过程基于生成出来的私钥,但整个认证过程中私钥本身不会传输到网络中。

SSH 的经典用途是登陆到远程电脑中执行命令,此外还支持隧道协议、端口映射和X11连接。借助SFTP或SCP协议,SSH还可以传输文件。 SSH 使用客户端-服务器模型, 标段端口为22。

端口转发

SSH 作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。

端口转发有两个主要作用:

(1)将不加密的数据放在 SSH 安全连接里面传输,使得原本不安全的网络服务增加了安全性,比如通过端口转发访问 Telnet、FTP 等明文服务,数据传输就都会加密。

(2)作为数据通信的加密跳板,绕过网络防火墙。

端口转发有三种使用方法:动态转发本地转发远程转发

下面的场景中,假设HostA 和 HostB 之间通过防火墙分为两个部分,只能在HostA 和 HostB 之间通过SSH连接的方式来相互访问。

本地转发

此时可以通过本地转发,既将SSH服务器作为中介跳板机,建立本地计算机与特定目标之间的加密连接。

它会指定一个本地端口(local-post),所有发向这个端口的请求,都会转发到SSH跳板机(tunnel-host),然后 SSH 跳板机作为中介,将收到的请求发到目标服务器(target-host)的目标端口(target-port)。

1
$ ssh -CNfgL local-port:target-host:target-port tunnel-host

上面命令中,-L参数表示本地转发,local-port是本地端口,target-host是你想要访问的目标服务器,target-port是目标服务器的端口,tunnel-host是 SSH 跳板机。

1
2
3
4
5
可选参数CNfg:
-C:压缩数据传输,
-N:不执行脚本或命令,仅进行端口转发
-f:ssh客户端在后台运行
-g:允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接

场景1:HostA 节点访问 HostB 节点在PortB端口提供的TCP服务

1

那么可以通过下面的命令来实现:

1
(HostA) $ ssh -L PortA:HostB:PortB user@HostB

场景2 和场景1类似,但这次是想通过HostB 访问 HostC上PortC 端口提供的TCP服务

2

那么可以通过下面的命令来实现:

1
(HostA) $ ssh -L PortA:HostC:PortC user@HostB

远程转发

远程转发指的是在远程 SSH 服务器建立的转发规则。

它跟本地转发正好反过来。建立本地计算机到远程计算机的 SSH 隧道以后,本地转发是通过本地计算机访问远程计算机,而远程转发则是通过远程计算机访问本地计算机。它的命令格式如下。

1
$ ssh -R remote-port:target-host:target-port -N remotehost

上面命令中,-R参数表示远程端口转发,remote-port是远程计算机的端口,target-host和target-port是目标服务器及其端口,remotehost是远程计算机。 它会指定一个远程端口(remote-port),所有发向那个端口的请求,都会转发到 SSH 跳板机(tunnel-host),然后 SSH 跳板机作为中介,将收到的请求发到目标服务器(target-host)的目标端口(target-port)。

场景3: 内网HostA 在PortA 端口有一个服务,可以通过远程转发将PortA端口,映射到外网HostB 的PortB 端口上,使得访问HostB 的PortB 端口,都会 转发到内网HostA 的PortA 端口

3

1
(HostA) ssh -R PortB:HostA:PortA user@HostB

动态转发

动态转发指的是,本机与 SSH 服务器之间创建了一个加密连接,然后本机内部针对某个端口的通信,都通过这个加密连接转发。它的一个使用场景就是,访问所有外部网站,都通过 SSH 转发。

动态转发需要把本地端口绑定到 SSH 服务器。至于 SSH 服务器要去访问哪一个网站,完全是动态的,取决于原始通信,所以叫做动态转发。

1
$ ssh -D local-port tunnel-host -N

上面命令中,-D表示动态转发,local-port是本地端口,tunnel-host是 SSH 服务器,-N表示这个 SSH 连接只进行端口转发,不登录远程 Shell,不能执行远程命令,只能充当隧道。

注意,这种转发采用了 SOCKS5 协议。访问外部网站时,需要把 HTTP 请求转成 SOCKS5 协议,才能把本地端口的请求转发出去。

如下,在本地端口7891作为进行动态转发,在curl通过这个端口进行外部端口访问:

1
2
$ ssh -ND 7891 tunnel-host
$ curl -x socks5://localhost:7891 http://www.baidu.com

上面命令中,curl 的-x参数指定代理服务器,即通过 SOCKS5 协议的本地2121端口,访问http://www.baidu.com。此时 也可将浏览器的代理服务器设置成socks5://localhost:7891,访问外部网站。

参考

  1. 维基百科Secure Shell
  2. 百度百科安全外壳协议
  3. SSH
  4. 什么是SSH 以及常见的ssh 功能
  5. 通过 SSH 实现 TCP / IP 隧道(端口转发):使用 OpenSSH 可能的 8 种场景