集群架构 - SSH远程服务管理

1. SSH远程服务端

1.1 SSH服务概述

SSH服务由服务端软件OpenSSH和SSH客户端组成。

OpenSSH提供一个安全的远程Secure shell用于管理远程Linux系统。

OpenSSH使用非对称加密手段加密保护通信数据。

1.2 SSH服务特点

  1. SSH建立在应用层基础之上的安全协议: 可靠,提供安全的远程登录会话协议
  2. SSH服务端后台启动名为sshd: 实时监听22端口,响应来自客户端的请求连接
  3. SSH服务端几乎支持所有的UNIX平台: 同时有效的防止远程管理过程中信息泄露
  4. SSH客户端适用多种平台: ssh远程连接、scp远程拷贝、sftp远程传输

1.3 SSH服务详细概述

SSH协议优势:

  • 加密传输数据
  • 防止中间人攻击
  • 支持多种认证方式
  • 支持端口转发

OpenSSH详细概述:

  • OpenSSH是SSH协议的免费开源实现
  • 提供SSH客户端和服务器端程序
  • 支持多种加密算法
  • 支持密钥认证和密码认证

1.4 安装SSH服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装SSH服务端
[root@liyanzhao ~]# yum install openssh-server

# 启动SSH服务并加入开机自启动
[root@liyanzhao ~]# systemctl enable sshd
[root@liyanzhao ~]# systemctl start sshd

# 检查服务状态
[root@liyanzhao ~]# systemctl status sshd

# 检查端口监听
[root@liyanzhao ~]# ss -lntup | grep :22
tcp LISTEN 0 128 :22 *:* users:(("sshd",pid=1234,fd=3))

2. SSH远程客户端

2.1 SSH客户端概述

SSH是典型的客户端和服务端的交互模式,客户端广泛的支持各个平台。

Windows平台:

  • 有很多工具可以支持SSH连接功能
  • 建议使用Xshell、PuTTY、SecureCRT等

Linux平台:

  • 需要安装客户端软件
  • yum install openssh-clients

2.2 客户端连接SSH服务方式

基本连接方式

1
2
3
4
5
6
7
8
# 使用ssh登陆远程主机
[root@liyanzhao ~]# ssh remotehost

# 使用指定用户登陆远程主机
[root@liyanzhao ~]# ssh remoteuser@remotehost

# 使用ssh服务不登陆远程主机执行命令
[root@liyanzhao ~]# ssh remoteuser@remotehost remote-command

示例:

1
2
3
4
5
6
7
8
# 使用root用户连接
ssh root@192.168.56.11

# 使用指定端口连接
ssh -p 2222 root@192.168.56.11

# 远程执行命令
ssh root@192.168.56.11 "ls -l /tmp"

2.3 SCP全量远程拷贝命令

命令参数说明:

  • -P: 指定端口,默认22端口可不写(大写)
  • -r: 递归拷贝目录
  • -p: 保持文件属性不变
  • -l: 限制传输速度

推送:push(上传)

1
2
3
4
5
# 推送文件到远程服务器
scp -P22 -pr /etc/inittab root@192.168.56.11:/tmp/

# 推送目录到远程服务器
scp -P22 -pr /etc/sysconfig root@192.168.56.11:/tmp/

拉取:pull(下载)

1
2
3
4
5
# 从远程服务器下载文件
scp -P22 -pr root@192.168.56.11:/tmp/inittab /root/

# 从远程服务器下载目录
scp -P22 -pr root@192.168.56.11:/tmp/sysconfig /root/

注意: scp通过加密的远程拷贝,支持数据推送和拉取,但仅能全量拷贝效率低。

2.4 SFTP远程传输命令

SFTP(SSH File Transfer Protocol)是SSH的扩展,提供交互式文件传输功能。

连接远程SFTP

1
2
# 连接远程sftp
sftp root@192.168.56.12

SFTP常用命令

命令 说明
get 下载文件
put 上传文件
ls 列出远程目录
lls 列出本地目录
cd 切换远程目录
lcd 切换本地目录
pwd 显示远程当前目录
lpwd 显示本地当前目录
quitexit 退出

SFTP使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 连接SFTP
sftp root@192.168.56.12

# 下载文件到本地服务器
sftp> get conf.txt /tmp/

# 上传本地服务器文件到远程服务器
sftp> put /root/t1.txt /root/

# 下载目录
sftp> get -r /remote/dir /local/dir

# 上传目录
sftp> put -r /local/dir /remote/dir

3. SSH远程登录方式

3.1 基于账户密码远程登录

知道服务器的IP端口、账号密码,即可通过ssh客户端登陆远程主机,远程主机联机过程中传输数据都是加密的。

1
2
3
4
5
# 使用密码登录
➜ ~ ssh -p22 root@192.168.56.11
root@192.168.56.11's password:
Last login: Mon Dec 18 16:33:38 2017 from 192.168.56.1
[root@A_Server ~]#

密码登录特点:

  • 简单易用
  • 需要每次输入密码
  • 密码可能被暴力破解
  • 安全性相对较低

3.2 基于密钥远程登录

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

SSH密钥原理:

  • ssh key使用非对称加密方式生成公钥和私钥
  • 私钥存放在本地~/.ssh目录
  • 公钥存储至需要登陆的服务器~/.ssh/authorized_keys

生成SSH密钥对

1
2
3
4
5
6
7
8
9
10
11
# 为了免秘钥的安全性,在A服务器建立普通用户,被登陆的B服务器也需要有相同账户
[root@A_Server ~]# su - liyanzhao

# 在A服务器上生成密钥,-t密钥类型,-C指定用户邮箱
[liyanzhao@A_Server ~]$ ssh-keygen -t rsa -C liyanzhao@foxmail.com
Generating public/private rsa key pair.
Enter file in which to save the key (/home/liyanzhao/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/liyanzhao/.ssh/id_rsa.
Your public key has been saved in /home/liyanzhao/.ssh/id_rsa.pub.

密钥类型:

  • rsa: RSA算法(推荐)
  • dsa: DSA算法
  • ecdsa: ECDSA算法
  • ed25519: Ed25519算法(最新,推荐)

分发公钥到远程服务器

1
2
3
4
5
6
7
# 公钥发送B服务器,输入B登录服务器密码,会提示建立authorized_keys新文件
[liyanzhao@A_Server .ssh]$ ssh-copy-id -i ~/.ssh/id_rsa.pub liyanzhao@192.168.56.12
/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
liyanzhao@192.168.56.12's password:

Number of key(s) added: 1

使用密钥登录

1
2
3
4
# A服务器使用普通用户密钥方式登陆B服务器
[liyanzhao@A_Server ~]$ ssh liyanzhao@192.168.56.12
Last login: Wed Dec 13 18:07:16 2017 from 192.168.56.1
[liyanzhao@B_Server ~]$

密钥登录特点:

  • 无需输入密码
  • 安全性高
  • 支持批量管理
  • 适合自动化脚本

常见错误处理

错误1: no route to host

1
2
3
# 原因:防火墙阻止
# 解决:检查防火墙规则
firewall-cmd --list-all

错误2: Connection refused

1
2
3
# 原因:防火墙或服务未启用
# 解决:检查SSH服务状态
systemctl status sshd

4. SSH配置安全防护

4.1 SSH服务登录防护手段

  1. 更改SSH服务远程登录端口
  2. 更改SSH服务监听本地内网IP
  3. 更改SSH服务禁止密码登录
  4. 更改SSH服务禁止ROOT管理员登录
  5. 更改SSH服务密码登录认证为密钥登录
  6. 重要服务器尽可能不使用公网IP地址
  7. 使用防火墙限制来源IP地址

4.2 SSH服务配置文件

SSH服务登录防护手段配置文件:/etc/ssh/sshd_config

4.3 SSH安全配置详解

更改SSH远程连接端口

1
2
3
4
5
# 编辑SSH配置文件
vim /etc/ssh/sshd_config

# 更改SSH远程连接端口
Port 6666

注意: 修改端口后需要:

  • 重启SSH服务
  • 更新防火墙规则
  • 使用新端口连接

绑定本地内网地址

1
2
# 绑定本地内网地址
ListenAddress 192.168.56.11

禁止Root管理员登录

1
2
# 禁止Root管理员登录
PermitRootLogin no

禁止密码登录

1
2
# 禁止密码登录
PasswordAuthentication no

允许以root密钥方式登陆

1
2
# 允许以root密钥方式登陆(禁止密码默认以root登陆)
PermitRootLogin without-password

禁止使用空密码

1
2
# 禁止使用空密码(默认禁止)
PermitEmptyPasswords no

关闭DNS解析,优化连接速度

1
2
3
# 关闭DNS解析,优化连接速度
UseDNS no
GSSAPIAuthentication no

4.4 完整SSH安全配置示例

添加如下配置至sshd配置文件/etc/ssh/sshd_config,根据需求做调整:

1
2
3
4
5
6
7
8
9
###SSH###
Port 6666
ListenAddress 192.168.56.11
PasswordAuthentication no
PermitRootLogin no
#PermitEmptyPasswords no
GSSAPIAuthentication no
UseDNS no
###END###

4.5 应用配置并重启服务

1
2
3
4
5
6
7
8
# 测试配置文件语法
sshd -t

# 重启SSH服务
systemctl restart sshd

# 检查服务状态
systemctl status sshd

4.6 其他安全建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 限制最大尝试次数
MaxAuthTries 3

# 设置超时时间
ClientAliveInterval 300
ClientAliveCountMax 2

# 限制用户登录
AllowUsers liyanzhao
DenyUsers root

# 限制用户组登录
AllowGroups wheel
DenyGroups test

5. SSH密钥分发实战

5.1 需求说明

要求所有服务器在统一用户liyanzhao,实现A机器从本地分发数据到B、C机器上,在分发到B、C的过程中不需要输入密码验证,当然除了分发的功能,还可以批量查看所有客户机上的CPU,LOAD,MEM,系统版本等信息。即实现从A服务器发布数据到B、C客户端服务器以及查看信息的免密码登录验证解决方案。

5.2 密钥批量分发

步骤1: 添加普通用户账号

部署密钥之前,先分别在A、B、C服务器上添加普通用户并配置密码。

1
2
3
# 在所有服务器上执行
useradd liyanzhao
echo "123456" | passwd --stdin liyanzhao

步骤2: A服务器切换普通用户并生成密钥

如下操作均在A-Server服务器上操作:

1
2
3
4
5
6
7
8
9
10
11
# A服务器切换普通用户
[root@A_Server ~]# su - liyanzhao

# 生成密钥对
[liyanzhao@A_Server ~]$ ssh-keygen -t rsa -C A-Server.com
Generating public/private rsa key pair.
Enter file in which to save the key (/home/liyanzhao/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): # 直接回车
Enter same passphrase again: # 直接回车
Your identification has been saved in /home/liyanzhao/.ssh/id_rsa.
Your public key has been saved in /home/liyanzhao/.ssh/id_rsa.pub.

步骤3: A服务器分发秘钥至B服务器

SSH不是默认端口,使用-P指定对应端口。

1
2
# 分发公钥到B服务器
[liyanzhao@A_Server ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub "-p6666 liyanzhao@192.168.56.12"

步骤4: 通过A服务器登陆至B服务器测试

1
2
3
4
# 测试密钥登录
[liyanzhao@A_Server ~]$ ssh -p22 liyanzhao@192.168.56.12
Last login: Wed Dec 13 18:07:16 2017 from 192.168.56.1
[liyanzhao@B_Server ~]$

步骤5: 分发A服务器秘钥至C服务器

1
2
# 分发公钥到C服务器
[liyanzhao@A_Server ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub "-p6666 liyanzhao@192.168.56.13"

步骤6: 通过A服务器登陆至C服务器测试

1
2
3
4
# 测试密钥登录
[liyanzhao@A_Server ~]$ ssh -p22 liyanzhao@192.168.56.13
Last login: Wed Dec 13 18:07:16 2017 from 192.168.56.1
[liyanzhao@C_Server ~]$

5.3 批量执行命令及文件分发

批量执行命令脚本

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
# 创建批量执行命令脚本
[root@A_Server ~]# cat > ssh_command.sh <<'EOF'
#!/bin/bash
if [ $# -ne 1 ];then
echo "USAGE $0: {Please Command}"
exit 1
fi

Command="$1"
IP="192.168.56"
User=liyanzhao
Port=22

for i in 12 13
do
echo "##Server IS $IP.$i###"
/usr/bin/ssh $User@$IP.$i -p"$Port" "$Command"
done
EOF

# 设置执行权限
chmod +x ssh_command.sh

# 使用示例
./ssh_command.sh "uptime"
./ssh_command.sh "free -h"
./ssh_command.sh "df -h"

批量分发文件脚本

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
# 创建批量分发文件脚本
[root@A_Server ~]# cat > ssh_file.sh <<'EOF'
#!/bin/bash
if [ $# -ne 2 ];then
echo "USAGE $0: {LocalFile|RemoteFile}"
exit 1
fi

File1="$1"
DirFile="$2"
IP="192.168.56"
User=liyanzhao
Port=22

for i in 12 13
do
echo "##Server IS $IP.$i###"
/usr/bin/scp -rp -P"$Port" $File1 $User@$IP.$i:"$DirFile"
done
EOF

# 设置执行权限
chmod +x ssh_file.sh

# 使用示例
./ssh_file.sh /root/test.txt /tmp/
./ssh_file.sh /root/config/ /tmp/

6. SSH企业项目案例

6.1 项目需求

ssh密钥实现批量分发备份、批量管理实战考试

时间: 5分钟

环境: 请准备有三台linux机器分别为A,B,C

6.2 题目1: 一把钥匙开多把锁

用自己的名字后面加888(例如:liyanzhao888)的用户完成一把钥匙开多把锁(A钥匙,B、C锁)的免密码验证登陆部署场景。

架构图:

1
2
A服务器(liyanzhao888)--密钥--> B服务器(liyanzhao888)
A服务器(liyanzhao888)--密钥--> C服务器(liyanzhao888)

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 在所有服务器创建用户
useradd liyanzhao888
echo "123456" | passwd --stdin liyanzhao888

# 2. 在A服务器生成密钥
su - liyanzhao888
ssh-keygen -t rsa -C "A-Server"

# 3. 分发公钥到B和C服务器
ssh-copy-id liyanzhao888@B服务器IP
ssh-copy-id liyanzhao888@C服务器IP

# 4. 测试连接
ssh liyanzhao888@B服务器IP
ssh liyanzhao888@C服务器IP

6.3 题目2: 多把钥匙开一把锁

在不破坏题1的前提下,同样用自己的名字加888的用户完成多把钥匙开一把锁(B、C钥匙,A锁)的免密码验证登陆部署场景。

架构图:

1
2
B服务器(liyanzhao888)--密钥--> A服务器(liyanzhao888)
C服务器(liyanzhao888)--密钥--> A服务器(liyanzhao888)

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 在B服务器生成密钥
# 在B服务器执行
su - liyanzhao888
ssh-keygen -t rsa -C "B-Server"
ssh-copy-id liyanzhao888@A服务器IP

# 2. 在C服务器生成密钥
# 在C服务器执行
su - liyanzhao888
ssh-keygen -t rsa -C "C-Server"
ssh-copy-id liyanzhao888@A服务器IP

# 3. 测试连接
# 从B服务器测试
ssh liyanzhao888@A服务器IP

# 从C服务器测试
ssh liyanzhao888@A服务器IP

6.4 题目3: 批量分发文件到用户家目录

如何实现从A指定目录批量分发文件到B、C用户的家目录(借助问题1的部署结果)。

时间: 2分钟

解答: 考察scp用法

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 方法1: 使用scp命令
scp /path/to/file liyanzhao888@B服务器IP:~/
scp /path/to/file liyanzhao888@C服务器IP:~/

# 方法2: 使用脚本批量分发
cat > batch_scp.sh <<'EOF'
#!/bin/bash
File="$1"
for host in B服务器IP C服务器IP
do
scp $File liyanzhao888@$host:~/
done
EOF

chmod +x batch_scp.sh
./batch_scp.sh /path/to/file

6.5 题目4: 分发文件到任意目录(普通用户)

实现从A指定目录的文件分发到B、C的任意目录下(不用root用户如何实现)?

时间: 5分钟

解答: 考察普通用户提权

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 方法1: 使用sudo提权(需要配置sudoers)
# 在B和C服务器配置sudo
visudo
liyanzhao888 ALL=(ALL) NOPASSWD: /usr/bin/scp

# 在A服务器执行
scp /path/to/file liyanzhao888@B服务器IP:/tmp/
ssh liyanzhao888@B服务器IP "sudo cp /tmp/file /etc/"

# 方法2: 使用目标目录的写权限
# 确保目标目录对liyanzhao888用户有写权限
ssh liyanzhao888@B服务器IP "chmod 777 /target/dir"
scp /path/to/file liyanzhao888@B服务器IP:/target/dir/

# 方法3: 使用rsync(推荐)
rsync -avz /path/to/file liyanzhao888@B服务器IP:/target/dir/

6.6 题目5: 批量查看系统信息

如何快速查看所有机器的负载load,CPU,内存等信息(借助问题1的部署结果)。

思考: 如果服务器数量多,如何并发查看和分发数据

时间: 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
# 方法1: 串行执行(简单但慢)
cat > batch_info.sh <<'EOF'
#!/bin/bash
for host in B服务器IP C服务器IP
do
echo "=== $host ==="
ssh liyanzhao888@$host "uptime && free -h && df -h"
done
EOF

# 方法2: 并行执行(快速)
cat > batch_info_parallel.sh <<'EOF'
#!/bin/bash
for host in B服务器IP C服务器IP
do
{
echo "=== $host ==="
ssh liyanzhao888@$host "uptime && free -h && df -h"
} &
done
wait
EOF

# 方法3: 使用pssh工具(推荐)
# 安装pssh
yum install pssh -y

# 创建主机列表
cat > hosts.txt <<EOF
liyanzhao888@B服务器IP
liyanzhao888@C服务器IP
EOF

# 并行执行命令
pssh -h hosts.txt -i "uptime && free -h && df -h"

6.7 高级批量管理方案

使用Ansible(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
# 安装Ansible
yum install ansible -y

# 配置主机清单
cat > /etc/ansible/hosts <<EOF
[webservers]
B服务器IP
C服务器IP
EOF

# 执行命令
ansible webservers -m shell -a "uptime && free -h"

使用expect自动化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 安装expect
yum install expect -y

# 创建自动化脚本
cat > auto_scp.exp <<'EOF'
#!/usr/bin/expect
set host [lindex $argv 0]
set file [lindex $argv 1]
set dest [lindex $argv 2]

spawn scp $file liyanzhao888@$host:$dest
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "123456\r" }
}
expect eof
EOF

chmod +x auto_scp.exp
./auto_scp.exp B服务器IP /path/to/file /tmp/

7. SSH高级应用

7.1 SSH隧道

本地端口转发

1
2
# 将本地8080端口转发到远程服务器的80端口
ssh -L 8080:localhost:80 user@remotehost

远程端口转发

1
2
# 将远程服务器的8080端口转发到本地的80端口
ssh -R 8080:localhost:80 user@remotehost

动态端口转发(SOCKS代理)

1
2
# 创建SOCKS代理
ssh -D 1080 user@remotehost

7.2 SSH跳板机

1
2
3
4
5
6
7
8
9
10
# 通过跳板机连接目标服务器
ssh -J jumpuser@jumphost targetuser@targethost

# 配置文件方式
cat >> ~/.ssh/config <<EOF
Host target
HostName targethost
User targetuser
ProxyJump jumpuser@jumphost
EOF

7.3 SSH配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 编辑SSH客户端配置
vim ~/.ssh/config

# 配置示例
Host server1
HostName 192.168.56.11
User root
Port 22
IdentityFile ~/.ssh/id_rsa

Host server2
HostName 192.168.56.12
User liyanzhao
Port 6666
IdentityFile ~/.ssh/id_rsa

8. SSH故障排查

8.1 常见问题

问题1: 连接超时

1
2
3
4
5
6
7
8
# 检查网络连通性
ping 目标服务器IP

# 检查端口是否开放
telnet 目标服务器IP 22

# 检查防火墙
firewall-cmd --list-all

问题2: 权限被拒绝

1
2
3
4
5
6
7
8
# 检查密钥权限
ls -l ~/.ssh/
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

# 检查远程服务器权限
ls -l ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

问题3: 主机密钥验证失败

1
2
3
4
5
# 清除known_hosts中的旧密钥
ssh-keygen -R 目标服务器IP

# 或手动编辑
vim ~/.ssh/known_hosts

8.2 调试模式

1
2
3
4
5
6
7
8
# 使用详细模式连接
ssh -v user@host
ssh -vv user@host
ssh -vvv user@host

# 查看SSH服务日志
tail -f /var/log/secure
journalctl -u sshd -f

9. SSH安全最佳实践

9.1 安全建议

  1. 使用密钥认证: 禁用密码认证
  2. 更改默认端口: 避免使用22端口
  3. 限制用户登录: 使用AllowUsers/DenyUsers
  4. 使用防火墙: 限制来源IP
  5. 定期更新: 保持SSH软件最新
  6. 监控日志: 定期检查登录日志
  7. 使用fail2ban: 防止暴力破解

9.2 Fail2ban配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装fail2ban
yum install fail2ban -y

# 配置fail2ban
cat > /etc/fail2ban/jail.local <<EOF
[sshd]
enabled = true
port = 22
maxretry = 3
bantime = 3600
EOF

# 启动服务
systemctl start fail2ban
systemctl enable fail2ban

实战优化