SSH
SSH(安全外壳)是一个程序,用于在远程计算机上登录并执行命令。 SSH旨在代替rlogin和rsh,并通过不安全的网络在两个不受信任的主机之间提供安全的加密通信。 X11连接和任意TCP / IP端口也可以通过安全通道转发。
具体的软件实现:
- openssh:ssh协议的开源实现,CentOS默认安装;
- dropbear:另一个开源实现
SSH协议版本
v1:基于CRC-32做MAC,不安全。(man-in-the-middle)
v2:双方主机协议选择安全的MAC方式
openssh简介
OpenSSH是最新的SSH免费版本的OpenBSD版本,在安全性和功能方面使其保持最新。
该软件包包括OpenSSH客户端和服务器所需的核心文件。 为了使该软件包有用,您还应该安装openssh-clients,openssh-server或两者。
相关包:
- openssh
- openssh-clients
- openssh-server
工具
基于C/S结构
Linux Client:ssh,scp,sftp,slogin
Windows Client:xshell,putty,securecrt
Server:sshd
公钥交换
- 客户端发起链接请求
- 服务端返回自己的公钥,以及一个会话ID(这一步客户端得到服务端公钥)
- 客户端生成密钥对
- 客户端用自己的公钥异或会话ID,计算出一个值Res,并用服务端的公钥加密
- 客户端发送加密后的值到服务端,服务端用私钥解密,得到Res
- 服务端用解密后的值Res异或会话ID,计算出客户端的公钥(这一步服务端得到客户端公钥)
- 最终:双方各自持有三个秘钥,分别为自己的一对公、私钥,以及对方的公钥,之后的所有通讯都会被加密
ssh加密通讯
ssh客户端
- 允许实现对远程系统经验证地加密安全访问;
- 当client远程连接ssh server是,会复制ssh server中/etc/ssh/ssh_host*key.pub(CentOS6:/etc/ssh/ssh_host_rsa_key.pub,CentOS7:/etc/ssh/ssh_host_ecdsa_key.pub)文件中的公钥到客户机的~/.ssh/known_hosts文件中。下次连接时,会自动匹配相应的私钥,如果不匹配,则拒绝连接。
客户端组件:ssh
配置文件:/etc/ssh/ssh_config
StrictHostKeyChecking no 表示首次登陆不显示检查提示
格式
ssh []host [COMMAND] ssh [-l user] host [COMMAND]
常用选项:
-p port:远程服务器监听的端口 -b:指定连接的源IP -v:调试模式 -C:压缩方式 -X:支持x11转发 -t:强制伪tty分配 ssh -t remoteserver1 ssh -t remoteserver2 ssh remoteserver3
ssh服务登录验证方式
- 用户/口令
- 基于密钥对
基于用户名和口令的登录验证
1.客户端发起ssh请求,服务器会把自己的公钥发送给用户
2.用户会根据服务器发来的公钥对密码进行加密
3.加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功
基于密钥对的登录验证
1.首先在客户端生成一对密钥(ssh-keygen)
2.并将客户端的公钥ssh-copy-id 拷贝到服务端
3.当客户端再次发送一个连接请求,包括ip、用户名
4.服务端得到客户端的请求后,会到authorized_keys中查找,如果有响应的IP和用户,就会随机生成一个字符串,例如:13579
5.服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端
6.得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的字符串发送给服务端
7.服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,就允许免密码登录
基于密钥对认证的实现
1)在客户端生成密钥对
[ ~]# ssh-keygen -t rsa -P ‘‘ -f ~/.ssh/id_rsa Generating public/private rsa key pair. Created directory ‘/root/.ssh‘. 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: SHA256:T/ApAu61soTHeELNlkMyPeMnbAT4eAE4wVqwQDSJYCc The key‘s randomart image is: +---[RSA 2048]----+ |&Eo. | |B+*o | |o=o.B . | |o = o . | | .. % + S + | | . B = o + | | + B . . | | = o | | . | +----[SHA256]-----+
2)把公钥传输到远程服务器对应的家目录
[ ~]# ssh-copy-id /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" The authenticity of host ‘192.168.8.61 (192.168.8.61)‘ can‘t be established. RSA key fingerprint is SHA256:PEtn8a7YXM4I8wBJMOPIBFmkcJEA6IFiraXR6wNrUiE. RSA key fingerprint is MD5:5a:ad:21:76:fa:a4:16:01:1a:54:3b:4d:2d:9a:1c:5c. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys ‘s password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh ‘‘" and check to make sure that only the key(s) you wanted were added.
3)测试
[ ~]# ssh Last login: Fri Nov 8 00:41:27 2019 from 192.168.8.129 [ ~]#
4)在Xshell实现基于key验证
首先在本机将公钥重命名为authorized_keys mv id_rsa.pub authorized_keys 然后使用sz命令将私钥导出到本地 [ .ssh]# sz id_rsa 最后在xshell中设置使用key登录即可,如下图
5)重新设置私钥口令
[ ~]# ssh-keygen -p Enter file in which the key is (/root/.ssh/id_rsa): Enter old passphrase: Enter new passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved with the new passphrase.
6)当给私钥设置了口令之后,每次连接到别的主机都需要输入私钥的口令,这样太过繁琐,于是,可以将私钥身份添加到身份验证代理ssh-agent,这样就只要输入一次私钥口令就行了。
[ ~]# ssh-agent bash
7)密钥通过命令添加给代理
[ ~]# ssh-add
注:.ssh目录的权限必须为700,私钥文件id_rsa权限必须为600
ssh服务器
服务器端:sshd
配置文件:/etc/ssh/sshd_config
常用参数:
GatewayPorts
指定是否允许远程主机连接到为客户端转发的端口。 默认情况下,sshd(8)将远程端口转发绑定到环回地址。 这样可以防止其他远程主机连接到转发的端口。 可以使用GatewayPorts指定sshd应该允许远程端口转发绑定到非环回地址,从而允许其他主机进行连接。 该参数可以是“否”以强制远程端口转发仅对本地主机可用,“是”以强制远程端口转发绑定到通配符地址,或者可以是“ clientspecified”以允许客户端选择要向其发送地址的地址。 转发是绑定的。 默认为“否”。
GSSAPIAuthentication
指定是否允许基于GSSAPI的用户身份验证。 默认为“否”。 请注意,此选项仅适用于协议版本2。
ClientAliveInterval
设置超时间隔(以秒为单位),如果没有从客户端接收到任何数据,则sshd(8)将通过加密的通道发送消息,以请求客户端的响应。 默认值为0,表示这些消息将不会发送到客户端。 此选项仅适用于协议版本2。
ClientAliveCountMax
设置客户端活动消息的数量,该消息可以在sshd(8)接收不到来自客户端的任何消息的情况下发送。 如果在发送客户端活动消息时达到此阈值,则sshd将断开客户端连接,从而终止会话。 重要的是要注意,客户端活动消息的使用与TCPKeepAlive有很大不同。 客户端活动消息是通过加密通道发送的,因此不会被欺骗。 由TCPKeepAlive启用的TCP keepalive选项是可欺骗的。 当客户端或服务器依赖于知道连接何时变为非活动状态时,客户端活动机制非常有用。
默认值为3。如果ClientAliveInterval设置为15,并且ClientAliveCountMax保留默认值,则无响应的SSH客户端将在大约45秒后断开连接。 此选项仅适用于协议版本2。
UseDNS
指定sshd(8)是否应查找远程主机名,并检查所解析的远程IP地址的主机名是否映射回相同的IP地址。 默认值为“是”。改为no可以提高响应速度 。
MaxStartups
指定到SSH守护程序的并发未认证连接的最大数量。 其他连接将被丢弃,直到身份验证成功或该连接的LoginGraceTime过期为止。 默认值为10:30:100。
Banner
在允许身份验证之前,指定文件的内容将发送到远程用户。 如果参数为“ none”,则不会显示任何横幅。 此选项仅适用于协议版本2。默认情况下,不显示横幅。要显示横幅可以通过Banner /path/file格式来设置。
限制用户连接
AllowUsers AllowGroups DenyUsers DenyGroups
如果没有这些关键词,只需根据需要创建它们。必须只创建您需要的关键词,以免出现不可靠的结果。AllowUsers 和 DenyUsers 列表是由空格分隔的有效用户名,AllowGroups 和DenyGroups 只能是现有的有效组。按以下次序匹配模式:DenyUsers,AllowUsers,DenyGroups,AllowGroups。
对 sshd_config 文件的任何修改要到重新启动 sshd 之后才会生效,如下
CentOS6:service sshd restart CentOS7:systemctl restart sshd
如果在 AllowUsers 列表中设置用户 ID,那么只有这些用户可以通过 SSH 连接。对于 DenyUsers 列表也是如此,只拒绝 DenyUsers 列表中包含的用户访问。同样的规则也适用于组列表。如果同时使用允许列表和拒绝列表,就非常让人迷惑,所以不要这样做。应该根据自己的安全需求,只使用允许列表或拒绝列表之一。
如果用户在系统上有帐户,但是在 AllowUsers 列表中没有他们的用户 ID,就拒绝他们访问。同样的规则也适用于 DenyUsers 列表。现在来看一个示例,假设 AllowUsers 列表包含以下内容:
AllowUsers hechunping
如果用户 test 尝试通过 SSH 访问,那么该访问会遭到拒绝,因为这个用户名没有出现在 AllowUsers 列表中。
[ ~]# ssh ‘s password: Permission denied, please try again. ‘s password: Permission denied, please try again. ‘s password: Permission denied (publickey,password).
通过查看 /var/log/secure文件确认这一点,这里的消息表明在 AllowUsers 列表中没有列出用户 test。
Nov 8 14:16:49 CentOS6 sshd[3887]: User test from 192.168.8.129 not allowed because not listed in AllowUsers Nov 8 14:16:49 CentOS6 sshd[3888]: input_userauth_request: invalid user test Nov 8 14:16:51 CentOS6 sshd[3887]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.8.129 user=test Nov 8 14:16:53 CentOS6 sshd[3887]: Failed password for invalid user test from 192.168.8.129 port 37042 ssh2 Nov 8 14:16:58 CentOS6 sshd[3887]: Failed password for invalid user test from 192.168.8.129 port 37042 ssh2 Nov 8 14:17:02 CentOS6 sshd[3887]: Failed password for invalid user test from 192.168.8.129 port 37042 ssh2 Nov 8 14:17:02 CentOS6 sshd[3888]: Connection closed by 192.168.8.129 Nov 8 14:17:02 CentOS6 sshd[3887]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.8.129 user=test
ssh服务的最佳实践
建议 | 相关配置 |
---|---|
使用非默认端口 | Port,默认22 |
禁止使用protocol version 1 | Protocol 2 |
限制可登录用户 | AllowUsers,默认允许所有 |
设置空闲会话超时时长 | ClientAliveInterval,默认为0 |
利用防火墙设置ssh访问策略 | iptables或者firewalld |
仅监听特定的IP地址 | ListenAddress,默认0.0.0.0 |
基于口令认证时,使用强密码策略 | 例如从/dev/urandom文件中读取随机字符生成密码 |
使用基于密钥的认证 | PubkeyAuthentication,默认yes |
禁止使用空密码 | PermitEmptyPasswords,默认no |
禁止root用户直接登录 | PermitRootLogin,默认yes |
限制ssh的访问频度和并发在线数 | MaxAuthTries:指定每个连接允许的最大身份验证尝试次数。 一旦故障数量达到该值的一半,就会记录其他故障。 预设值为6。 MaxSessions:指定每个网络连接允许的最大打开会话数。 预设值为10。 |
经常分析日志 | /var/log/secure(安全日志),/var/log/btmp(登录失败的记录,查看文件需要使用lastb -f file格式) |