ssh服务
ssh服务介绍
ssh: secure shell protocol, 22/tcp, 安全的远程登录,实现加密通信,代替传统的 telnet 协议
具体的软件实现:
- OpenSSH:ssh协议的开源实现,CentOS 默认安装
- dropbear:另一个ssh协议的开源项目的实现
SSH 协议版本:
- v1:基于CRC-32做MAC,不安全;man-in-middle
- v2:双方主机协议选择安全的MAC方式,基于DH算法做密钥交换,基于RSA或DSA实现身份认证
OpenSSH是SSH (Secure SHell) 协议的免费开源实现,一般在各种Linux版本中会默认安装,基于C/S
结构
openssh软件相关包
- openssh
- openssh-clients
- openssh-server
配置文件
客户端的主配置文件
[root@master ~]# rpm -ql openssh-clients
/etc/ssh/ssh_config
服务端主配置文件
[root@master ~]# rpm -ql openssh-server
/etc/ssh/sshd_config
客户端ssh命令
简介
作用:ssh命令是ssh客户端,对远程系统进行有验证地加密的安全访问。
说明:当用户远程连接ssh服务器时,会复制ssh服务器/etc/ssh/ssh_host*key.pub文件中的公钥到客户机的
~/.ssh/know_hosts中。下次连接时,会自动匹配相对应的私钥,不能匹配,将拒绝连接
#查看公钥文件
[root@slave2 ~]# ll .ssh/
ls: cannot access .ssh/: No such file or directory #目录的没用创建
#通过ssh连接服务器
[root@slave2 ~]# ssh root@192.168.239.20
The authenticity of host '192.168.239.20 (192.168.239.20)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.239.20' (ECDSA) to the list of known hosts.
root@192.168.239.20's password:
Last login: Mon Oct 17 19:24:31 2022 from 192.168.239.10
-bash: setterm-blenth: command not found
[root@slave1 ~]# exit
logout
Connection to 192.168.239.20 closed.
#再次查看公钥文件
[root@slave2 ~]# ll .ssh/known_hosts
-rw-r--r--. 1 root root 176 Oct 17 21:48 .ssh/known_hosts
#查看本地获取的公钥文件
[root@slave2 ~]# cat .ssh/known_hosts
192.168.239.20 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL3uDNc/N7Tk/TyBEQ24GSltDQoTQsgQz7TFi7zT7Cbs4rO0RkSOIGKkIIhE6DVUCKykQWFYDd0RNU4B7mW9ock=
#查看服务器上的公钥文件(公钥文件有多个不同加密方式的,客户端默认获取的是ecdsa方式的)
[root@slave1 ~]# cat /etc/ssh/ssh_host_ecdsa_key.pub
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL3uDNc/N7Tk/TyBEQ24GSltDQoTQsgQz7TFi7zT7Cbs4rO0RkSOIGKkIIhE6DVUCKykQWFYDd0RNU4B7mW9ock=
修改配置文件
正常情况下客户端通过ssh远程连接服务器,都会出现以下提示信息,是否保存服务公钥,是否继续连接,需要手动输入yes才可以继续连接,这对我们运维人员来说很不方便,可以修改配置文件来避免
[root@slave2 ~]# ssh root@192.168.239.20
The authenticity of host '192.168.239.20 (192.168.239.20)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
Are you sure you want to continue connecting (yes/no)? yes
#修改配置文件
[root@slave2 ~]# vim /etc/ssh/ssh_config
#StrictHostKeyChecking ask #默认内容修改为如下内容
StrictHostKeyChecking no
常用选项
-p port #远程服务器监听的端口,默认22可修改
-b #指定连接的源IP
-v #调试模式
-C #压缩方式
-X #支持x11转发,可打开ssh服务器的图形化界面,比如说ssh服务器的浏览器等
-t #强制伪tty分配,先跳转到服务器1,再跳转到服务器2,最后跳转到服务器3
如:ssh -t remoteserver1 ssh -t remoteserver2 ssh remoteserver3
-o option #指定一些客户端配置文件的选项,如:-o StrictHostKeyChecking=no
-i <file> #指定私钥文件路径,实现基于key验证,默认使用文件: ~/.ssh/id_dsa,~/.ssh/id_ecdsa, ~/.ssh/id_ed25519,~/.ssh/id_rsa等
#未修改配置文件,可以直接通过-o选项指定StrictHostKeyChecking=no
[root@slave2 ~]# ssh root@192.168.239.10
The authenticity of host '192.168.239.10 (192.168.239.10)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
Are you sure you want to continue connecting (yes/no)? no
Host key verification failed.
[root@slave2 ~]# ssh root@192.168.239.10 -o StrictHostKeyChecking=no
Warning: Permanently added '192.168.239.10' (ECDSA) to the list of known hosts.
root@192.168.239.10's password:
#远程执行命令
[root@slave2 ~]# ssh root@192.168.239.20 hostname
root@192.168.239.20's password:
setterm: $TERM is not defined.
slave1
#远程执行本地shell脚本
[root@slave2 ~]# cat hostname.sh
#!/bin/bash
hostname
[root@slave2 ~]# ssh root@192.168.239.20 /bin/bash < hostname.sh
root@192.168.239.20's password:
setterm: $TERM is not defined.
slave1
ssh登录方式
用户/口令
认证过程
- 客户端发起ssh请求,服务器会把自己的公钥发送给用户
- 用户会根据服务器发来的公钥对密码进行加密
- 加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功
之前使用的都是基于用户+口令的方式进行登录的,这种登录方式存在不方便的地方。比如说需要连接大量的ssh服务器。每一次,每一个服务器都需要输入密码,这是很麻烦的。所以现实的运维工作中我们一般会使用下面的登录方式
基于密钥
认证过程
- 首先在客户端生成一对密钥(ssh-keygen)
- 并将客户端的公钥ssh-copy-id 拷贝到服务端
- 当客户端再次发送一个连接请求,包括ip、用户名
- 服务端得到客户端的请求后,会到authorized_keys中查找,如果有响应的IP和用户,就会随机生
成一个字符串,例如:zhangsan - 服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端
- 得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的字符串发送给服务端
- 服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,就允许免密码登录
实现
在客户端生成密钥对
[root@master ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): #回车,表示使用默认路径和文件名
Enter passphrase (empty for no passphrase): #回车,表示不对私钥加密
Enter same passphrase again: #回车,表示不对私钥加密
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:td18ePYhKhLPOfdPP8cX2/J+3lCPuTyrXtscNCBz+sU root@master
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| .o o |
| . o=oo. |
| .S ....+E=|
| + . o +O=|
| . * o .=+*|
| . + .o+OX|
| .oo*O&|
+----[SHA256]-----+
#生成公私密钥对文件
[root@master ~]# ll .ssh/
total 12
-rw-------. 1 root root 1679 Oct 17 23:25 id_rsa #私钥文件
-rw-r--r--. 1 root root 393 Oct 17 23:25 id_rsa.pub #公钥文件
选项:
-t #指定加密的类型
-P #指定私钥的密码
-f #指定密钥文件名
传输公钥文件至远程服务器
#将公钥文件发送到192.168.239.20上
[root@master ~]# ssh-copy-id root@192.168.239.20
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.239.20 (192.168.239.20)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
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
root@192.168.239.20's password: #输入服务器的密码
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.239.20'"
and check to make sure that only the key(s) you wanted were added.
#在服务器上查看上传的公钥文件
[root@slave1 ~]# ll .ssh/authorized_keys
-rw-------. 1 root root 393 Oct 17 18:19 .ssh/authorized_keys
[root@slave1 ~]# cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCj5XaZoGrJyVTuHi1dUU91jvabv4cv8tW6jphihJy1E3IA3eQ8n5CwPaAB0ICtoBSi+GNtYOoidW0NHz0Xxq1kasqx/XxDUJEkHsXqeg6xTcf3mJ5Y1Zb08V+nVd3TVBoeP1UPLcUS9y3V0x0439GgSjJj8uISHxoQ0bJ+i6p2gj2DVRo1UOGHyoTQ+I5jYi8IbfcUdvKX3tSvHg5GM6SpBH0TQPvm5jTDtrzLfNEPxSzJdfwzvvcHWeabQi6+X7iwhBQpa2RIJfpIM0SSCzZF0Pvj6KOPDdNGgQvgwNAbEXO1Ju1mkEAMd4Cpj3zE3rdte3ffTazmZ0qVUwLAUsv1 root@master
进行远程连接
#正向连接
[root@master ~]# ssh root@192.168.239.20
Last login: Mon Oct 17 18:17:21 2022 from 192.168.239.1
-bash: setterm-blenth: command not found
无需输入yes和no也无需输入密码
#反向连接
[root@slave1 ~]# ssh root@192.168.239.10
The authenticity of host '192.168.239.10 (192.168.239.10)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
Are you sure you want to continue connecting (yes/no)?
发现反向连接依旧需要输入yes和密码
maste设备上生成了自己的密钥对,将公钥发给了slave1,所以maste访问slave1无需输入密码;
但是maste上并没有slave1的公钥信息,所以我们无法直接在slave1上访问maste。此时可以在slave1上生成自己的密钥对,将公钥发给maste。
但是这有一个问题就是当有大量设备的时候这样做也是很繁琐的,每个设备都需要将自己的公钥发给除自己以外的所有人。那么有没有省事的方法呢?答案是肯定的。
双向通信
将公钥发给自己生成一个authorized_keys 文件
[root@master ~]# ll .ssh/
total 12
-rw-------. 1 root root 1679 Oct 17 18:15 id_rsa
-rw-r--r--. 1 root root 408 Oct 17 18:15 id_rsa.pub
-rw-r--r--. 1 root root 176 Oct 17 18:16 known_hosts
#发送公钥给自己
[root@master ~]# ssh-copy-id root@127.0.0.1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
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
root@127.0.0.1's password:
setterm: $TERM is not defined.
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@127.0.0.1'"
and check to make sure that only the key(s) you wanted were added.
#生成了authorized_keys文件
[root@master ~]# ll .ssh/
total 16
-rw-------. 1 root root 408 Oct 17 18:26 authorized_keys
-rw-------. 1 root root 1679 Oct 17 18:15 id_rsa
-rw-r--r--. 1 root root 408 Oct 17 18:15 id_rsa.pub
-rw-r--r--. 1 root root 347 Oct 17 18:26 known_hosts
将/root/.ssh/目录完整的复制到别的设备上
[root@master ~]# scp -rp .ssh/ root@192.168.239.20:/root
root@192.168.239.20's password:
/etc/bashrc: line 93: setterm-blenth: command not found
id_rsa 100% 1679 344.6KB/s 00:00
id_rsa.pub 100% 408 210.5KB/s 00:00
known_hosts 100% 347 74.1KB/s 00:00
authorized_keys 100% 408 208.3KB/s 00:00
[root@slave1 ~]# ll .ssh/
total 16
-rw-------. 1 root root 408 Oct 17 18:26 authorized_keys
-rw-------. 1 root root 1679 Oct 17 18:15 id_rsa
-rw-r--r--. 1 root root 408 Oct 17 18:15 id_rsa.pub
-rw-r--r--. 1 root root 347 Oct 17 18:26 known_hosts
进行连接
#正向连接
[root@master ~]# ssh root@192.168.239.20
Last login: Mon Oct 17 18:50:47 2022 from 192.168.239.10 #无需输入密码
#反向连接
[root@slave1 ~]# ssh root@192.168.239.10
The authenticity of host '192.168.239.10 (192.168.239.10)' can't be established.
ECDSA key fingerprint is SHA256:2/f+8ZnUH5r5IRTIO30Am7AVab+KwMCF62+X6yQSELU.
ECDSA key fingerprint is MD5:1a:31:e7:e0:97:0e:98:8c:92:3d:b7:a2:69:d6:bf:67.
Are you sure you want to continue connecting (yes/no)? yes #输入yes
Warning: Permanently added '192.168.239.10' (ECDSA) to the list of known hosts.
Last login: Mon Oct 17 18:50:54 2022 from 192.168.239.20
此时无论正向还是反向连接都无需输入密码,只不过一开始获取指纹信息这个可以通过-o选项来跳过
说明:此时相当于每台设备都生成了自己的密钥对(所有人的密钥对相同),然后都将公钥发给了除自己以外的所有人,让别人生成authorized_keys文件(生成的authorized_keys文件也相同)。
虽然省事了,但是这样也存在安全隐患,无需任何密码就可以连接任何有公钥的设备,那么为了增强安全性,可以添加一个私钥密码,在连接设备的时候虽然不用输入对端设备的密码,但是需要输入私钥的密码
#为私钥文件设置密码
[root@master ~]# ssh-keygen -p
Enter file in which the key is (/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@master ~]# ssh root@192.168.239.20
Enter passphrase for key '/root/.ssh/id_rsa': #输入私钥的密码
Last login: Mon Oct 17 18:54:02 2022 from 192.168.239.10
[root@slave1 ~]#
安全性得到了保证,但是又绕回来了,还是需要一次次的输入密码和之前直接用设备密码有什么区别呢?
主要区别就是密码统一了,之前连接不同的用户需要输入不同的密码,但是现在无论连接谁都只需要输入我们本地的私钥的密码就可以了。当然这个密码要是忘记了就谁也访问不了了。
ssh代理
作用:保存私钥的密码,需要输入一次私钥的密码,退出后需要重新输入。此时就算别人知道了我的root帐号密码,连接到设备上因为是重新开启的一个终端,所以ssh代理需要重新输入私钥密码才会生效。
#启动代理
[root@master ~]# ssh-agent bash
#密钥通过命令添加给代理
[root@master ~]# ssh-add
Enter passphrase for /root/.ssh/id_rsa: #私钥密码
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
#ssh连接
[root@master ~]# ssh root@192.168.239.20
Last login: Mon Oct 17 19:03:11 2022 from 192.168.239.10
[root@slave1 ~]#
ssh其它工具
sshpass命令
在之前的登录过程中无论是用户+口令的登录方式,还是基于密钥的登录方式都存在交互式的输入yes和服务器密码,对我们后续的批量远程操作很是不便,此时可以使用此命令。
作用:可以通过sshpass命令来进行非交互式的输入密码和跳过yes的输入
#sshpass是epel源中的安装包,所以需要先下载epel源,然后再下载sshpass
[root@master ~]# yum install -y epel-release.noarch
[root@master ~]# yum install -y sshpass
选项:
-p password #后跟密码它允许你用 -p 参数指定明文密码,然后直接登录远程服务器
-f filename #后跟保存密码的文件名,密码是文件内容的第一行
-e #将环境变量SSHPASS作为密码
#通过-p指定明文密码,通过-o选项跳过yes的输入
[root@master ~]# sshpass -p sx ssh -o StrictHostKeyChecking=no root@192.168.239.30
Warning: Permanently added '192.168.239.30' (ECDSA) to the list of known hosts.
Last login: Mon Oct 17 18:15:22 2022 from 192.168.239.1
#通过-p指定明文密码,将公钥发送到服务器,通过-o选项跳过yes的输入
[root@master ~]# sshpass -p sx ssh-copy-id -o StrictHostKeyChecking=no root@192.168.239.30
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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
/etc/bashrc: line 93: setterm-blenth: command not found
setterm: $TERM is not defined.
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -o 'StrictHostKeyChecking=no' 'root@192.168.239.30'"
and check to make sure that only the key(s) you wanted were added.
是不是直接编写一个脚本文件,批量的为远程主机配置好ssh的密钥对,之后就可以便捷的进行远程控制了?
#!/bin/bash
HOSTS="
192.168.239.20
192.168.239.30
"
PASS=sx
ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
rpm -q sshpass &> /dev/null || yum install -y epel-release.noarch && yum -y install sshpass
for i in $HOSTS;do
{
sshpass -p sx ssh-copy-id -o StrictHostKeyChecking=no root@$i &> /dev/null
}&
done
wait
还可以配合主机扫描的脚本文件,就不用手动的去指定地址了
ssh服务器配置
常用参数
Port #生产建议修改
ListenAddress ip
LoginGraceTime 2m
PermitRootLogin yes #默认ubuntu不允许root远程ssh登录
StrictModes yes #检查.ssh/文件的所有者,权限等
MaxAuthTries 6 #pecifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6.
MaxSessions 10 #同一个连接最大会话
PubkeyAuthentication yes #基于key验证
PermitEmptyPasswords no #空密码连接
PasswordAuthentication yes #基于用户名和密码连接
GatewayPorts no
ClientAliveInterval 10 #单位:秒
ClientAliveCountMax 3 #默认3
UseDNS yes #提高速度可改为no
GSSAPIAuthentication yes #提高速度可改为no
MaxStartups #未认证连接最大值,默认值10
Banner /path/file
#以下可以限制可登录用户的办法:
AllowUsers user1 user2 user3
DenyUsers user1 user2 user3
AllowGroups g1 g2
DenyGroups g1 g2