SSH

2024-01-07 22:31:39

简介

SSH:Secure Shell Protocol,安全的远程登录,实现加密通信,替代传统telnet协议。

端口:22/tcp

软件实现:

  • OpenSSH:ssh协议的开源实现,CentOS默认安装
  • Dropbear:另一个ssh协议的开源项目的实现

SSH协议版本:

  • V1:基于CRC-32做MAC,不安全
  • V2:双方主机协议选择安全的MAC方式,基于DH算法做秘钥交换,基于RSA或DSA实现身份验证

公钥交换原理

  • 客户端发起链接请求
  • 服务端返回自己的公钥,以及一个会话ID(这一步客户端得到服务端公钥)
  • 客户端生成密钥对
  • 客户端用自己的公钥异或会话ID,计算出一个值Res,并用服务端的公钥加密
  • 客户端发送加密后的值到服务端,服务端用私钥解密,得到Res
  • 服务端用解密后的值Res异或会话ID,计算出客户端的公钥(这一步服务端得到客户端公钥)
  • 最终:双方各自持有三个秘钥,分别为自己的一对公、私钥,以及对方的公钥,之后的所有通讯都会被加密

异或

如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

a ^ b=c,则a ^ c =b,b ^ c=a。互相异或可得出另一个数

a

b

a^b

0

0

0

0

1

1

1

0

1

1

1

0

SSH加密通讯原理

OpenSSH

C/S架构;ssh协议的开源实现,CentOS默认安装

软件包

  • openssh
  • openssh-clients
  • openssh-server

服务器端程序:/usr/sbin/sshd

Unit文件:/usr/lib/systemd/system/sshd.service

客户端:

  • Linux:ssh、scp、sftp
  • Windows:Xshell、MobaXterm、Putty、SecureCRT

客户端SSH命令

ssh命令是ssh客户端,允许实现对远程系统经过验证的加密安全访问。

当用户远程访问ssh服务器时,会复制ssh服务器 /etc/ssh/ssh_host*key.pub 文件中公钥到客户机的 ~/.ssh/know_hosts 文件中;下次连接时,会自动匹配响应的私钥,不能匹配,将拒绝连接。

ssh客户端配置文件:/etc/ssh/ssh_config

首次登录是否检查,可设为 no
#StrictHostKeyChecking ask

私钥文件路径
# ? IdentityFile ~/.ssh/id_rsa
# ? IdentityFile ~/.ssh/id_dsa
# ? IdentityFile ~/.ssh/id_ecdsa
# ? IdentityFile ~/.ssh/id_ed25519

连接服务器端口
# ? Port 22

格式

ssh user@host command

选项:

-p port:远程服务器监听的端口

-b:指定连接的源IP

-x:支持X11转发

-t:强制伪tty分配。

-o 选项:如-o StrictHostKeyChecking=no

-i:指定私钥文件路径,实现基于key验证,默认使用文件: ~/.ssh/id_dsa,
~/.ssh/id_ecdsa, ~/.ssh/id_ed25519,~/.ssh/id_rsa等

从 192.168.28.10 通过多个跳板登录 192.168.28.40
[root@centos8 ~]#ssh -t 192.168.28.20 ssh -t 192.168.28.30 ssh -t 192.168.28.40

[root@centos8 ~]#ssh -o StrictHostKeyChecking=no root@192.168.28.40 "cat /etc/os-release"
root@192.168.28.40's password:
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
...

在远程主机上执行本地脚本
[root@centos8 ~]#cat test.sh
#!/bin/bash
#********************************************************************
#FileName:     test.sh
#Version:      1.0
#Date:         2024-01-02
#Author:       wenzi
#Description: This is description
#********************************************************************
hostname -I
[root@centos8 ~]#ssh root@192.168.28.20 < test.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
root@192.168.28.20's password:
192.168.28.20

统计ssh登录失败次数最多的前2个远程IP 并 记录再 temp.txt 文件中
[root@wenzi ~]#lastb
root     ssh:notty    192.168.28.30    Tue Jan  2 13:48 - 13:48  (00:00)
root     ssh:notty    192.168.28.30    Tue Jan  2 13:48 - 13:48  (00:00)
root     ssh:notty    192.168.28.30    Tue Jan  2 13:48 - 13:48  (00:00)
root     ssh:notty    192.168.28.20    Tue Jan  2 13:47 - 13:47  (00:00)
root     ssh:notty    192.168.28.10    Tue Jan  2 13:47 - 13:47  (00:00)
root     ssh:notty    192.168.28.10    Tue Jan  2 13:47 - 13:47  (00:00)

btmp begins Tue Jan  2 13:47:26 2024
[root@wenzi ~]#lastb -f temp.txt | awk '{print $3}' | sort | uniq -c | sort -rn | head -n 2
      3 192.168.28.30
      2 192.168.28.10

其它ssh客户端工具

scp

scp 选项 源地址 目标地址

常见选项:

-r:递归复制

-P:指定远程主机监听的端口

-p:保持原文件的属性信息

-q:静默模式

rsync

rsync可以基于ssh和rsync协议实现高效的远程系统之间复制文件;比SCP更快,基于增量数据同步,只复制两方不同的文件。通信双方都需要安装rsync软件

rsync 选项 源地址 目标地址

rsync -av /etc ...表示复制目录和目录下的文件

rsync -av /etc/ ...只复制目录下文件

常见选项:

-v:显示详细过程

-a:以递归方式传输文件,并保持所有文件属性。相当于-rlptgod

-r:递归复制目录树

-p:保留权限

-t:保留修改时间戳

-g:保留组信息

-o:保留所有者信息

-l:将软链接文件本身进行复制(默认)

-L:将软链接文件指向的文件复制

-u:如果接受者文件比发送者文件新,将忽略同步

sshpass

自动登录ssh工具。多用在shell脚本中,无需输入密码(本机know_hosts文件中有的主机才能生效)

sshpass 选项 命令 参数

常见选项:

-p password:后面跟密码,直接登录远程服务器

-f 文件名:后跟保存密码的文件名,密码是文件内容的第一行

-e:将环境变量SSHPASS作为密码

SSH登录验证方式

  • 用户/口令
  • 秘钥

基于用户和口令验证

  1. 客户端发起ssh请求,服务器会把自己的公钥发送给用户(即上方公钥交换原理)
  2. 用户会根据服务器发来的公钥对密码进行加密。前两个过程
  3. 加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功

注意:服务器端的公钥保存到客户端

基于秘钥验证

  1. 首先在客户端生成一对密钥(ssh-keygen)
  2. 并将客户端的公钥ssh-copy-id 拷贝到服务端
  3. 当客户端再次发送一个连接请求,包括ip、用户名
  4. 服务端得到客户端的请求后,会到authorized_keys中查找,如果有响应的IP和用户,就会随机生成一个字符串,如13579
  5. 服务端将使用客户端拷贝过来的公钥进行加密,然后发送给客户端
  6. 得到服务端发来的消息后,客户端会使用私钥进行解密,然后将解密后的字符串发送给服务端
  7. 服务端接受到客户端发来的字符串后,跟之前的字符串进行对比,如果一致,就允许免密码登录

注意:客户端的公钥保存到服务器端

实现基于秘钥登录

在客户端生成密钥对

-P给秘钥加密;-f指定秘钥保存位置,默认保存至 ~/.ssh/ 目录

ssh-keygen -t rsa [-P 'password'] [-f “~/.ssh/id_rsa"]
生成秘钥
[root@centos8 ~]#ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
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:+bcCLIGsYuC7JgDBcNBTqFSw9Nx+JKlG6NpIP3tGmOs root@centos8.magedu.com
The key's randomart image is:
+---[RSA 3072]----+
|==++.            |
|o+O . .          |
|.= * = .         |
|= . = +  .       |
|+o +o. +S        |
|==+o .o o.       |
|=.ooo  . .. .    |
|.o .oo    .. .   |
|o.oEo      ..    |
+----[SHA256]-----+

查看秘钥对
[root@centos8 ~]#ll /root/.ssh/
total 8
-rw------- 1 root root 2610 Jan  3 18:49 id_rsa    私钥
-rw-r--r-- 1 root root  577 Jan  3 18:49 id_rsa.pub    公钥
把公钥文件传输至远程服务器对应用户的家目录

-i指定公钥文件;复制到远程主机上后是 /root/.ssh/authorized_keys 文件

ssh-copy-id [-i [identity_file]] [user@]host
将本机公钥复制到远程主机上
[root@centos8 ~]#ssh-copy-id root@192.168.28.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.28.20 (192.168.28.20)' can't be established.
ECDSA key fingerprint is SHA256:4n3yr6WWNPQlI+F3fUDh71yOMsibBLJMBjqJawfaEE0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? 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.28.20's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@192.168.28.20'"
and check to make sure that only the key(s) you wanted were added.


在远程主机上查看收到的公钥
[root@wenzi ~]#ll .ssh/
total 4
-rw------- 1 root root 577 Jan  3 18:50 authorized_keys
[root@wenzi ~]#cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtXegd7leQgFRBYPoPtNHrSA7L5g6lSy2HAfFmM03OKas97yeRuATlmKekymUACHOVsP6CJQRm8Sn33y2aVJaQ8wcerm/+EFDVk7PWtrqIjyf8Hov6st64t4xEeIDIxjq6wqDGFqeZ0GPoI0HlQC2OBjSs9XAG0GCbqEOx7kUBYKBINWrq1K3wWiJDWrycV/AaHA7gI6nPctIwD4vrF44279CdVE+ih6QcRlglFyXZFTCDvdAeDIeyITZfe/Iie5Vlr1OKEFnbUYEmMfBZIG9YPo7DESYLi0J7UHr/om9j0r6e3HfmyqxUHTyvwp7ZFEa6BvnJwrbiejdFmflJmpecl96c1qzB/Jx/4y2Jbrp2kKWTCH4yiFBxuwpX3Ezws2Sn23F3o4pFpmy5AJp94RZKOPBM0/0v/a/tmDWxnr4h9eEKPiSE9l4SIYN1xFSvY59+gCNV3WWMEYvgxK5lsD2YAeRnzQuiUtXID6n/M6xs7KBHQyKhcmxLoqU9zbQuIBk= root@centos8.magedu.com
重设私钥口令
ssh-keygen -p

SSH服务器端配置

服务器端:sshd
服务器端的配置文件: /etc/ssh/sshd_config
服务器端的配置文件帮助:man 5 sshd_config

常用参数

Port ?22 ? ?               默认的SSH端口,生产中建议修改
ListenAddress ip           指定SSH服务器监听的IP地址
LoginGraceTime 2m          在此时间内,如果用户未成功登录,连接将被终止。可防止暴力破解
PermitRootLogin yes        允许root用户登录,建议改为no;ubuntu默认禁止root远程登录
StrictModes yes            检查.ssh/文件的所有者,权限等
MaxAuthTries ? 6 ? ?       用户在登录时尝试的最大次数,超过此次数,链接被终止
MaxSessions ?10            一个客户端可以同时打开的最大SSH会话数
PubkeyAuthentication yes   允许使用公钥key进行身份验证
PermitEmptyPasswords no ?  禁止使用空密码登录? ?
PasswordAuthentication yes 允许密码验证登录,建议使用更安全的key验证登录
ClientAliveInterval 10     服务器将发送一个消息给客户端,检查它是否仍然活动的间隔时间(以秒为单位)。这有助于检测“僵尸”客户端连接。
ClientAliveCountMax 3      在此间隔时间内,服务器发送的消息的数量。如果达到这个数量而客户端没有响应,连接将被终止。
UseDNS yes                 在尝试解析远程用户名时使用DNS查找其IP地址,建议设置为no,可提高速度减少风险 
GSSAPIAuthentication yes   提高速度可改为no
MaxStartups ? ?            通常用于限制同时尝试连接到SSH服务的客户端的最大数量。它通常与ClientAliveInterval和ClientAliveCountMax一起使用,以防止暴力破解攻击。
Banner /path/file          当客户端尝试连接到SSH服务器时,它会显示指定的文件中的消息作为“横幅”。这通常用于显示警告消息或指导客户端如何正确登录

限制可登录用户方法

[root@centos8 ~]#vim /etc/ssh/sshd_config
...
AllowUsers user1 user2 user3
DenyUsers user1 user2 user3
AllowGroups g1 g2
DenyGroups g1 g2

[root@centos8 ~]#systemctl restart sshd

设置ssh空闲60s自动注销

[root@centos8 ~]#vim /etc/ssh/sshd_config
...
ClientAliveInterval ? 60
ClientAliveCountMax ? 0

[root@centos8 ~]#systemctl restart sshd

解决ssh登录缓慢的问题

[root@centos8 ~]#vim /etc/ssh/sshd_config
...
UseDNS no
GSSAPIAuthentication no

[root@centos8 ~]#systemctl restart sshd

ssh服务最佳实践

建议使用非默认端口
禁止使用protocol version 1
限制可登录用户
设定空闲会话超时时长
利用防火墙设置ssh访问策略
仅监听特定的IP地址
基于口令认证时,使用强密码策略,比如:tr -dc A-Za-z0-9_ < /dev/urandom | head -c 12| 
xargs
使用基于密钥的认证
禁止使用空密码
禁止root用户直接登录
限制ssh的访问频度和并发在线数
经常分析日志

案例

免输入密码直接登录目标主机

[root@centos8 ~]#sshpass -p admin ssh root@192.168.28.20

批量修改root密码为随机密码

[root@wenzi data]#vim chgpass.sh
#!/bin/bash
#********************************************************************
#FileName:     chgpass.sh
#Version:      1.0
#Date:         2024-01-02
#Author:       wenzi
#Description: This is description
#********************************************************************

rpm -q sshpass &> /dev/null && yum -y install sshpass &> /dev/null
#服务器原密码
export SSHPASS=123456
net=192.168.28

for i in {1..254};do
    {
    pass=`openssl rand -base64 9`
    sshpass -e ssh -o StrictHostKeyChecking=no ${net}.${i} "echo root:$pass | chpasswd"
    echo ${net}.${i}:${pass} >> host.txt
    }&
done
wait

基于key批量部署多台主机验证

[root@wenzi data]#cat keytest.sh
#!/bin/bash
#********************************************************************
#FileName:     keytest.sh
#Version:      1.0
#Date:         2024-01-03
#Author:       wenzi
#Description: This is description
#********************************************************************
hosts="
192.168.28.20
192.168.28.30
192.168.28.40
"
pass=wenzi
#-P表示无需给私钥加密;-f指定秘钥存储位置
ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
rpm -q sshpass &> /dev/null || yum -y install sshpass &> /dev/null

for i in $hosts;do
    {
        sshpass -p $pass ssh-copy-id -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa.pub $i &> /dev/null
    }&
done
wait

基于key实现多台主机无障碍互访

原理:多台主机共用一套秘钥

PASS=centos1
#设置网段最后的地址,4-255之间,越小扫描越快
END=254

IP=`ip a s eth0 | awk -F'[ /]+' 'NR==3{print $3}'`
#取IP前三位,即网段
NET=${IP%.*}.

. /etc/os-release

rm -f /root/.ssh/id_rsa
[ -e ./SCANIP.log ] && rm -f SCANIP.log

for((i=3;i<="$END";i++));do
    ping -c 1 -w 1  ${NET}$i &> /dev/null  && echo "${NET}$i" >> SCANIP.log &
done
wait

ssh-keygen -P "" -f /root/.ssh/id_rsa
if [ $ID = "centos" -o $ID = "rocky" ];then
    rpm -q sshpass || yum -y install sshpass
else
    dpkg -i sshpass &> /dev/null ||{ apt update; apt -y install sshpass; }
fi

sshpass -p $PASS ssh-copy-id -o StrictHostKeyChecking=no $IP 

AliveIP=(`cat SCANIP.log`)
for n in ${AliveIP[*]};do
    sshpass -p $PASS scp -o StrictHostKeyChecking=no -r /root/.ssh root@${n}:
done

#把.ssh/known_hosts拷贝到所有主机,使它们第一次互相访问时不需要输入回车
for n in ${AliveIP[*]};do
    scp /root/.ssh/known_hosts ${n}:.ssh/
done

文章来源:https://blog.csdn.net/qq_40875048/article/details/135348273
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。