一. 回顾

1.1 ssh

ssh

secure shell

  • 远程登录连接,控制主机

  • 数据的传输都是加密的

  • 基于非对称加密技术

1.2 加密技术

加密技术

对称加密

  • 双方共同拥有一把钥匙,其中一方拿着加密,另外一方就拿着解密

  • 弊端:这个公钥的钥匙很容易被有心人获取

非对称加密

  • 使用公钥对进行加解密

  • 生成一对钥匙,其中一方作为私钥,另一方就是公钥

  • 私钥是只有自己知道,私钥保存在本地

  • 公钥是给需要通信的人,公钥可以给其他人

  • 使用公钥加密,私钥解密,一般用在数据加密传输
    (A、B 2个人,B给A用加密的方式传输数据,私钥在A手里,B用A的公钥对数据加密)

  • 使用私钥加密,公钥解密,一般用于认证
    (A向B发送数据,B用于确认是不是A发送的数据,客户端A用A的私钥对数据进行加密,服务端B拿A的公钥进行解密。只管认证,不管加密性)

1.3 ssh登录

ssh登录

登录方式

  • 密码登录
    流程
    1、客户端发送登录请求
    2、服务器发送机器的公钥发送给客户端
    3、客户端用服务器的公钥对密码进行加密,发送给服务端
    4、服务器收到密文之后,用私钥进行解密,与/etc/shadow进行验证
    5、返回验证结果

  • 密钥登录,公钥认证
    1、客户端生成公钥对
    2、将客户端的用户公钥发送给服务器,保存在目标用户~/.ssh/authorized_keys
    3、客户端发送请求,服务器返回1个随机字符串
    4、客户端收到随机字符串之后,用自己的私钥加密,发送给服务器
    5、服务器收到密文之后,用客户端的公钥进行解密,拿到随机字符串与生成的字符串比较。返回认证结果(随机字符串其他人拿到了就拿到了,没有任何关系,因为A的公钥很多人都可以有)

  • 弊端

    • 第三方攻击
    • A无法判定收到的这个公钥是不是B的
    • 为了解决这个问题
      • 第一次登录的时候会进行人为确认
      • 确认了之后,将B机器主机公钥存放在~/.ssh/known_hosts,以后每次登录都会进行对比 (如果系统重装后,登录不上,提示known_hosts……,将known_hosts删掉)

公钥认证

1、使用命令生成公钥对

​ ssh-keygen

​ -t 选项 指定生成的加密算法

​ 默认是rsa算法加密,过程中一直敲回车就可以了

2、客户端将公钥发送给服务器

​ 保存在目标用户的~/.ssh/authorized_keys

3、检测权限

​ authorized_keys 600权限

​ .ssh 以及家目录都给755以下权限

或者 允许密码验证登录时(前提条件) # ssh-copy-id wy@192.168.0.39 -p 2233 把公钥发送过去

[root@cPen_python ~]# ssh-copy-id wy@192.168.0.39 -p 2233 # 注:需要可以支持密码登录

1.4 ssh远程操作工具

ssh远程操作工具

  • ssh

    • 远程执行命令,远程登录
    • 登录方式
      • ssh 服务器ip地址
        • 使用当前用户和默认端口登录
        • 使用客户端的当前用户名,登录到远端服务器的同名用户下,默认端口22
          (没有同名用户,登录失败)
      • ssh 用户名@服务器ip地址
        • 登录到远端服务器的指定用户下,使用默认端口22登录
      • ssh 服务器地址 -l 用户名 -p 端口号
        • 指定用户名和端口去登录
      • ssh -o 接一些配置选项 服务器的ip地址
        #无序输入yes,自动保存hostkey
        ssh -o StrictHostKeyChecking=no 192.168.0.132 -p 223
      • ssh -i /tmp/id_rsa 指定私钥认证文件
        默认情况在~/.ssh/这下面找私钥
      • ssh -vvv
        打印登录过程的详细信息

1.5 服务配置

服务配置

  • 服务安装包

    • oepnssh

      [root@cPen_python ~]# which ssh
      /usr/bin/ssh
      [root@cPen_python ~]# rpm -qf /usr/bin/ssh
      openssh-clients-7.4p1-21.el7.x86_64
  • 配置文件

    • /etc/ssh/sshd_config 服务端配置文件
    • /etc/ssh/ssh_config 客户端配置
  • 主程序
    服务端 /usr/sbin/sshd
    客户端 /usr/bin/ssh

  • 重新加载配置
    重启服务 service sshd restart/reload
    kill -1 sshd的pid
    kill -HUP sshd的pid号

1.6 查看ssh服务启动情况

查看ssh服务启动情况

1、ps -aux/-ef

2、pidof sshd

3、netstat -autpln 所有接口(a)的udp tcp连接,显示出所有程序(p) 监听状态(l) n数字显示端口号

​ # 注:查看网络连接状态

​ # ps -eo pid,uid,comm|grep sshd # 注:-eo查看特定字段信息

4、lsof -i:22 打印出程序所需要的文件

1
2
3
4
5
6
7
8
9
10
11
[root@localhost ~]# ps aux |grep sshd
root 1066 0.0 0.1 112924 4316 ? Ss 09:41 0:00 /usr/sbin/sshd -D
root 1608 0.0 0.1 158928 5608 ? Ss 09:43 0:00 sshd: root@pts/0
root 9546 0.0 0.0 112824 980 pts/0 S+ 11:26 0:00 grep --color=auto sshd
[root@localhost ~]# ps -ef |grep sshd
root 1066 1 0 09:41 ? 00:00:00 /usr/sbin/sshd -D
root 1608 1066 0 09:43 ? 00:00:00 sshd: root@pts/0
root 9550 1612 0 11:26 pts/0 00:00:00 grep --color=auto sshd
[root@localhost ~]# ps -eo pid,uid,comm|grep sshd # 注:-eo查看特定字段信息
1066 0 sshd
1608 0 sshd

1.7 ssh-agent

ssh-agent

​ 管理密钥

​ 在你自己的机器上开启这个服务

​ 配置: xshell–> 主机属性–》ssh --》勾选 使用xagent进行身份验证 ;勾选 使用代理转发

#注:自己的机器是Windows,在Windows上开启ssh-agent服务,现在有A、B 2台机器,A、B两台机器都有Windows的公钥,这种情况开启ssh-agent(xshell里面开启),A登录B时默认情况会拿windows的公钥进行加密,B机器用Windows的私钥进行解密 必须在xshell里进行操作,这都是xshell的行为


二. 跳板机

#注:跳板机给办公人员用的 跳板机/堡垒机 为了保护系统的安全

#注:使用ssh-agent 访问跳板机和想要访问的主机

#注:使用场景 阿里的业务 本来有10万台主机(在局域网里面,没有外网,外部不能访问),我在家里,十万台机器捞出一台,这1台主机可以访问外网(跳板机/堡垒机),这1台跳板机的配置尤其重要

开启ssh-agent,把自己主机的公钥添加到目标主机和堡垒机下 (目标主机的权限和堡垒机的权限)

#注:连到A上,从A跳到B上,B不一定有当前主机的公私钥

#跳板机 安全加固:

不能使用root直接登录,使用sudo赋予相应权限

不能使用默认端口登录

不能使用密码登录,都使用公钥登录

添加防火墙配置

总结:

#跳板机

#安全加固

​ 1、不能使用密码登录

​ 2、不能使用root登录

​ 3、修改默认端口

​ 4、添加防火墙配置

​ 5、使用跳板机登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
示例1:查看路由 ip r
--------------------------------------------------------------------------------------------
[root@cPen_python ~]# ip r # 注:查看路由
default via 192.168.0.1 dev ens33 proto dhcp metric 100
192.168.0.0/24 dev ens33 proto kernel scope link src 192.168.0.32 metric 100
[root@cPen_python ~]# ip r delete default via 192.168.0.1 # 注:删除网关
[root@cPen_python ~]# ip r
192.168.0.0/24 dev ens33 proto kernel scope link src 192.168.0.32 metric 100
[root@cPen_python ~]# ping www.baidu.com # 注:删除后ping不通外网
connect: 网络不可达
[root@cPen_python ~]# ping 8.8.8.8
connect: 网络不可达
[root@cPen_python ~]# ip r add default via 192.168.0.1 # 注:还原
============================================================================================

示例2:A机器登录到B机器(简化登录) vim .ssh/config
#以后会遇到很多机器,ip地址是记不住的
--------------------------------------------------------------------------------------------
#A机器登录到B机器,操作前需要先把A机器公钥放到B机器上 进行授权
#不修改全全局配置,只修改个人配置:在用户家目录下创建.隐藏文件
#在客户端上配置(配到自己的主机上)
#注:意思是将机器root@192.168.0.31 -p 2233 取个别名叫B
#ForwardAgent yes # 注:转发 开启
#StrictHostKeyChecking no # 注:不需要输入yes 直接把key保存在known_hosts里面
#ServerAliveInterval 60 # 注:存活状态,检测服务存活状态
#IdentityFile ~/.ssh/id_rsa # 注:指定认证私钥
#示例如下
[root@cPen_python ~]# vim .ssh/config
###############################################
ForwardAgent yes
StrictHostKeyChecking no
ServerAliveInterval 60
IdentityFile ~/.ssh/id_rsa
###############################################
Host B
HostName 192.168.0.31
User cPen
Port 2233
[root@cPen_python .ssh]# chmod 600 config # 注:授予权限 不执行这条语句 可能会报错
[root@cPen_python .ssh]# ssh B
Last login: Mon Nov 23 15:05:16 2020 from 192.168.0.32 # 注:登录成功
[root@cPen_centos8 ~]#
#注:即简化 # ssh 192.168.0.31 -l root -p 2233 操作 (比如登录到ftp服务器 ssh ftp)
============================================================================================

示例3:查看端口连接状态 (客户机想访问服务器的时候使用 客户机上telnet) telnet 192.168.0.31 2233
#注:这个命令只能测tcp的 udp的测不了,但是大部分服务都是tcp的
#查看端口是否可以访问(即服务是否可达) telnet 192.168.0.31 2233
--------------------------------------------------------------------------------------------
#ping命令 是查看2台机器网络是否连通
#查看服务是否可达使用 telnet命令
#示例:查看端口是否可达(服务是否可达)
[root@cPen_python .ssh]# yum install telnet -y
[root@cPen_python .ssh]# telnet 192.168.0.31 2233
Trying 192.168.0.31...
Connected to 192.168.0.31. # 注:服务可达
Escape character is '^]'.
SSH-2.0-OpenSSH_8.0
============================================================================================

示例4:提示主机不被信任 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
--------------------------------------------------------------------------------------------
#注:提示WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
将~/.ssh/known_hosts 删掉
============================================================================================

示例5:永久修改主机名 hostnamectl set-hostname "A"
--------------------------------------------------------------------------------------------
#方法1
[root@cPen_python .ssh]# hostnamectl set-hostname "A"
#注:其实是修改 /etc/hostname
[root@A ~]# less /etc/hostname
#方法2
#或者直接修改 /etc/hostname
#临时修改主机名
[root@B ~]# hostname cp
============================================================================================

示例6:查看进程数 pstree -p
--------------------------------------------------------------------------------------------
#注:看程序树状结构 pstree -p
[root@cPen_python .ssh]# pstree -p |grep sshd
|-sshd(1065)-+-sshd(3782)---bash(3784)
| |-sshd(3980)---bash(3982)-+-grep(4318)
| |-sshd(4059)---bash(4061)
| `-sshd(4288)---bash(4290)
#注:前面是父程序,后面是父程序创造出来的子程序,子程序分配新的bash环境,bash环境在操作命令grep
#注:父进程创造出子进程,子进程有创造出一个子进程,子进程创造出一个新的bash环境
#-------------------------------------------------------------------------------------------
#注:连接到B机器后bash环境多了一个ssh子进程去处理B机器
[root@a ~]# ssh B
Last login: Mon Nov 23 15:52:16 2020 from 192.168.0.32
[root@a .ssh]# pstree -p |grep sshd
|-sshd(1065)-+-sshd(3782)---bash(3784)
| |-sshd(3980)---bash(3982)-+-grep(4325)
| |-sshd(4059)---bash(4061)---ssh(4323)
| `-sshd(4288)---bash(4290)
============================================================================================

示例7:修改客户端配置 ~/.ssh/config
#配置文件:~/.ssh/config
#工作中使用跳板机代理登录 (客户端的配置,方便开发配置)
--------------------------------------------------------------------------------------------
#注:假设现在有A、B、C三台机器,B是跳板机,假设A C不通,A通B,B通C,B通D,B通E…………
#注:B机器当做跳板机,A是自己的本地机,A机器做代理,B机器自动做转发
#注:在本地机A机器中操作
[root@a ~]# vim ~/.ssh/config
###############################################
ForwardAgent yes
StrictHostKeyChecking no
ServerAliveInterval 60
IdentityFile ~/.ssh/id_rsa
###############################################
Host B
HostName 192.168.0.31
User sanchuang
Port 2233

Host 192.168.0.54
User sanchuang
Port 2233
ProxyCommand ssh 192.168.0.31 -W %h:%p -l sanchuang -p 2233
#注:ProxyCommand表示 A通过跳板机(192.168.0.31)B登录到
#-------------------------------------------------------------------------------------------
Host * /ftp* /10.* 以10网段开头的ip地址 ssh 10.0.0.1 跳到这个配置执行
User sanchuang
Port 2233
ProxyCommand ssh B nc %h %p -w 10 2>/dev/null
#注:上课时冲突 前面写Host *与ssh B冲突
============================================================================================

示例8:远程执行命令 ssh B
--------------------------------------------------------------------------------------------
#不登录B机器,执行B机器上的命令 (一般用于脚本)
[root@a ~]# ssh B ifconfig # 注:登录到B执行 ifconfig命令
[root@a ~]# ssh B ip a # 注:登录到B执行 查看ip地址 命令 ;命令的返回是B机器给的
[root@a ~]# ssh B "/usr/sbin/ip a" # 注:脚本里建议使用命令的绝对路径
============================================================================================

示例9:远程传输 scp (前提ssh可以连接)
--------------------------------------------------------------------------------------------
#注:传输文件
[root@a ~]# touch ahost
[root@a ~]# scp ahost B:/tmp # 注:将A机器 当前路径ahost文件cp到B机器下的/tmp路径下
ahost 100% 0 0.0KB/s 00:00
[root@a ~]# scp B:/tmp/bhost ./ # 注:将B机器 /tmp/bhost文件cp到当前路径
bhost 100% 0 0.0KB/s 00:00
[root@a ~]# scp B:tmp/testhost ./ # 注:将B机器 家目录下 tmp/testhost文件cp到当前路径
#注:传输目录
[root@a ~]# scp -r adir B: # 注:将A机器当前路径下 adir文件夹 cp到B机器家目录下
[root@a ~]# scp -r adir B:bdir # 注:复制文件夹并改名
[root@a ~]# scp -r adir B:bdir/ # 注:和上面的没有区别
============================================================================================

示例10:sftp传输文件 (前提ssh可以连接)
--------------------------------------------------------------------------------------------
#注:ftp文件传输
#注:sftp 传输文件 本地和异地传输文件
#注:格式 sftp 用户名@主机名
[sanchuang@a ~]$ sftp B
Connected to B.
sftp> ls # 注:显示远程目录列表
2q aa adir bb bdir testdir testdir2 testhost
sftp> get bdir
Fetching /home/sanchuang/bdir/ to bdir
Cannot download non-regular file: /home/sanchuang/bdir/
sftp> mget bdir
Fetching /home/sanchuang/bdir/ to bdir
Cannot download non-regular file: /home/sanchuang/bdir/
sftp> get 2q # 注:get 远程路径 下载文件
Fetching /home/sanchuang/2q to 2q
/home/sanchuang/2q 100% 226 107.5KB/s 00:00
sftp> exit
============================================================================================

示例11:pssh pscp命令 (前提ssh可以连接)
--------------------------------------------------------------------------------------------
#批量处理
pssh
-h 指定主机文件列表,内容格式”[user@]host[:Port]”
-i 指定每个服务器的处理信息
[root@a ~]# yum install pssh -y # 注:没有的话需要安装epel源
[root@a ~]# cat ip.txt
192.168.0.31:2233
192.168.0.54:22
[root@a ~]# pssh -h ip.txt -i "/usr/sbin/ip a"
[1] 17:18:13 [FAILURE] 192.168.0.54:22 Exited with error code 255、
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
…… # 注:需要保证ssh能不能过去
[2] 17:18:13 [SUCCESS] 192.168.0.31:2233 # 注:返回SUCCESS表示执行成功
……
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
……
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen
……
#-------------------------------------------------------------------------------------------
#ip.txt里面可以这样写
[root@a ~]# vim ip.txt
sanchuang@192.168.0.31:2233
sanchuang@192.168.0.54:2233
============================================================================================

示例12:pscp.pssh 批量传输文件 (前提ssh可以连接)
--------------------------------------------------------------------------------------------
[root@a ~]# pscp.pssh -h ip.txt pscptest /tmp
# 注:把当前目录下的pscptest文件传送到目标主机的/tmp目录下
[root@a ~]# vim ip.txt
sanchuang@192.168.0.31:2233
sanchuang@192.168.0.54:2233
[root@a ~]# pscp.pssh -h ip.txt pscptest /tmp
[1] 17:41:31 [FAILURE] sanchuang@192.168.0.54:2233 Exited with error code 1
[2] 17:41:31 [SUCCESS] sanchuang@192.168.0.31:2233
============================================================================================

示例13:fping 批量ping(前提ssh可以连接)
--------------------------------------------------------------------------------------------
#注:批量ping 使用fping命令
[root@a ~]# yum install fping -y
[root@a ~]# fping -g 192.168.0.1/24 # 注:-g 根据网段去ping
192.168.0.1 is alive
……
192.168.0.254 is unreachable
[root@a ~]# fping -f ip.txt # 注:-f根据文件指定ip去ping
192.168.0.31 is alive
192.168.0.54 is alive
[root@a ~]# vim ip.txt
192.168.0.31
192.168.0.54

三. ssh服务补充

3.1 ssh

ssh --> secure shell

作用:远程登录和操作远程的服务器 --> 信息加密 --> 非常安全的远程登录协议

#注:远程登录远程操控 省成本

ssh协议 属于应用层的协议

Linux:openssh --> centos7/8自带

Windows 没有ssh协议

3.2 命令

命令:

​ ssh

​ scp # 注:远程copy

​ sftp

​ ssh-keygen

​ ssh-copy-id

3.3 登录方式

登录方式:

​ Xshell # 注:不开源

​ putty # 注:开源

​ secureCRT # 注:开源

  1. 用户名和密码

​ /etc/passwd # 注:放用户名

​ /etc/shadow # 注:放密码

  1. 密钥

​ 公钥和私钥

​ public key --> 公开 # 注:给别人

​ private key # 注:自己所有

3.4 安全加固措施

安全加固措施:

  1. 修改端口号 22

    ​ nmap # 注:端口扫描

    ​ nc # 注:端口扫描

    1. 禁用root

      su # 注:su 切换到root

  2. 密码复杂性

  3. 启用密钥 # 注:禁止密码认证

  4. 打补丁 或者 安装最新版本的ssh软件

  5. iptables防火墙

#注:免密通道(密钥登录)

3.5 免密通道

免密通道:

​ 单向信任 # 注:把密钥给其他主机

​ 双向信任 # 注:双方互给公钥

#注:一般用root用户,为了安全起见用普通用户

3.6 ansible

ansible:自动化运维的工具:批量管理和操作

#注:ansible批量管理 批量部署的软件;底层用的ssh协议,推荐建立免密通道

#注:ansible软件 用Python写的

3.7 日志文件:/var/log/secure

1
2
3
4
5
6
7
8
9
10
日志文件:/var/log/secure
[root@cPen_centos8 ssh]# vim /etc/ssh/sshd_config
# Logging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV # 注:日志类型 认证类型 AUTHPRIV 设置
#LogLevel INFO

日志文件:
/var/log/secure
[sanchuang@cPen_centos8 ~]$ ps aux|grep rsyslog # 注:外包日志的进程
1
2
3
4
5
ssh将自己的日志功能外包给rsyslog服务去帮它记录日志

[sanchuang@cPen_centos8 ~]$ vim /etc/rsyslog.conf
# The authpriv file has restricted access.
authpriv.* /var/log/secure

3.8 ssh服务登录不了,如何排除?

ssh服务登录不了,如何排除?

  1. 检测网络是否通畅

    ping

  2. 检测ssh服务是否启动,检查端口,selinux

  3. ssh的配置:是否禁用root,是否禁用密码认证

  4. 检查防火墙iptables

    ​ service firewalled stop

  5. 黑白名单 # 注:centos6、7里面用,8里面没有

3.9 ssh免密通道

ssh免密通道

  1. 生成密钥对

    ​ ssh-keygen

    ​ ssh-keygen -t ecdsa

  2. 上传公钥

    ​ ssh-copy-id -i id_ecdsa.pub root@192.168.0.35

    ​ ssh-copy-id -p 2299 -i id_ecdsa.pub root@192.168.0.35

  3. 远程连接

    ​ ssh -p ‘2299’ ‘root@192.168.0.39’

1
2
3
4
5
6
免密通道的建立步骤:
[root@localhost .ssh]# ssh-keygen -t ecdsa
[root@localhost .ssh]# ssh-copy-id -p 2299 -i id_ecdsa.pub root@192.168.0.39
[root@localhost .ssh]# ssh -p '2299' 'root@192.168.0.39'

known_hosts:存放我们曾经ssh连接过的机器的公钥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
scp	就是在2台机器之间底层使用ssh协议来拷贝文件或者文件夹
[root@cPen_centos8 ssh]# ssh root@192.168.0.24 # 注:远程登录
[root@cPen_centos8 ssh]# ssh root@192.168.0.24 df -Th # 注:远程执行命令
[root@cPen_python ssh]# scp echo.sh root@192.168.0.35:/root # 注:传文件 (源文件 远程)
[root@cPen_python ssh]# scp -r /boot root@192.168.0.35:/root # 注:传文件夹
[root@cPen_python ssh]# scp -r root@192.168.0.35:/etc/passwd # 注:拿文件夹
[root@cPen_python ssh]# ssh root@192.168.0.35 bash /root/echo.sh feng zhang wang
scp 就是在2台机器之间底层使用ssh协议来拷贝文件或者文件夹
---------------------------------------------------------------------------------------------------------------------------------
[root@cPen_centos8 ssh]# getenforce # 注:查看selinux
Disabled
[root@cPen_centos8 ssh]# setenforce 0 # 注:临时关闭selinux
setenforce: SELinux is disabled
---------------------------------------------------------------------------------------------------------------------------------
[sanchuang@cPen_centos8 ~]$ ifdown ens33
[sanchuang@cPen_centos8 ~]$ ifup ens33
#注:禁用root用户登录后,本地可以用root用户登录