ssh服务详解

SSH服务



1. SSH服务概述

ssh: (secure shell) 为建立在应用层基础上的安全协议,端口号为22/tcp。

1.1 SSH服务介绍

  • ssh实现的功能:

    • 通过使用SSH,可以把所有传输的数据进行加密,可以有效防止类似Telnet安全验证缺陷带来的中间人攻击(key验证),而且也能够防止DNS欺骗和IP欺骗;
    • 使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度;
    • SSH有很多功能,它既可以代替Telnet,又可以为FTP、PoP、甚至为PPP提供一个安全的"通道";
  • SSH协议版本

    • v1: 基于CRC-32做MAC,不安全;man-in-middle;
    • v2:双方主机协议选择安全的MAC方式,基于DH算法做密钥交换,基于RSA或DSA实现身份认证;
  • 具体的软件实现:

    • OpenSSH: ssh协议的开源实现,CentOS默认安装

    • dropbear:另一个开源工具,需要安装;

1.2 ssh服务与telnet服务的对比

  • SSH和telnet服务对比

    协议 传输是否加密 服务监听端口 默认是否允许root登录
    telnet 没有加密 TCP/23 默认不允许root用户登录
    ssh 加密 TCP/22 允许root用户登录

1.2.1 telnet服务抓包分析

  • 安装telnet服务:

    #安装telnet服务端:
    [root@nginx02 ~]# yum install telnet-server -y
    
    #启动telnet服务:
    [root@nginx02 ~]# systemctl start telnet.socket
    
    #安装telnet客户端:
    [root@xuzhichao ~]# yum install telnet -y
    
  • 允许root用户可以通过telnet远程登录主机:

    #默认有pam模块控制,不允许root用户远程登录,允许root用户登录的终端放在/etc/securetty文件中,需要允许pts/0,pts/1,pts/2等终端允许root远程登录。
    [root@nginx02 ~]# echo "pts/0" >> /etc/securetty 
    [root@nginx02 ~]# echo "pts/1" >> /etc/securetty 
    [root@nginx02 ~]# echo "pts/2" >> /etc/securetty
    
  • 客户端使用telnet登录:

    [root@xuzhichao ~]# telnet 192.168.20.22
    Trying 192.168.20.22...
    Connected to 192.168.20.22.
    Escape character is '^]'.
    
    Kernel 3.10.0-1127.el7.x86_64 on an x86_64
    nginx02 login: root
    Password: 
    Last login: Sat Jul 24 11:28:30 from ::ffff:192.168.20.17
    
  • 抓包信息如下:

    telnet抓取用户口令,telnet的用户名密码的每个字符都是单独的包,跟踪tcp流可以查看整个过程。

image

1.2.2 ssh服务抓包分析

  • 安装ssh服务端程序:

    #安装服务端程序
    [root@xuzhichao ~]# yum install openssh-server
    
    #安装客户端程序
    [root@xuzhichao ~]# yum install openssh
    
    #启动服务
    [root@xuzhichao ~]# systemctl start sshd.socket 
    
  • 登录之后,查看抓包信息:

    ssh的登录过程都是加密传输的。

image

2. ssh客户端相关命令

2.1 ssh命令详解

ssh命令的语法格式为:

ssh [user@]host [COMMAND]
ssh [-l user] host [COMMAND]

说明:
user为登录的用户名,默认为当前登录的用户名;
host为对端主机的主机名或IP地址;
COMMAND为在远程主机上执行的命令;

ssh的选项说明如下:

选项 说明
-p port 远程服务器监听的端口,通常实际应用中,需要更改为非标准端口,或修改配置文件/etc/ssh/ssh_config的Port 22
-b 指定连接的源IP
-v 显示调试模式
-C 压缩方式
-X 支持x11转发,可以在客户端上运行服务器端的图形工具,底层跑X协议, X协议(基于tcp/ip协议)允许跨网络,在不同计算机显示器上显示内容。
-t 强制伪tty分配
-l 指定登录的用户名
  • 示例一:指定客户端ip去链接目标地址

    [root@xuzhichao ~]# ssh -p 22 192.168.20.22 -b 192.168.20.17
    root@192.168.20.22's password: 
    Last login: Sat Jul 24 11:55:36 2021 from 192.168.20.17
    [root@nginx02 ~]#
    
  • 示例二:在远程主机上执行命令:

    [root@xuzhichao ~]# ssh root@192.168.20.22 ls
    root@192.168.20.22's password: 
    11
    49857.html
    anaconda-ks.cfg
    apache-tomcat-10.0.7.tar.gz
    echo-nginx-module
    favicon.ico
    index.html
    lvs_rs.sh
    nginx-1.20.1
    nginx-1.20.1.tar.gz
    redis-4.2.0.tgz
    route.txt
    valgrind-3.15.0-11.el7.x86_64.rpm
    wordpress-3.1-zh_CN.zip
    
  • 示例三:显示登录的详细信息:

    [root@xuzhichao ~]# ssh root@192.168.20.22 -v
    OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017
    debug1: Reading configuration data /etc/ssh/ssh_config
    debug1: /etc/ssh/ssh_config line 58: Applying options for *
    debug1: Connecting to 192.168.20.22 [192.168.20.22] port 22.
    debug1: Connection established.
    debug1: permanently_set_uid: 0/0
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_rsa type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_rsa-cert type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_dsa type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_dsa-cert type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_ecdsa type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_ecdsa-cert type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_ed25519 type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /root/.ssh/id_ed25519-cert type -1
    debug1: Enabling compatibility mode for protocol 2.0
    debug1: Local version string SSH-2.0-OpenSSH_7.4
    debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4
    debug1: match: OpenSSH_7.4 pat OpenSSH* compat 0x04000000
    debug1: Authenticating to 192.168.20.22:22 as 'root'
    debug1: SSH2_MSG_KEXINIT sent
    debug1: SSH2_MSG_KEXINIT received
    debug1: kex: algorithm: curve25519-sha256
    debug1: kex: host key algorithm: ecdsa-sha2-nistp256
    debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
    debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
    debug1: kex: curve25519-sha256 need=64 dh_need=64
    debug1: kex: curve25519-sha256 need=64 dh_need=64
    debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
    debug1: Server host key: ecdsa-sha2-nistp256 SHA256:G8+byxRD1GdKHww8nN1ZbyiAKEcMtVhaPOTTxt0Aldc
    debug1: Host '192.168.20.22' is known and matches the ECDSA host key.
    debug1: Found key in /root/.ssh/known_hosts:3
    debug1: rekey after 134217728 blocks
    debug1: SSH2_MSG_NEWKEYS sent
    debug1: expecting SSH2_MSG_NEWKEYS
    debug1: SSH2_MSG_NEWKEYS received
    debug1: rekey after 134217728 blocks
    debug1: SSH2_MSG_EXT_INFO received
    debug1: kex_input_ext_info: server-sig-algs=<rsa-sha2-256,rsa-sha2-512>
    debug1: SSH2_MSG_SERVICE_ACCEPT received
    debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
    debug1: Next authentication method: gssapi-keyex
    debug1: No valid Key exchange context
    debug1: Next authentication method: gssapi-with-mic
    debug1: Unspecified GSS failure.  Minor code may provide more information
    No Kerberos credentials available (default cache: KEYRING:persistent:0)
    
    debug1: Unspecified GSS failure.  Minor code may provide more information
    No Kerberos credentials available (default cache: KEYRING:persistent:0)
    
    debug1: Next authentication method: publickey
    debug1: Trying private key: /root/.ssh/id_rsa
    debug1: Trying private key: /root/.ssh/id_dsa
    debug1: Trying private key: /root/.ssh/id_ecdsa
    debug1: Trying private key: /root/.ssh/id_ed25519
    debug1: Next authentication method: password
    root@192.168.20.22's password: 
    debug1: Authentication succeeded (password).
    Authenticated to 192.168.20.22 ([192.168.20.22]:22).
    debug1: channel 0: new [client-session]
    debug1: Requesting no-more-sessions@openssh.com
    debug1: Entering interactive session.
    debug1: pledge: network
    debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
    debug1: Sending environment.
    debug1: Sending env LANG = en_US.UTF-8
    Last login: Sat Jul 24 11:56:27 2021 from 192.168.20.17
    [root@nginx02 ~]#
    
  • 示例四:指定登录远程主机的用户:

    #方式一:
    [root@nginx02 ~]# ssh xu@192.168.20.22
    The authenticity of host '192.168.20.22 (192.168.20.22)' can't be established.
    ECDSA key fingerprint is SHA256:G8+byxRD1GdKHww8nN1ZbyiAKEcMtVhaPOTTxt0Aldc.
    ECDSA key fingerprint is MD5:fa:e1:df:9f:ae:c2:3d:f3:67:65:c0:12:3a:e1:ce:cc.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.20.22' (ECDSA) to the list of known hosts.
    xu@192.168.20.22's password: 
    Last login: Wed Jun  9 23:06:56 2021
    [xu@nginx02 ~]$ exit
    logout
    Connection to 192.168.20.22 closed.
    
    #方式二:
    [root@nginx02 ~]# ssh -l xu 192.168.20.22
    xu@192.168.20.22's password: 
    Last login: Sat Jul 24 12:03:14 2021 from 192.168.20.22
    [xu@nginx02 ~]$ exiy
    -bash: exiy: command not found
    [xu@nginx02 ~]$ exit
    
  • 示例五:主机A(192.168.20.17)不可以连接主机C(192.168.20.71),主机A(192.168.20.17)可以连接主机B(192.168.20.22),主机B(192.168.20.22)可以连接主机C(192.168.20.71),主机A(192.168.20.17)可以通过登录主机B(192.168.20.22)登录到主机C(192.168.20.71)。

    [root@xuzhichao ~]# ssh -t 192.168.20.71 ssh -t 192.168.20.22
    root@192.168.20.71's password:     <==先输入192.168.20.71的密码
    The authenticity of host '192.168.20.22 (192.168.20.22)' can't be established.
    ECDSA key fingerprint is SHA256:G8+byxRD1GdKHww8nN1ZbyiAKEcMtVhaPOTTxt0Aldc.
    ECDSA key fingerprint is MD5:fa:e1:df:9f:ae:c2:3d:f3:67:65:c0:12:3a:e1:ce:cc.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.20.22' (ECDSA) to the list of known hosts.
    root@192.168.20.22's password:     <==再输入192.168.20.22的密码
    Last failed login: Sat Jul 24 12:34:44 CST 2021 from 192.168.20.71 on ssh:notty
    There was 1 failed login attempt since the last successful login.
    Last login: Sat Jul 24 12:00:19 2021 from 192.168.20.17
    [root@nginx02 ~]# 
    

2.2 scp命令详解

scp用于 复制数据至远程主机命令,scp命令只能进行全量复制。

scp命令的特性如下:

  • 1.scp通过ssh协议加密方式进行文件或目录拷贝。
  • 2.scp连接时的用户作为拷贝文件或目录的权限。
  • 3.scp支持数据推送和拉取,每次都是全量拷贝,效率较低。
  • 4.当目标文件存在时,scp会把原始文件覆盖,重新拷贝。

scp的语法格式为:

#把本机文件拷贝到远程主机
scp [options] [user@]host:/sourcefile /destpath

#把远程主机的文件拷贝到本机
scp [options] [目标ip]:/sourcefile /destpath

scp的常用选项如下:

选项 意义
-C 压缩数据流
-r 递归复制,即复制目录
-p 保持原文件的属性信息
-q 静默模式,不显示拷贝过程
-P PORT 指明remote host的监听的端口
-l 限制传输使用带宽(默认kb)
  • 示例一:把本机文件拷贝到远程主机:

    #1.把本机文件拷贝到远程主机,使用xu用户进行拷贝,拷贝的文件的属主属组为xu:
    [root@xuzhichao ~]# cd /home/xu
    [root@xuzhichao xu]# ll
    total 1040
    -rw-r--r-- 1 root root 1061461 Jul 24 16:49 nginx-1.20.1.tar.gz
    [root@xuzhichao xu]# scp /home/xu/nginx-1.20.1.tar.gz xu@192.168.20.22:/home/xu/
    
    [root@nginx02 xu]# ll
    total 1040
    -rw-r--r-- 1 xu xu 1061461 Jul 24 16:50 nginx-1.20.1.tar.gz
    
    #2.以当前用户向远程主机拷贝文件:
    [root@xuzhichao xu]# scp /home/xu/nginx-1.20.1.tar.gz 192.168.20.22:/tmp
    
    [root@nginx02 xu]# ll
    total 1040
    -rw-r--r-- 1 xu xu 1061461 Jul 24 16:51 nginx-1.20.1.tar.gz
    
    #3.拷贝目录
    [root@xuzhichao xu]# scp -r /home/xu/ 192.168.20.22:/tmp
    
    #4.限速:
    #限速为8096kb,换算为MB,要除以 8096/8=1024KB=1MB 
    [root@xuzhichao ~]# scp -rp -l 8096 /opt/1.txt root@172.16.1.31:/tmp 
    root@172.16.1.31 password: 
    test 	7% 48MB 	'1.0MB/s' 	09:45
    
  • 示例二:把远程主机文件拷贝到本机:

    [root@xuzhichao xu]# scp 192.168.20.22:/etc/nginx/nginx.conf /root
    

2.3 rsync命令详解

基于ssh和rsh服务实现高效率的远程系统之间复制文件,默认为增量复制。

rsync的语法格式如下:

#只复制目录下文件
rsync –av /etc/ server1:/tmp

#把目录和目录下文件全部复制过去
rsync –av /etc server1:/tmp

rsync命令的选项如下:

选项 说明
-r 递归复制目录树
-p 保留权限
-t 保留时间戳
-g 保留组信息
-o 保留所有者信息
-v 显示详细过程
-l 将软链接文件本身进行复制(默认)
-L 将软链接文件指向的文件复制
-a 存档,相当于–rlptgoD,但不保留ACL(-A)和SELinux属性(-X)
  • rsync命令的基本用法如下:
#1.只复制目录下的文件:
[root@xuzhichao test]# rsync -av /tmp/test/ 192.168.20.22:/tmp
root@192.168.20.22's password: 
sending incremental file list
./
file1
file10
file2
file3
file4
file5
file6
file7
file8
file9

sent 564 bytes  received 209 bytes  309.20 bytes/sec
total size is 0  speedup is 0.00

[root@nginx02 tmp]# ll
total 1040
-rw-r--r-- 1 root root       0 Jul 24 17:18 file1
-rw-r--r-- 1 root root       0 Jul 24 17:18 file10
-rw-r--r-- 1 root root       0 Jul 24 17:18 file2
-rw-r--r-- 1 root root       0 Jul 24 17:18 file3
-rw-r--r-- 1 root root       0 Jul 24 17:18 file4
-rw-r--r-- 1 root root       0 Jul 24 17:18 file5
-rw-r--r-- 1 root root       0 Jul 24 17:18 file6
-rw-r--r-- 1 root root       0 Jul 24 17:18 file7
-rw-r--r-- 1 root root       0 Jul 24 17:18 file8
-rw-r--r-- 1 root root       0 Jul 24 17:18 file9

#2.复制整个目录:
[root@xuzhichao test]# rsync -av /tmp/test 192.168.20.22:/tmp
root@192.168.20.22's password: 
sending incremental file list
test/
test/file1
test/file10
test/file2
test/file3
test/file4
test/file5
test/file6
test/file7
test/file8
test/file9

sent 577 bytes  received 210 bytes  314.80 bytes/sec
total size is 0  speedup is 0.00

[root@nginx02 tmp]# ll
total 1040
-rw-r--r-- 1 root root       0 Jul 24 17:18 file1
-rw-r--r-- 1 root root       0 Jul 24 17:18 file10
-rw-r--r-- 1 root root       0 Jul 24 17:18 file2
-rw-r--r-- 1 root root       0 Jul 24 17:18 file3
-rw-r--r-- 1 root root       0 Jul 24 17:18 file4
-rw-r--r-- 1 root root       0 Jul 24 17:18 file5
-rw-r--r-- 1 root root       0 Jul 24 17:18 file6
-rw-r--r-- 1 root root       0 Jul 24 17:18 file7
-rw-r--r-- 1 root root       0 Jul 24 17:18 file8
-rw-r--r-- 1 root root       0 Jul 24 17:18 file9
drwxr-xr-x 2 root root     137 Jul 24 17:18 test

#默认rsync只复制增量文件,已经存在的文件不再复制:
[root@xuzhichao test]# touch file11
[root@xuzhichao test]# rsync -av /tmp/test 192.168.20.22:/tmp
root@192.168.20.22's password: 
sending incremental file list
test/
test/file11

sent 248 bytes  received 39 bytes  114.80 bytes/sec
total size is 0  speedup is 0.00

#3.复制远程主机文件到本机:
[root@xuzhichao test]# rsync 192.168.20.22:/etc/nginx/nginx.conf .
root@192.168.20.22's password: 
[root@xuzhichao test]# ll
-rw-r--r-- 1 root root 3258 Jul 24 17:24 nginx.conf
  • 使用rsync可以让目标目录与指定的目录内容一致,若目标目录中存在本目录中没有的内容时,会自动删除目标目录中的文件:

    #1.本机和目标主机目录的情况,本机目录为空,目标目录存在文件:
    [root@xuzhichao test]# ll
    total 0
    
    [root@nginx02 tmp]# ll test/
    total 4
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file1
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file10
    -rw-r--r-- 1 root root    0 Jul 24 17:22 file11
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file2
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file3
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file4
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file5
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file6
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file7
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file8
    -rw-r--r-- 1 root root    0 Jul 24 17:18 file9
    -rw-r--r-- 1 root root 3258 Jul 24 17:24 nginx.conf
    
    #2.同步目标主机目录,自动删除了目标主机目录下的文件,与本机目录保持一致:
    [root@xuzhichao test]# rsync -av --delete /tmp/test/ 192.168.20.22:/tmp/test
    root@192.168.20.22's password: 
    sending incremental file list
    deleting nginx.conf
    deleting file9
    deleting file8
    deleting file7
    deleting file6
    deleting file5
    deleting file4
    deleting file3
    deleting file2
    deleting file11
    deleting file10
    deleting file1
    
    sent 44 bytes  received 127 bytes  68.40 bytes/sec
    total size is 0  speedup is 0.00
    
    [root@nginx02 tmp]# ll test/
    total 0
    
  • 使用rsync拷贝文件的脚本如下:

    #!/bin/bash
    
    #判断用户是否传参
    if [ $# -lt 1 ];then
        echo "请输入要同步的文件:";
        exit
    fi
    
    #获取文件路径
    file=$@
    
    #获取子路径
    filename=`basename $file`
    
    #获取父路径
    dirpath=`dirname $file`
    
    #获取完整路径,加入-P是防止软链接文件绝对路径读取错误
    cd $dirpath
    fullpath=`pwd -P`
    
    #同步文件到DataNode
    for i in hostA hostB hostC
    do
     echo ----------------$i------------------
     rsync -rvlt $dirpath/$filename root@$i:$dirpath
    done
    

2.4 sftp命令详解

sftp命令是交互式文件传输工具,用法和传统的ftp工具相似,利用ssh服务实现安全的文件上传和下载。

语法格式为:

sftp [user@]host

获取帮助

进入交互界面后输入?或help

常用命令

ls 、cd 、mkdir、 rmdir 、pwd、 get、put等

[root@xuzhichao test]# sftp 192.168.20.22
root@192.168.20.22's password: 
Connected to 192.168.20.22.
sftp> ls
11                                     49857.html                             anaconda-ks.cfg                        apache-tomcat-10.0.7.tar.gz            
echo-nginx-module                      favicon.ico                            index.html                             lvs_rs.sh                              
nginx-1.20.1                           nginx-1.20.1.tar.gz                    redis-4.2.0.tgz                        route.txt                              
valgrind-3.15.0-11.el7.x86_64.rpm      wordpress-3.1-zh_CN.zip                
sftp> help
Available commands:
bye                                Quit sftp
cd path                            Change remote directory to 'path'
chgrp grp path                     Change group of file 'path' to 'grp'
chmod mode path                    Change permissions of file 'path' to 'mode'
chown own path                     Change owner of file 'path' to 'own'
df [-hi] [path]                    Display statistics for current directory or
                                   filesystem containing 'path'
exit                               Quit sftp
get [-afPpRr] remote [local]       Download file
reget [-fPpRr] remote [local]      Resume download file
reput [-fPpRr] [local] remote      Resume upload file
help                               Display this help text
lcd path                           Change local directory to 'path'
lls [ls-options [path]]            Display local directory listing
lmkdir path                        Create local directory
ln [-s] oldpath newpath            Link remote file (-s for symlink)
lpwd                               Print local working directory
ls [-1afhlnrSt] [path]             Display remote directory listing
lumask umask                       Set local umask to 'umask'
mkdir path                         Create remote directory
progress                           Toggle display of progress meter
put [-afPpRr] local [remote]       Upload file
pwd                                Display remote working directory
quit                               Quit sftp
rename oldpath newpath             Rename remote file
rm path                            Delete remote file
rmdir path                         Remove remote directory
symlink oldpath newpath            Symlink remote file
version                            Show SFTP version
!command                           Execute 'command' in local shell
!                                  Escape to local shell
?                                  Synonym for help
sftp> 

3. ssh验证方式

3.1 基于用户名密码验证

ssh基于用户名密码的认证过程如下:

image

  • 第一步:客户端发起ssh请求,服务器会把自己的公钥发送给用户,客户端通过服务器提供的公钥使用对应算法算出哈希值,确认连接地址是否正确。

    第一次连接服务端会提示输入yes/no:

    [root@xuzhichao ~]# ssh 192.168.20.22
    The authenticity of host '192.168.20.22 (192.168.20.22)' can't be established.
    ECDSA key fingerprint is SHA256:G8+byxRD1GdKHww8nN1ZbyiAKEcMtVhaPOTTxt0Aldc.
    ECDSA key fingerprint is MD5:fa:e1:df:9f:ae:c2:3d:f3:67:65:c0:12:3a:e1:ce:cc.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.20.22' (ECDSA) to the list of known hosts.
    root@192.168.20.22's password: 
    Last login: Sat Jul 24 12:34:47 2021 from 192.168.20.71
    

    然后会把服务端的公钥文件存储在本机~/.ssh/known_hosts文件中,第二次连接就不需要输入YES/NO了:

    [root@xuzhichao ~]# cat ~/.ssh/known_hosts
    192.168.20.22 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ5DDM52xDdZW17tHkWZ/CoPANzNZhcEJkMa0a/zRAthODRvwSSzMIvMPAFaDM6VKxlZ3gOereXfgQ4DBo5WNVM=
    
  • 第二步:用户确认无误后,输入y,验证登录密码,系统会根据服务器发来的公钥对密码进行加密。

  • 第三步:加密后的信息回传给服务器,服务器用自己的私钥解密,如果密码正确,则用户登录成功。

  • 注意:当客户端第二次ssh连接服务端时,会要求服务器使用自身的私钥签名,如果客户端使用之前存储的公钥可以解开,则允许登陆,若无法解开,则不允许登陆。因此,当一个服务端主机的ip没有变化,但是秘钥发生变化时,将无法登录该服务端,报错提示如下:

image

解决方法为:删除客户端~/.ssh/known_hosts中对应服务器的行即可。

3.2 基于秘钥的验证

默认情况下,通过ssh客户端命令登陆远程服务器,需要提供远程系统上的帐号与密码,但为了降低密码泄露的机率和提高登陆的方便性,建议使用密钥验证方式。

3.2.1 基于秘钥验证的原理

image

验证过程如下:

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

3.2.2 基于秘钥验证的实现

  • 客户端创建秘钥

    使用ssh-keygen命令生成密钥对,ssh-keygen命令的语法格式如下:

    ssh-keygen -t rsa [-p ‘’] [-f “~/.ssh/id_rsa"]
    
    说明:
    -t:指定算法rsa、dsa,默认为rsa生成的密钥
    -P:提供旧密码
    -p:要求改变某私钥文件的密语而不重建私钥。程序将提示输入私钥文件名、原来的密语、以及两次输入新密语
    -f:指定密钥保存路径,默认为:~/.ssh/id_rsa
    -N:指定私钥密码
    -b bits:指定密钥长度。对于RSA密钥,最小要求768位,默认是2048位。DSA密钥必须恰好是1024位(FIPS 186-2 标准的要求)
    -C :指定用户邮箱
    
    #方式一:
    #使用交互式方式生成密钥对:
    [root@xuzhichao ~]# ssh-keygen -t rsa
    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:DWGjf0OqtHidk3fVoJK/wLAfN/U5HDIgPSkdi7ugUDw root@xuzhichao
    The key's randomart image is:
    +---[RSA 2048]----+
    |        +  .     |
    |    .  o o+ +    |
    |     E. .+.B  .  |
    |    . .. =+.o. o |
    |   .  ..S.* .oo..|
    |    .o.+.B.+ o+.o|
    |    ..+ *.= =  +.|
    |     .   + = o  .|
    |          . .    |
    +----[SHA256]-----+
    
    #方式二:
    #无需交互式,自动应答方式生成秘钥(扩展方式) 
    [root@iptables ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ""
    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:
    SHA256:h8vNJkIUXoovBtoOVm2aJZmmfRDfbWspqjBkrrUbgqw root@iptables
    The key's randomart image is:
    +---[RSA 2048]----+
    |   .  . .        |
    |    *o.+.        |
    |  .B.=+. o       |
    | o=.Bo  ..o      |
    |o=.+o.o.S+.      |
    |Bo ..o..o=       |
    |o=+  .. + +      |
    |oooo.  . o       |
    |E oo             |
    +----[SHA256]-----+
    
    #查看生成的秘钥文件,注意秘钥文件的权限和属主属组,必须严格遵守:
    [root@xuzhichao ~]# ll ~/.ssh/
    total 12
    -rw------- 1 root root 1679 Jul 24 22:45 id_rsa   <==私钥文件
    -rw-r--r-- 1 root root  396 Jul 24 22:45 id_rsa.pub  <==公钥文件
    -rw-r--r-- 1 root root  525 Jul 24 22:27 known_hosts
    
  • 客户端向服务端推送公钥

    把公钥文件传输至远程服务器对应用户的家目录下的.ssh/生成authorized_keys

    使用ssh-copy-id命令推送公钥,ssh-copy-id语法格式为:

    ssh-copy-id [-i [identity_file]] [user@]host
    
    说明:
    -i :指定公钥路径,不加此项,则拷贝默认路径
    [user@] :以什么用户身份进行公钥分发(root),如果不输入,表示以当前系统用 户身份分发公钥
    host :下发公钥至那台服务器, 填写远程主机IP地址
    
    #方式一:推送公钥:
    [root@xuzhichao ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.20.22
    /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
    root@192.168.20.22's password: 
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh 'root@192.168.20.22'"
    and check to make sure that only the key(s) you wanted were added.
    
    #方式二:无需交互推送公钥
    [root@xuzhichao ~]# yum install sshpass -y
    [root@xuzhichao ~]# sshpass -p123456 ssh-copy-id -i ~/.ssh/id_rsa.pub -o StrictHostKeyChecking=no root@192.168.20.71
    /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
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@192.168.20.71'"
    and check to make sure that only the key(s) you wanted were added.
    
  • 连接测试

    [root@xuzhichao ~]# ssh 192.168.20.22
    Last login: Sat Jul 24 22:28:43 2021 from 192.168.20.1
    [root@nginx02 ~]# exit
    logout
    Connection to 192.168.20.22 closed.
    
    [root@xuzhichao ~]# ssh 192.168.20.22 "hostname"
    nginx02
    
  • 以上示例为私钥不使用密码加密,当私钥使用密码加密时,每次连接远程主机都需要输入密码:

    [root@iptables ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P "123456"  <==私钥加密的密码为123456
    Generating public/private rsa key pair.
    /root/.ssh/id_rsa already exists.
    Overwrite (y/n)? y
    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:f/rVloxzlhG9Db2FgouRjM1J9Vf8pjXniaG0kzI5lN4 root@iptables
    The key's randomart image is:
    +---[RSA 2048]----+
    |        ...    ..|
    |       * o o   +o|
    |      . B o o +.=|
    |         = o + o@|
    |        S = + oO=|
    |         B E .+o=|
    |          = oo.*o|
    |           o .+. |
    |          ...    |
    +----[SHA256]-----+
    
    [root@iptables ~]# ssh-copy-id 192.168.20.22
    
    [root@iptables ~]# ssh 192.168.20.22
    Enter passphrase for key '/root/.ssh/id_rsa':    <==需要输入私钥的密码
    Last login: Sat Jul 24 23:18:07 2021 from 192.168.20.17
    [root@nginx02 ~]#
    
  • 解决以上问题的方法为验证代理

    加密私钥后,每次连接认证过的主机都要输入加密口令,此时可以考虑使用验证代理,这样口令就只需要输入一次。

    在GNOME中,代理被自动提供给root用户,否则运行命令ssh-agent bash来激活代理。

    注意:代理功能仅对当前shell有效。

    [root@iptables ~]# ssh-agent bash
    [root@iptables ~]# ssh-add
    Enter passphrase for /root/.ssh/id_rsa: 
    Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)
    [root@iptables ~]# ssh 192.168.20.22
    Last login: Sat Jul 24 23:21:20 2021 from 192.168.20.71
    [root@nginx02 ~]# 
    
  • 修改私钥保护密码的方式如下:

    #方法一:
    [root@iptables ~]# 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.
    
    #方法二:
    #其中:-P指定原始密码,-N指定新密码
    [root@iptables ~]# ssh-keygen -p -f "/root/.ssh/id_rsa" -P "654321" -N "123456"
    Your identification has been saved with the new passphrase.
    

3.2.3 实现多台主机可以互相基于key验证

  • 方式一:每台主机都生成私钥对,然后每台主机都把公钥文件传到某一台主机上,包括该主机自身,最后把这个主机上的.ssh/authorized_keys文件拷贝到其他主机上即可。

    #1.所有主机都执行下面操作:
    [root@iptables ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ""
    [root@iptables ~]# ssh-copy-id 192.168.20.17
    
    #2. 把192.168.20.17的~/.ssh/authorized_keys文件拷贝到所有主机
    [root@xuzhichao ~]# scp ~/.ssh/authorized_keys 192.168.20.22:/root/.ssh/authorized_keys
    [root@xuzhichao ~]# scp ~/.ssh/authorized_keys 192.168.20.71:/root/.ssh/authorized_keys
    
    #3.此时这三台主机就可以实现相互之间的基于key验证。
    
  • 方式二:所有主机共用一对公钥和私钥。即在一台主机上生成公钥,私钥,authorized_keys文件,然后全部拷贝到其他主机:

    #1.在192.168.20.71主机都执行下面操作:
    [root@iptables ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ""
    [root@iptables ~]# ssh-copy-id 192.168.20.71  <==上传给自己
    
    #将~/.ssh/目录下的所有内容拷贝给其他主机
    [root@iptables ~]# scp ~/.ssh/* 192.168.20.17:/root/.ssh/
    [root@iptables ~]# scp ~/.ssh/* 192.168.20.22:/root/.ssh/
    
    #3.此时这三台主机就可以实现相互之间的基于key验证。
    

3.2.4 xshell实现基于key的验证

  • Xshell-->选择工具->新建密钥生成工具

image

  • 选择加密的算法和秘钥长度,点击“下一步”:

image

  • 生成秘钥对,点击“下一步”:

image

  • 填写秘钥名称。秘钥增加密码则不建议配置

image

  • Windows会提示密码,继续即可

image

  • 点击“完成”即可:

image

  • 生成秘钥后,点击Xshell->工具->用户秘钥管理者->选择对应秘钥的属性:

image

  • 点击“公钥”,复制公钥内容或点击“保存为文件”:

image

  • 将从WIndows下复制好的公钥粘贴至跳板机~/.ssh/authorized_keys中,然后测试。

  • xshll新建会话,在“用户身份验证”的方法中选择“Public Key”,选择公钥文件,输入用户名,点击“连接”即可成功连接主机:

image

4. ssh服务端配置

4.1 ssh服务端配置文件

ssh服务端的配置文件为:/etc/ssh/sshd_config

ssh的配置文件字段意义如下:

#Port 22                      
'指定ssh服务的端口,建议修改为非常规端口'(需要关闭selinux或semanage port -a -t ssh_port_t -p tcp #PORTNUMBER,使用semanage port -l | grep ssh查看type类型。)

#AddressFamily any             
'支持ipv4/ipv6协议,any为都支持'

#ListenAddress 0.0.0.0   <==指定那个IP地址来监听服务端口port,0.0.0.0位任意端口
listenaddress  172.20.251.121   <==添加一行指定监听地址

HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
'ssh使用的非对称公钥和私钥,身份验证和数据传输加密需要'
'连接centos6优先使用RSA key'
'连接centos7优先使用EXDSA key'

SyslogFacility AUTHPRIV
#LogLevel INFO
日志类型和日志级别,日志文件/var/log/secure

#LoginGraceTime 2m   
'登录宽限时长,也就是等待输入密码时间'

#PermitRootLogin yes
'改为no,则不予许root连接登录  解决方法,用普通账户登录,然后su -root'

#StrictModes yes 
'检查/etc/ssh/下公钥私钥文件的所有者,权限等,改为no就会跳过,不检查这些属性'

#MaxAuthTries 6
'指定最大尝试连接次数,为指定值的一半'

#MaxSessions 10 
'每一个网络连接开启的会话,即克隆的会话数'

AuthorizedkeysFile         .ssh/authorized_keys
'基于key验证,公钥的存放文件'

#PubkeyAuthentication yes
'支持基于key验证'

PasswordAuthentication yes
'支持用户密码验证'

GSSAPIAuthentication yes 	
'提高连接速度可改为no'

GatewayPorts no
'是否允许远程主机连接本地的转发端口'

UseDNS yes      
'默认会进行反向解析,提高连接速度可改为no'

#AllowAgentForwarding yes
'允许代理转发'

#AllowTcpForwarding yes
'允许Tcp转发'

#MaxStartups 10:30:100
'未认证连接超过10个用户时, 限制新建连接30%的连接,最大为100个连接'

PermitEmptyPasswords no
'是否允许空口令登录'

#ClientAliveInterval 0
'每过多少秒,探测一次连接用户是否活动'

#ClientAliveCountMax 3
'最大探测次数,超过后断开,这两个参数搭配使用为最终用户连接到服务器后的超时时间(timeout)’

Banner /path/file       <==如:/etc/ssh.txt
'登录提示语句,指定一个文件路径,在文本中写入提示语,ssh连接是会显示文本内容'

'限制可登录用户的办法,在配置文件中添加如下内容'
'允许访问用户'
#AllowUsers user1 user2 user3
'拒绝访问用户'
#DenyUsers user1 user2 user3
'允许访问组'
#AllowGroups group1 group2 group3
'拒绝访问组'
#DenyGroups group1 group2 group3
'注意:黑名单和白名单同时存在一个账号,该账号不能登陆,现象为密码错误。'

4.2 ssh安全相关优化

常用的安全相关优化如下:

  • 1.建议使用非默认端口;
  • 2.禁止使用protocol version 1,协议版本有漏洞;
  • 3.限制可登录用户;
  • 4.设定空闲会话超时时长;
  • 5.利用防火墙设置ssh访问策略;
  • 6.允许特定的主机访问服务器;
  • 7.仅监听特定的IP地址 :
  • 8.基于口令认证时,使用强密码策略;
  • 9.建议使用基于密钥的认证;
  • 10.禁止使用空密码;
  • 11.禁止root用户直接登录;
  • 12.限制ssh的访问频度和并发在线数;
  • 13.经常分析日志;

相关优化配置如下:

Port 6666 # 变更SSH服务远程连接端口 
PermitRootLogin no # 禁止root用户直接远程登录 
PasswordAuthentication no # 禁止使用密码直接远程登录,可选
UseDNS no # 禁止ssh进行dns反向解析,影响ssh连接效率参数 
GSSAPIAuthentication no # 禁止GSS认证,减少连接时产生的延迟
PermitEmptyPasswords no  #不允许空口令登录
posted @ 2021-07-25 00:50  向往自由的独行者  阅读(1053)  评论(0编辑  收藏  举报