Skip to content

SSH远程访问及控制

SSH概述

SSH(Secure Shell)是一种安全通道协议,主要用来实现字符界面的远程登录、远程复制等功能。SSH 协议对通信双方的数据传输进行了加密处理,其中包括用户登录时输入的用 户口令,与TELNET(远程登录)等应用相比,SSH

默认监听端口:TCP 22

加密方式

  • 对称加密:是指加密和解密用的是同一套密钥(效率高)
  • 非对称加密:加密用公钥,解密用私有(加密和解密用的不是同一套密钥)(非对称加密的安全性高)

网络通信流程

mermaid
sequenceDiagram
    participant Client
    participant Server

    %% ========== TCP三次握手 ==========
    Note over Client,Server: 【TCP连接建立】三次握手
    Client->>Server: SYN (seq=x)
    Server->>Client: SYN-ACK (ack=x+1, seq=y)
    Client->>Server: ACK (ack=y+1)

    %% ========== 非对称加密部分 ==========
    rect rgb(255, 240, 240)
    Note over Server: 【非对称加密阶段】密钥交换
    Server->>Client: 发送服务器公钥
    Note over Client: 客户端保存服务器公钥
    Client->>Server: 用服务器公钥加密的对称密钥
    Note over Server: 服务器用私钥解密获取对称密钥
    end

    %% ========== 对称加密部分 ==========
    rect rgb(240, 240, 255)
    Note over Client,Server: 【对称加密阶段】安全通信
    loop 加密数据传输
        Client->>Server: 加密数据[对称密钥]
        Server->>Client: 加密响应[对称密钥]
    end
    end

一、TCP三次握手建立连接

  1. 客户端发起连接(SYN)
    • 客户端发送 SYN 包(同步序列号)到服务器
    • 包含初始序列号 seq=x,表示客户端数据流的起始点
  2. 服务器响应(SYN-ACK)
    • 服务器回复SYN-ACK包:
      • ack=x+1 确认收到客户端的 SYN
      • 同时发送自己的初始序列号 seq=y
  3. 客户端确认(ACK)
    • 客户端发送ACK包:
      • ack=y+1 确认收到服务器的 SYN
    • 连接建立完成,双方进入可通信状态

二、非对称加密阶段(紫色文字部分)

  1. 服务器发送公钥
    • 服务器将自己的 公钥 发送给客户端
    • 客户端收到后保存该公钥(标注:"客户端收到公钥后保存")
  2. 客户端加密对称密钥
    • 客户端生成一个 对称加密的临时密钥(会话密钥)
    • 使用服务器的公钥加密该密钥,并发送给服务器(标注:"客户端用服务端公钥将自己的对称加密密钥传给服务端")
  3. 服务器解密密钥
    • 服务器用 私钥 解密获取对称密钥(标注:"服务端用自己的私钥解密")
    • 此时双方共享同一对称密钥,后续通信将切换为对称加密

三、对称加密数据传输(红色箭头部分)

  1. 加密通信开始
    • 所有数据传输均使用 对称密钥 加密(标注:"数据传输用的是对称加密的密钥")
    • 包括:
      • 客户端→服务器的请求(如登录凭证、命令)
      • 服务器→客户端的响应(如执行结果、文件内容)
  2. 流程特点
    • 高效性:对称加密比非对称加密计算量小,适合持续数据传输
    • 安全性:密钥通过非对称加密安全交换,避免中间人攻击

关键设计解析

  1. 非对称加密的作用
    • 仅用于 安全交换对称密钥(解决密钥分发问题)
    • 公钥公开,私钥保密(标注:"私钥在自己手里")
  2. 对称加密的作用
    • 加密实际通信内容(标注:"对称加密数据传输")
    • 算法如 AES,速度快且资源占用低
  3. 完整安全性
    • 双向认证(服务器通过公钥证明身份,客户端通过密码/密钥证明身份)
    • 前向保密(临时对称密钥会话结束后销毁)

OpenSSH

OpenSSH 是 SSH (Secure Shell) 协议的开源实现,用于在不安全的网络中提供安全的加密通信。它主要用于远程登录、文件传输等操作。

重点路径

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

配置文件解析

服务端sshd_config解析

ini
# 网络监听
Port 22                       				# 监听端口(建议改为1024以上端口防扫描)
ListenAddress 0.0.0.0         				# 监听所有IP(生产环境建议绑定具体IP)
AddressFamily inet            				# 仅IPv4(inet6为IPv6)

# 密钥文件配置(对应非对称加密)
HostKey /etc/ssh/ssh_host_ed25519_key   	# ED25519算法(首选)
HostKey /etc/ssh/ssh_host_rsa_key       	# RSA备份(兼容旧客户端)

# 密钥重新生成周期(默认2小时)
KeyRegenerationInterval 3600
ServerKeyBits 4096           				# RSA密钥长度(至少2048)

# 非对称密钥认证(对应图中公钥认证流程)
PubkeyAuthentication yes     				# 启用公钥认证
AuthorizedKeysFile .ssh/authorized_keys  	# 用户公钥存储路径

# 密码认证(高风险,建议关闭)
PasswordAuthentication no
PermitEmptyPasswords no

# 其他认证限制
PermitRootLogin no           				# 禁止root直接登录。prohibit-password允许root密钥登录
MaxAuthTries 3               				# 每连接最大认证尝试次数

# 密钥交换算法(对应图中密钥协商阶段)
KexAlgorithms curve25519-sha256,ecdh-sha2-nistp521

# 对称加密算法(对应图中加密数据传输阶段)
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com

# MAC完整性校验算法
MACs hmac-sha2-512-etm@openssh.com

# 协议版本控制
Protocol 2                  				# 禁用旧的SSHv1

# 超时设置(防僵死连接)
ClientAliveInterval 300      				# 300秒检测一次客户端活动
ClientAliveCountMax 3        				# 3次无响应后断开

# 连接限制
MaxSessions 10              				# 每IP最大会话数
MaxStartups 10:30:60        				# 并发未认证连接限制

# 日志级别(调试时设为VERBOSE)
LogLevel INFO

# 权限严格检查
StrictModes yes             				# 检查用户目录权限
UsePrivilegeSeparation sandbox  			# 权限隔离

生产环境推荐配置

ini
# 安全基线配置
Port 2222
Protocol 2
# 设置客户端完成认证的​​最大时间窗口​​(从TCP连接建立到成功认证)
LoginGraceTime 1m
# 允许root密钥登录
PermitRootLogin prohibit-password
# 每连接最大认证尝试次数
MaxAuthTries 2
# 每IP最大会话数
MaxSessions 2
# 300秒检测一次客户端活动
ClientAliveInterval 300
# 完全禁用保活(特殊场景使用)
ClientAliveCountMax 0        # 需配合TCP层KeepAlive

客户端ssh_conf解析

ini
# 非对称密钥认证(匹配图中"客户端用服务端公钥加密"流程)
    IdentityFile ~/.ssh/id_ed25519     # 指定客户端私钥文件(用于认证)
    IdentitiesOnly yes                 # 只使用配置的密钥文件

# 服务器公钥验证(对应图中"客户端收到公钥后保存")
    StrictHostKeyChecking ask          # 首次连接时询问是否保存服务器公钥(保存到~/.ssh/known_hosts)
    UserKnownHostsFile ~/.ssh/known_hosts  # 服务器公钥存储路径

生成密钥

ssh-keygen

加密算法说明
rsa兼容性最好,但性能较低,密钥长度:默认 3072 位(推荐 ≥2048,安全临界值为 4096)-b 4096指定长度
ed25519安全性高,性能最优,密钥长度短,密钥长度:固定 256 位
ecdsa比 RSA 更高效,密钥尺寸更小,密钥长度:256/384/521 位。-b 384指定长度
dsa(已淘汰)OpenSSH 7.0+ 已默认禁用,存在安全性问题,密钥长度:固定 1024 位

案例

bash
# 生成ED25519密钥对(推荐)
ssh-keygen -t ed25519 -C "admin@server" -f ~/.ssh/server_key

# 生成4096位RSA密钥
ssh-keygen -t rsa -b 4096 -C "backup@example.com"

# 为现有私钥生成公钥
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub

# 批量生成无密码密钥对(自动化场景)
ssh-keygen -t rsa -b 2048 -N "" -f /tmp/auto_key
  • -C:添加注释(通常用邮箱标识)
  • -f:指定密钥文件路径

SSH密钥文件解析

私钥文件(保密!)

  • 默认路径:~/.ssh/id_[algorithm](如id_ed25519

  • 权限要求:600(仅用户可读写)

  • 内容特征:

    text
    -----BEGIN OPENSSH PRIVATE KEY-----
    BASE64编码的密钥数据...
    -----END OPENSSH PRIVATE KEY-----

公钥文件(可分发)

  • 默认路径:~/.ssh/id_[algorithm].pub

  • 内容格式:

    text
    ssh-ed25519 AAAAC3Nz... comment
    # 算法类型   Base64密钥  备注信息

已知主机记录(自动生成)

  • ~/.ssh/known_hosts:存储已验证过的主机指纹

客户端密钥登录

流程

mermaid
sequenceDiagram
    participant Client as 客户端
    participant Server as 服务器

    Note over Client: 准备阶段
    Client->>Client: 生成密钥对(ssh-keygen)
    Client->>Server: 将公钥写入~/.ssh/authorized_keys

    Note over Client: 认证阶段
    Client->>Server: SSH连接请求(TCP 22)
    Server-->>Client: 发送随机质询(challenge)

    alt 密钥验证成功
        Client->>Client: 用私钥签名质询
        Client->>Server: 发送签名结果
        Server->>Server: 用存储的公钥验证签名
        Server-->>Client: 认证通过
        Client->>Server: 建立加密通道
    else 密钥验证失败
        Server-->>Client: 退回密码认证或拒绝
    end

xshell连接

1.将私钥id_rsa下载到客户端

密钥生成后需要将id_rsa.pub内容写入到~/.ssh/authorized_keys认证文件中,否则客户端无法登录

bash
cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

2.设置用户身份验证

勾选Public Key并选中后右边选设置,将id_rsa秘钥上传

Linux连接(免密登录)

Linux 服务器之间的连接需要将当前服务器的公钥id_rsa.pub上传到要登录的服务器上

bash
# 生成密钥
ssh-copy-id -i ~/.ssh/id_rsa.pub IP

# 产生认证文件
cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys 

# 验证(无需密码)
ssh root@IP

免密免指纹

客户端第一次连接时会有指纹确认,保存后下次会跳过指纹确认

bash
# 生成密钥
ssh-keygen -t rsa -P "" -C "免密登录"
# 产生认证文件
cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
# 远程发送
ssh-copy-id -i  ~/.ssh/id_rsa.pub 目标IP

# 免指纹确认
sshpass -p "" ssh -o StrictHostKeyChecking=no root@IP

ssh密钥免交户批量分发脚本

shell
#!/bin/bash
# description:SSH密钥批量分发

IP_FILE="IP.txt"
# 定义加密技术
ENCCRYT="rsa"
# 定义ssh私钥文件
PRIVATE_KEY_FILE="$HOME/.ssh/id_$ENCCRYT"
# 定义ssh公钥文件
PUBLIC_KEY_FILE="$HOME/.ssh/id_$ENCCRYT.pub"
# 清空旧密钥
rm -rf "$HOME"/.ssh/
# 生成新秘钥
ssh-keygen -t "$ENCCRYT" -f "$PRIVATE_KEY_FILE" -P "" -C "批量主机免密登录" &>/dev/null

# 读取IP文件中的IP地址
while read -r line; do
    # 跳过空行
    [ -z "$line" ] && continue
    # 跳过以#开头的注释行
    [[ "$line" =~ ^#.*$ ]] && continue
    IP=$(echo "$line" | awk '{print $1}')
    USER=$(echo "$line" | awk '{print $2}')
    PWD=$(echo "$line" | awk '{print $3}')
    
    if ! ping "$IP" -c 1 &>/dev/null; then
    	echo "$1 无法ping通请检查网络"
    	continue
    fi
  	sshpass -p "$PWD" ssh-copy-id -i "$PUBLIC_KEY_FILE" -o StrictHostKeyChecking=no "$USER"@"$IP" &>/dev/null
    if [[ $? -eq 0 ]]; then
    	echo "$1 设置成功"
    else
    	echo "$1 设置失败" "ERROR"
    fi
done <"$IP_FILE"