SSH 协议及 openssh

SSH 协议及 openssh

SSH 协议

SSH 协议为 Secure SHell 的缩写,SSH 协议专为远程登录会话和其它网络层提供安全协议。

  1. SSH协议由三部分组成
    • 传输层协议 (SSH-TRANS)
      提供服务器认证,数据机密性,信息完整性 等的支持;
    • 用户认证协议 (SSH-USERAUTH)
      为服务器提供客户端的身份鉴别;
    • 连接协议 (SSH-CONNECT)
      将加密的信息隧道复用成若干个逻辑通道,提供给更高层的应用协议使用; 各种高层应用协议可以相对地独立于SSH基本体系之外,并依靠这个基本框架,通过连接协议使用SSH的安全机制。

Alt text

  1. 在 Linux 系统上有两个应用程序可以来实现 SSH 协议

    • openssh
    • dropbear
  2. SSH用户认证方式

基于口令的认证
基于口令的认证方式如下图所示:

基于口令的认证方式简要概括如下:

  • 客户端向服务器发起SSH连接请求,服务器将自己的公钥发送给客户端,SSH客户端提示用户是否信任服务器的公钥,若信任则将服务器的公钥及对应的IP存在用户家目录~/.ssh/known_hosts文件中
[root@localhost ~]# ssh 172.18.17.201
The authenticity of host '172.18.17.201 (172.18.17.201)' can't be established.
RSA key fingerprint is 84:ad:f0:e9:21:52:dd:a7:a6:bf:0e:a1:36:29:7d:10.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.18.17.201' (RSA) to the list of known hosts.
root@172.18.17.201's password:
[root@localhost ~]# cat ~/.ssh/known_hosts
172.18.17.201 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt1EHbPr9zVnFaJzLRfy4VukGgaHC+s0UesCdpBYleKODL1lqdkCtkmbKWoESS3X678EH4CVf44TVjlXgqjCLAaxYYI7EGL6V1o+DzTguhT4VDgNUIqhX8UALFsAv3GRnGV0MAZ0UIdZr0AR6vqclj6ozTdvg/lg5A8c3Q1zTbW2ZaYHMgmaVM7hWSGGZ82j1WUDv/4Rdyn9eJPAdUH+gdJ/GvE4QgKbtBtlF8ViNVOAGSWilOhrEVssJw8zr4+981rIl6RVytHy34XJ51w1NOj5Nkssun+axnvIlHt4GWsJtyQCwlGC+uShBt0+54tXcFxRBB+jEjSqw11IN4KiMsw==
  • 客户端用服务器的公钥加密用户名,密码等信息发送给服务器
[root@localhost ~]# ssh 172.18.17.201
root@172.18.17.201's password: <= 输入密码
  • 服务器用自己的私钥解密密文,并将解开的用户密码和/etc/shadow里的密码进行匹配,若匹配成功则用户认证成功。

基于key的认证

基于key的认证方式简要概括如下:

  • 首先客户端得有一对公私钥,我们可以使用工具 openssh 的客户端工具 ssh-keygen 生成。公、私钥默认的存放目录为~/.ssh/id_rsa
[root@6 ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ''
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
d6:b1:d7:8a:24:c3:ee:31:1b:3e:16:58:98:62:d1:48 root@6
The key's randomart image is:
+--[ RSA 2048]----+
| .Eo |
| o . |
| . o . |
| o o... o . |
| . . oS + . . |
| .o.+ o . |
| =.. . |
| oo= |
| .+. |
+-----------------+
[root@6 ~]# ls ~/.ssh/
id_rsa id_rsa.pub
  • 客户端将自己的公钥发送到要连接的用户的家目录 ~/.ssh/authorized_keys 文件中,我们可以使用客户端工具 ssh-copy-id 工具完成整个发送并存储于 authorized_keys 文件中的操作。此步操作用户的认证方式还是基于用户口令认证的方式完成用户身份验证的,因为基于 key 的认证方式还未建立起来。
# 客户端传送公钥到服务器 ~/.ssh/authorized_keys 文件中
[root@6 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.18.17.201
# 服务器上查看客户端传过来的公钥信息
[root@7 ~]# cat ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3VAWII6Pg/PmJK2wzdC7eeUUGoyRpAbrYaDgfNhOjzKryWGu3TUYD8fyo0faXUuUaiqO+pAEKI1YZTBQ/fDKtrJWgJjcHTFGOjh4+bzVQ8z2kmaWVO+QGXNcOsdHuCcQAHjOPsFPYKJucghn9Q6RnhCq3anEAEckA37XRi7nwdYsoLiET9VYcZGwNs/BFNt3/ok8s9RrHYT6LgQAo9gqw05/EO6FSEt2tJ4jIZ5ET5Rl++BTqQkMkdjEolOfOkc8BE75aLdc3SSHjmUd/K41gX5JjOdBsKskeWmTe5gcSp6O13D2DSslWgRw5XqS4whCuAKULmB/CeCz92l155x5Uw== root@6
  • 现在基于 key 的验证方式已建立起来,当客户端在发起 SSH 连接请求时,请求信息中包含客户端要连接的用户和客户端的IP,服务器接收到请求时会到需连接的用户的家目录下去查找 authorized_keys 文件中的信息,若与客户端请求的信息相匹配,则服务器会随机生成一段字符串,并用客户端的公钥进行加密,将加密后的密文发送给客户端。
  • 客户端接收到服务器发送过来的密文后,用自己的私钥解密,将解密后的字符串发送给服务器
    • 为了安全起见,若客户端的密钥进行了加密,则在解密的过程中,需要用户输入私钥口令。若之前创建私钥未加密,现在想对私钥加密,我们可以使用ssh-keygen -p 来完成。
    • 对私钥进行加密后,客户端每次 SSH 连接都要输入私钥的加密口令,这样很不方便,我们可以在客户端上找一个代理来帮我们完成此项工作,我们只需要将私钥的加密口令告诉这个代理,下次 SSH 连接的时候就不需要我们自己再输私钥加密口令了。
# 对之前生成的私钥加密
[root@6 ~]# ssh-keygen -p -f ~/.ssh/id_rsa
Key has comment '/root/.ssh/id_rsa'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.
# 此时再登录需要输入私钥加密的口令
[root@6 ~]# ssh 172.18.17.201
Enter passphrase for key '/root/.ssh/id_rsa':
# 使用代理来完成输入私钥加密口令的操作
# 使用 bash 作为代理
[root@6 ~]# ssh-agent bash
# 将私钥加密口令告诉代理
[root@6 ~]# ssh-add
Enter passphrase for /root/.ssh/id_rsa:
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
# 再次 SSH 连接再也不需要人工完成输入私钥加密口令的操作了
[root@6 ~]# ssh 172.18.17.201
Last login: Wed Sep 13 10:49:24 2017 from 172.18.17.10
  • 服务器接收到字符串后,与之前生成的字符串进行匹配,若一样则客户端身份认证成功,免密码登录。

SSH协议的实现之一 openssh

openssh 客户端工具

  • Linux: ssh,scp,sftp,slogin
  • Windows: xshell, putty,securecrt

下面介绍 Linux系统上的客户端工具 ssh

  • ssh 相关文件路径
    配置文件:/etc/ssh/ssh_config
    客户端的公私钥及远程服务端发送过来的公钥:~/.ssh/
[root@6 ~]# ls ~/.ssh/
id_rsa id_rsa.pub known_hosts
  • ssh 语法
ssh [user@]host [options] command
-p PORT 指定连接的远程服务器监听端口
-b IP 指定客户端连接的源IP
-v 调试模式
-C 压缩模式
-X 支持X11转发,ssh客户端执行远程ssh端的图形窗口
-Y
-t 强制tty分配,ssh -t MidHost ssh DestHost 可以实现端口转发

openssh 服务端工具
openssh 服务端工具有 sshd 和 sshd-keygen,我们称 sshd 为服务更合适

  • sshd 服务相关文件路径
    配置文件:/etc/ssh/sshd_config
    公私钥存放目录:/etc/ssh/
[root@7 ~]# ls /etc/ssh/*
/etc/ssh/moduli /etc/ssh/ssh_host_rsa_key
/etc/ssh/ssh_config /etc/ssh/ssh_host_rsa_key.pub
/etc/ssh/sshd_config
  • sshd 配置文件 /etc/ssh/sshd_config 常用配置参数
配置文件: /etc/ssh/sshd_conf
配置文件常用参数
Port PORT 监听的端口
ListenAddress IP 监听的地址
HostKey /etc/ssh/* 公私钥存放目录
LoginGraceTime 用户登录超时时间
UseDNS yes/no 是否让DNS解析
GSSAPIAuthentication yes/no 是否GSSAPI验证
PermitRootLogin yes/no 是否允许root登录
MaxAuthTries NUM 尝试错误连接的次数
MaxSessions NUM 一个客户端允许的连接次数
PubKeyAuthentication 基于key的用户身份验证
PermitEmptyPasswords 空口令登录
PasswordAuthentication 基于密码认证
ClientAliveInterval 数据多长时间没有传输就断开连接
ClientAliveCountMax 次数,配合ClientAliveInterval使用
MaxStartups start:rate:full
Banner 欢迎词

SSH 端口转发

本地转发

Alt text
防火墙策略:不允许外网主机 SSH-Client 直接访问内网主机 Telnet-Server ,但允许 SSH-Client 访问内网主机 SSH-Server 22号端口

可以使用SSH本地转发访问Telnet-Serve

# SSH-Client
ssh -L SSH-Client-Port:Telnet-Server-IP:Telnet-Server-Port SSH-Server-IP [-Nf]
# SSH-Client
telnet 127.0.0.1 SSH-Client-Port

实例演示

  1. Telnet-Server 上添加 iptables 策略,禁止SSH-Client 连接 Telnet-Server
# 清除原来的防火墙策略
[root@telnet-server ~]# iptables -F
# 添加策略阻止 SSH-Client(172.18.17.10
[root@telnet-server ~]# iptables -A INPUT -s 172.18.17.10 -j REJECT
  1. SSH-Client 上执行端口转发命令
# SSH-Client:
[root@SSH-Client ~]# ssh -L 8888:172.18.17.201:23 172.18.17.101 -Nf
root@172.18.17.101's password:
  1. SSH-Client 测试连接
# SSH-Client:
[root@SSH-Client ~]# telnet 127.0.0.1 8888
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Kernel 3.10.0-514.el7.x86_64 on an x86_64
telnet-server login: zhubiao
Password:
Last login: Wed Sep 13 14:24:49 from ::ffff:172.18.17.101
[zhubiao@telnet-server ~]$
  1. 结束端口转发
# SSH-Client:
[root@SSH-Client ~]# killall ssh


远程转发

Alt text
防火墙策略:外网主机 SSH-Server 不能访问内网所有主机,但内网主机 SSH-Client 可以通过22端口连接到SSH-Server
要求:外网主机 SSH-Server 访问内网主机 Telnet-Server

可以使用SSH远程端口转发访问Telnet-Serve

# SSH-Client
ssh -R SSH-Server-Port:Telnet-Server-IP:Telnet-Server-Port SSH-Server-IP [-Nf]
# SSH-Server
telnet 127.0.0.1 SSH-Client-Port

实例演示

  1. Telnet-Server 上添加 iptables 策略,禁止SSH-Server 连接 Telnet-Server
# Telnet-Server
# 清除原来的防火墙策略
[root@telnet-server ~]# iptables -F
# 添加策略阻止 SSH-Server(172.18.17.10)
[root@telnet-server ~]# iptables -A INPUT -s 172.18.17.10 -j REJECT
  1. 在SSH-Client上添加端口转发命令
# SSH-Client:
[root@SSH-Client ~]# ssh -R 8888:172.18.17.201:23 172.18.17.10 -Nf
root@172.18.17.10's password:
  1. 在SSH-Server 测试连接
# SSH-Server
[root@SSH-Server ~]# telnet 127.0.0.1 8888
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Kernel 3.10.0-514.el7.x86_64 on an x86_64
telnet-server login: zhubiao
Password:
Last login: Wed Sep 13 14:25:34 from ::ffff:172.18.17.101
[zhubiao@telnet-server ~]$ <=连接成功


动态端口转发

Alt text

防火墙策略:只允许 SSH-Client 通过 22 端口访问 SSH-Server。
需求:如何访问 www.google.com 网站

可以使用 SSH 的动态端口转发功能实现我们的需求

ssh -D SSH-Client-Port SSH-Server-IP [-Nf]

实例演示

  1. 配置httpd服务器
    为了演示,我们在WEB(www.google.com)服务器上安装httpd服务
# 安装 httpd 服务
yum -y install httpd
# 启动 httpd 服务
[root@telnet-server ~]# systemctl start httpd
[root@telnet-server ~]# systemctl is-active httpd
active
# 写一个简单的HTML网页
[root@telnet-server ~]# echo '<h1>www.google.com</h1>' > /var/www/html/index.html
  1. WEB 服务器上添加 iptables 策略,禁止SSH-Client 连接 WEB服务器
# Telnet-Server
# 清除原来的防火墙策略
[root@telnet-server ~]# iptables -F
# 添加策略阻止 SSH-Server(172.18.17.10)
[root@telnet-server ~]# iptables -A INPUT -s 172.18.17.10 -j REJECT
  1. SSH-Client 上执行动态端口转发命令
SSH-Client:
[root@SSH-Server ~]# ssh -D 8888 172.18.17.101 -Nf
root@172.18.17.101's password:
  1. 添加代理
    若使用命令 curl 访问网页,则执行以下命令:
[root@SSH-Server ~]# curl --socks5 127.0.0.1:8888 http://172.18.17.201
<h1>www.google.com</h1>

若使用火狐浏览器访问网页,添加代理的方法如下所示:

Alt text

  1. 测试

Alt text


–END–