SSH

SSH

SSH - secure shell,protocol,22/tcp,安全的远程登录

SSH具体的软件实现:

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

SSH协议版本:

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

Openssh软件组成

OpenSSH相关包:

  • openssh
  • openssh-clients
  • openssh-server
centos 默认最小化安装也会安装openssh相关软件包
~]# rpm -qa "openssh*"
openssh-server-7.4p1-16.el7.x86_64
openssh-7.4p1-16.el7.x86_64
openssh-clients-7.4p1-16.el7.x86_64

相关软件包分析
~]# rpm -ql openssh-server
    /usr/lib/systemd/system/sshd.service service服务
    /usr/sbin/sshd 服务软件程序,对外提供服务
    /etc/ssh/sshd_config 服务器端配置文件

~]# rpm -ql openssh-clients <客户端工具>
    /usr/bin/ssh ssh命令
    /usr/bin/scp
    /etc/ssh/ssh_config 客户端配置文件

~]# rpm -ql openssh <包含服务器端和客户端的通用信息>

查看相关端口由哪个服务监听的命令:
~]# lsof -i :22
~]# ss -tnp  -p选项

相关工具:基于C/S结构

  • Linux Client: ssh, scp, sftp,slogin
  • Windows Client:xshell, putty, securecrt, sshsecureshellclient
  • Server: sshd

ssh公钥交换连接 <ssh为什么安全?>

首次连接时:

第一次连接远程主机时:

无论client是Windows和Linux,客户端和服务器端各有各的公钥和私钥

公钥所在目录:
 ~]#ls  /etc/ssh
ssh_host_ecdsa_key.pub centos7默认使用的加密算法:ecdsa
ssh_host_rsa_key.pub   centos6默认使用的加密算法:rsa
对公钥做hash之后,连接确认,如果hash值不一样,说明是不存在的主机。

怎么提取ssh_host_ecdsa_key.pub的hash值呢?
1、先将公钥取出来,其中ssh_host_ecdsa_key.pub默认不是完整的公钥,里面
有描述和换行符

2、ssh_host_ecdsa_key.pub此文件中的公钥信息默认是被base64编码过的
    base64 -d 还原原本的值

3、md5sum pubkey

确认连接的主机是不是你要连接的主机

第二次连接时就不再询问<--> 连接确认yes后,在本地家目录中的.ssh目录中会
生成一个known_hosts文件。第一次连接时yes后会将server端的公钥自动传给
client端。传送server端公钥的同时还会携带会话id,连接过程如上图所示。

注意: 如果一台主机被替换时,以前ssh基于以前主机私钥链接时,应该删除对应的公钥信息(/root/.ssh/known_hosts文件中)

ssh加密通信

ssh客户端

  • 客户端组件:
  • ssh, 配置文件:/etc/ssh/ssh_config
    Host PATTERN
      StrictHostKeyChecking no 首次登录不显示检查提示
      如果企业内部连接可以修改此选项自动回答yes
客户端配置文件修参数1):
企业内部是使用:这个参数一般可以需要修改
如果要批量修改此参数:脚本等等,或者自动化运维工具
    echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config
追加至文件最后也行

客户端配置文件修改参数2):
    企业内部考虑安全可能需要修改默认的22端口号
        因此客户端配置文件可能涉及修改默认端口号
        否则需要-p手动指定
  • 格式:ssh [user@]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 -t>选项可简化些许流程
    ssh -t remotehostip1 ssh -t remotehostip2 ssh remotehostip3
    只有最后一个主机无需加-t

ssh登录验证方式

1)ssh基于用户名和口令的登录验证

2)ssh基于秘钥的登录验证

基于key认证的实现

  • (1)客户端生成密钥对儿
    ssh -keygen [-t type] [-f “~/.ssh/id_**”] [-p ‘’]
      -t:指定加密算法<默认rsa>
      -f:指定生成文件路径
      -p:密钥口令

    默认为交互式:加上-f -P选项直接指定为非交互式命令啦~
    最简单 ssh -keygen直接回车,就生成了一个密钥对
    
    
  • (2)把公钥文件传输至远程服务器对应用户的家目录
    ssh-copy-id [-i [identity_file]] [user@]host

    hostip前面需要指明当前用户与host主机哪个用户连接是基于key验证
    就会将刚才生成的公钥传到连接用户的家目录的.ssh目录下,并且命名
    为authorized_keys (默认权限为600)
    
  • (3)测试

  • (4) 在SecureCRT或Xshell实现基于key验证
    在SecureCRT工具—>创建公钥—>生成Identity.pub文件转化为openssh兼容格式(适合SecureCRT,Xshell不需要转化格式),并复制到需登录主机上相应文件authorized_keys中,注意权限必须为600,在需登录的ssh主机上执行:ssh-keygen -i -f Identity.pub >> .ssh/authorized_keys

基于key认证实现时需要注意:
①~/.ssh/authorized_keys 文件权限600
②私钥必须保管妥善,添加口令,防止被盗取

当私钥添加口令时,每次登陆或者切换需要输入私钥口令,也是相当麻烦

解决办法:<一旦退出又需要重新执行验证代理>
重设或者更改私钥口令:
    ~]# ssh-keygen –p <自动会选择~/.ssh/id_rsa 文件>
验证代理(authentication agent)保密解密后的密钥
    这样口令就只需要输入一次
    在GNOME中,代理被自动提供给root用户
    否则运行ssh-agent bash
        ~]# ssh-agent bash <启用agent代理>
钥匙通过命令添加给代理
    ssh-add
        ~]# 将秘钥口令托管给agent代理

实验一

一台主机管理多台主机时:基于key验证

实现:在管理主机上生成秘钥对,然后将生产的公钥分发至管理的主机

  • ①:~]#ssh-keygen -f “/root/.ssh/id_rsa” -P ‘’
  • ②:.ssh]#ssh-copy-id root@192.168.66.17
  • ③:.ssh]#ssh-copy-id root@192.168.66.27
  • ④:.ssh]#ssh-copy-id root@192.168.66.37
  • 此时当前主机可以实现基于key验证登录17、27、37这三台主机

脚本实现:expect ==> expect最常用的实现

#!/bin/bash

ssh-keygen -f "/root/.ssh/id_rsa" -P '' &> /dev/null
rpm -q expect &> /dev/null || yum install expect -y -q
pass=*****
user=root
while read ip ;do
expect <<EOF
set timeout 20
spawn ssh-copy-id $user@$ip 
expect {
	"yes/no" { send "yes\n";exp_continue }
	"password" { send "$pass\n" } 
}
expect eof
EOF
done < /data/hostlist.txt
# /data/hostlist.txt 为需要管理的主机列表
一个集群三五台主机实现两两互联均基于key验证

实现:在其中一台主机上生成秘钥对和authorized_keys,然后拷贝.ssh目录

  • ①:~]#ssh-keygen -f ‘/root/.ssh/id_rsa’ -P ‘’
  • ②:~]#ssh-copy-id root@127.0.0.1 生成authorized_keys文件
  • ③: ~]#scp -r /root/.ssh 192.168.66.17:/root/
使用同一套公钥私钥。

实验二

在SecureCRT或Xshell实现基于key验证

实现windows使用xshell 连接Linux是基于key验证的

  • ①:xshell生成自己的秘钥对
  • ②:秘钥对生成完成之后:将公钥导入到对应主机对应用户家目录.ssh/authorized_keys文件中
  • ③:xshell中身份验证选择基于key验证连接主机

SCP命令

由前面可知scp命令来自于openssh-clients包
~]#rpm -qf /usr/bin/scp
openssh-clients....

scp 的基本语法:

  • scp [opt] SRC DEST
scp  [opt]  复制源  目标
    ①可以实现将远程主机文件复制至本地主机
    ②可以实现将本地主机文件复制至远程主机
    ③可以实现将远程主机文件复制至另一远程主机

scp命令走的是ssh协议

若主机之间实现了基于key验证,则可以直接复制

scp命令的选项:

  • -C 压缩数据流
  • -r 递归复制 <用于目录>
  • -p 保持原文件的属性信息
  • -q 静默模式
  • -P PORT 指明remote host的监听的端口
scp 命令的局限性:  
  不能使用scp命令实现主机与备份主机的同步 
    eg:host1   host2主机为host1主机的文件备份主机
    因为scp命令默认是直接复制整个目录或整个目录下所有文件
        ①scp不会只复制host1主机目录新增文件;
        ②当host1主机文件删除时:host2主机不会删除对应文件

rsync命令

基于ssh和rsh服务实现高效率的远程系统之间复制文件

使用安全的shell连接做为传输方式

  • rsync -av /etc server1:/tmp 复制目录和目录下文件
  • rsync -av /etc/ server1:/tmp 只复制目录下文件
  • 注意: 源 带/ 和 不带/ 的区别

比scp更快,只复制不同的文件

常用选项:

  • -n 模拟复制过程
  • -v 显示详细过程
  • -r 递归复制目录树
  • -p 保留权限
  • -t 保留时间戳
  • -g 保留组信息
  • -o 保留所有者信息
  • -l 将软链接文件本身进行复制(默认)
  • -L 将软链接文件指向的文件复制
  • -a 存档,相当于–rlptgoD,但不保留ACL(-A)和SELinux属性(-X)
rsync:可以实现文件备份同步;经常用来数据同步 
    但是局限是rsync同步时是以文件为单位,不能只复制文件变化的部分

目前结合计划任务可以实现数据同步,但是并不能实现实时同步
  --delete  同步时一般加上此选项,可以实现源有被删除的文件,同步主机也
删除对应文件,实现数据同步选项。

实时同步:以服务方式运行rsync

sftp命令与sshfs

sftp命令是交互式文件传输工具

  • 用法和传统的ftp工具相似
  • 利用ssh服务实现安全的文件上传和下载
  • 使用ls cd mkdir rmdir pwd get put等指令,可用?或help获取帮助信息

sshfs命令 <epel源> 可以利用ssh协议将远程主机的某个目录挂载至本机

  • 示例:sshfs 192.168.66.66:/data /mnt
  • 取消挂载:umount /mnt

轻量级自动化运维工具

pssh

pssh:基于python编写,可在多台服务器上执行命令的工具,也可实现文件复制,提供了基于ssh和scp的多个并行工具

项目:http://code.google.com/p/parallel-ssh/

pdsh

pdsh:Parallel remote shell program,是一个多线程远程shell客户端,可以并行执行多个远程主机上的命令。 pdsh可以使用几种不同的远程shell服务,包括标准的“rsh”,Kerberos IV和ssh

项目: https://pdsh.googlecode.com/

mussh

mussh:Multihost SSH wrapper,是一个shell脚本,允许您使用一个命令在
多个主机上通过ssh执行命令或脚本。 mussh可使用ssh-agent和RSA / DSA密
钥,以减少输入密码

项目:http://www.sourceforge.net/projects/mussh

说明:以上工具都包含在EPEL源中

以上工具可以实现数量不多的几十台主机的自动运维管理。
以pssh为例:
    若经常在多个主机之间做相同的操作时:比如同时安装某个相同的服务、修改
    某服务的配置文件等等
pssh:基于ssh和scp实现并行处理的工具:
~]# rpm -qi pssh
....
 o ssh : pssh
 o scp : pscp
 o nuke : pnuke
 o rsync : prsync
 o slurp : pslurp

~]# rpm -ql pssh
 /usr/bin/pnuke
/usr/bin/prsync
/usr/bin/pscp.pssh
/usr/bin/pslurp
/usr/bin/pssh

/usr/bin/pssh - pssh工具

pssh的使用的前提已经实现基于key验证,否则会报错,
因为pssh默认是基于key验证

-A 基于口令验证  --> 但是只有一次输入口令的机会,要求只有管理的主机密码
一致<而且要求当前主机的.ssh的主机有known_hosts 内容含有管理的主机>
    否则不会给你输入yes的机会

pssh批量管理建议还是基于key验证

pssh命令选项:

  • –version:查看版本
  • -h:主机文件列表,内容格式”[user@]host[:port]”
  • -H:主机字符串,内容格式”[user@]host[:port]”
  • -A:手动输入密码模式
  • -i:每个服务器内部处理信息输出
  • -l:登录使用的用户名
  • -p:并发的线程数<可选>
  • -o:输出的文件目录<可选>
  • -e:错误输出文件<可选>
  • -t:TIMEOUT 超时时间设置,0无限制<可选>
  • -O:SSH的选项
  • -P:打印出服务器返回信息
  • -v:详细模式
~]# pssh -h /data/hostlist.txt -i 'sed -i "s/SELINUX=enforcing/
SELINUX=disabled/" /etc/selinux/config'
    关闭/data/hostlist.txt 列表主机的selinux;重启生效

pscp.pssh工具

  • pscp.pssh功能是将本地文件批量复制到远程主机

pscp-pssh选项

  • -v 显示复制过程
  • -r 递归复制目录
比如:脚本部署至多个主机:pscp.pssh
    ~]# pscp.pssh  -h hosts  /data/1.sh  /data/
        将本机/data/1.sh  批量部署至hosts列表主机的/data目录

pslurp工具

  • pslurp功能是将远程主机的文件批量复制到本地

pslurp选项

  • -L 指定从远程主机下载到本机的存储的目录,local是下载到本地后的名称
  • -r 递归复制目录
批量下载hosts文件中的列表主机的passwd文件至/data下,并更名为user
    pslurp -h hosts /data /etc/passwd user
抓取至的主机下为避免重名会创建以ip地址为名称的目录,然后将文件存放。
    data]# pslurp -h hosts -L /data/ /etc/fstab user
[root@centos7-17 data]# tree 
.
├── 192.168.38.16
│   └── user
├── 192.168.38.17
│   └── user
├── 192.168.38.27
│   └── user
├── 192.168.38.37
│   └── user
├── 1.sh
└── hosts

端口转发

SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是,SSH 还能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务。这一过程也被叫做“隧道”(tunneling),这是因为SSH 为其他 TCP 链接提供了一个安全的通道来进行传输而得名。

使用场景:在生产实际中一般企业外部进入至企业内部是不允许的,因为安全策略
现在有需求:互联网的主机也能访问企业内部的主机
    使用ssh协议可以开放特定的主机给出差在外的互联网主机
    或者使用ssh协议将不安全的协议封装

第一种场景:

本地端口转发

  • -L localport:remotehost:remotehostport sshserver

选项:

  • -f 后台启用
  • -N 不打开远程shell,处于等待状态
  • -g 启用网关功能

互联网主机开启端口,本地端口转发

实现:
    1)配置主机C
        ①~]#iptables -A INPUT -s 192.168.38.27 -j REJECT
            使用iptables禁止A主机直接连接
        ②~]# ss -tnl <默认25端口只有本机能连接>
        ...  127.0.0.1:25  ... 修改监听的地址范围
   未修改时,该主机不能连接25端口
   ~]# telnet 192.168.38.17 25
    Trying 192.168.38.17...
    telnet: connect to address 192.168.38.17: Connection refused
         
        vim /etc/postfix/main.cf
            inet_interfaces = localhost  
            将localhost改为all
        重启服务,生效

    2)主机C上执行:
    ~]# ssh -L 9527:192.168.38.17:25 192.168.38.37 -fN
        开启本机9527端口相当于去连接17的25端口,中间借助37主机
         -fN 不加默认会连接37主机上去
    ~]# telnet 127.0.0.1 9527
        连接本机的9527端口相当于连接17的25端口

在主机C(17)以为是跳板机主机B(37)在连接自己的25端口

此实现的前提:默认互联网可以连接本地内部的22端口;但是一般是22端口不会开
启,因此这种连接方式比较危险

第二种场景:

远程转发:

  • -R sshserverport:remotehost:remotehostport sshserver

远程端口转发

企业内部一般会拒绝互联网主机连接企业内部,但是企业内部主机可以允许连接
至互联网,给出差在外的同事开启ssh隧道,然后他可以直接通过互联网连接至企
业内部,不需要更改任何的防火墙策略和开启VPN。
    外网的同事只能连接开启的那一台主机

实现:
    ①在主机B上执行 
    ~]# ssh -R 6666:192.168.38.17:25 192.168.38.27 -fN
        此时由企业内部主机建立隧道,在A主机上会自动打开6666端口
    
    ②此时A主机连接自己的端口:
    ~]# telnet 127.0.0.1 6666
        可以连接

在主机C上也是以为跳板机主机B在连接自己

第三种场景:

动态端口转发:<防止出去的场景>

当用firefox访问internet时,本机的1080端口做为代理服务器,firefox的访问请求被转发到sshserver上,由sshserver替之访问internet

  • ssh -D 1080 root@sshserver -fNg
 ssh -D 1080 root@sshserver -fNg
    当在本地访问1080端口时请求就会发送给远程的跳板机,通过跳板机
    再去访问对应主机  <1080并不是固定端口,本机未使用端口均可>
  • 在本机浏览器配置代理,通过此浏览访问时,将请求发给本机的对应端口

ssh服务器

ssh服务器

  • 服务器端:sshd, 配置文件: /etc/ssh/sshd_config
  • 建议配置文件修改时先做备份
  • 配置文件帮助:man sshd_config

ssh服务器常用参数:

  • Port
端口:放在互联网的主机ssh的默认22端口是需要修改的
  • ListenAddress ip
默认ssh监听在所有ip,可以修改指定监听的ip
ListenAddress 0.0.0.0 <所有ip>
  • LoginGraceTime 2m
~]# ssh 192.168.38.37
root@192.168.38.37's password: 
    用户建立连接,但迟迟不输入密码连接

2min不连接就断开,免得浪费资源
  • PermitRootLogin yes
PermitRootLogin:Ubuntu默认root不能直接使用xshell连接,因为此选项
PermitRootLogin prohlbit-password 禁止密码连接<但是可以基于秘钥连>
  • StrictModes yes 检查.ssh/文件的所有者,权限等
StrictModes:要求.ssh/目录对应文件权限、所有者 严格检查
  • MaxAuthTries 6
MaxAuthTries:口令验证尝试次数为:6/2=3
  • MaxSessions 10 同一个连接最大会话
MaxSessions:一个ssh连接可开启的会话数
    即xshell的复制SSH渠道可以复制10个
  • PubkeyAuthentication yes
PubkeyAuthentication:基于key验证
  • PermitEmptyPasswords no
  • PasswordAuthentication yes
PasswordAuthentication:是否支持密码验证登录
  • GatewayPorts no
  • ClientAliveInterval 单位:秒
  • ClientAliveCountMax 默认3
  • UseDNS yes
  • GSSAPIAuthentication yes 提高速度可改为no
UseDNS:将ip地址反向解析为域名
GSSAPIAuthentication:API验证平时一般不用
  • MaxStartups 未认证连接最大值,默认值10
未认证的连接如下:
~]# ssh 192.168.38.37
root@192.168.38.37's password:
    如果未认证的连接在10个以内不做任何处理,如果大于10个以30%的速率拒绝
    连接,达到60个时,全部拒绝
限定并发连接数
  • Banner /path/file
Banner:登录的提示信息
  • 限制可登录用户的办法:
    AllowUsers user1 user2 user3
    DenyUsers
    AllowGroups
    DenyGroups

ssh服务的最佳实践

  • 建议使用非默认端口 <尤其发布至互联网的主机,默认端口一定要修改>
  • 禁止使用protocol version 1 <版本1有漏洞>
  • 限制可登录用户
  • 设定空闲会话超时时长
  • 利用防火墙设置ssh访问策略
  • 仅监听特定的IP地址
  • 基于口令认证时,使用强密码策略
    tr -dc A-Za-z0-9_ < /dev/urandom | head -c 12| xargs
    openssl random -base64 6
  • 使用基于密钥的认证
  • 禁止使用空密码
  • 禁止root用户直接登录
  • 限制ssh的访问频度和并发在线数
  • 经常分析日志

错误登录访问日志

  • /var/log/btmp
~]# file /var/log/btmp
/var/log/btmp: DBase 3 index file 数据库文件
    不能使用文本查看工具查看,需要使用 lastb 命令查看

~]#lastb 
root ssh:notty 192.168.38.27    Wed Aug  7 06:29 - 06:29  (00:00) 
root ssh:notty 192.168.38.27    Wed Aug  7 06:29 - 06:29  (00:00)

~]# lastb -f /var/log/btmp
        lastb -f file 
   定期分析此文件/var/log/btmp:如果错误连接数在1天以内超过50次,认为
不正常访问,列入黑名单。

计划两个脚本完成:
    ①每天将/var/log/btmp中信息备份至一个目录,然后将此文件清零
        ~]# cp /var/log/btmp /data/btmp`date -d "yesterday" +%F`
        文件清零 
            > /var/log/btmp (bash)
            所有shell:cat /dev/null > /var/log/btmp
        ~]# cat /dev/null > /var/log/btmp
    ②然后对取出的文件进行处理 (错误次数>=50) 拒绝访问
    lastb -f  filename| awk '{ip[$3]++}END{for(i in ip){if(ip[i]\
    >=50){system("iptables -A INPUT -s" i "-j REJECT")}}}'

相关命令如上,脚本略。
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐