如何配置SSH密钥登录:Shell脚本自动化实战指南
目录导读
SSH密钥认证原理与优势
在深入Shell脚本配置之前,必须理解SSH密钥认证的核心机制,与传统密码认证不同,密钥对由私钥(位于客户端,需严格保密)和公钥(部署到服务器)组成,认证时,服务器使用公钥加密挑战数据,客户端用私钥解密,整个过程无需传输密码。

主要优势:
- 防御暴力破解:密钥长度通常2048位以上,穷举难度极高
- 自动化友好:脚本无需处理密码交互,支持免密登录
- 集中权限管理:通过公钥分发即可控制访问权限
- 审计追踪:结合
~/.ssh/authorized_keys日志,可追踪具体用户行为
基础配置步骤详解
1 生成密钥对
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/id_rsa_server
参数说明:
-t rsa:指定算法(支持rsa/ed25519)-b 4096:位长度(推荐4096)-C:注释标记-f:指定文件名,避免覆盖默认密钥
2 上传公钥到服务器
传统方式使用ssh-copy-id:
ssh-copy-id -i ~/.ssh/id_rsa_server.pub user@server_ip
该命令自动将公钥追加到服务器的~/.ssh/authorized_keys文件,并设置正确权限(600)。
3 服务端配置优化
编辑/etc/ssh/sshd_config:
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
PermitRootLogin prohibit-password
配置后重启服务:sudo systemctl restart sshd
Shell脚本自动化配置方案
1 一键生成并部署密钥(交互式脚本)
#!/bin/bash
# 脚本名称: configure_ssh_key.sh
# 功能: 自动生成密钥对并部署到远程服务器
set -e
# 颜色输出定义
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# 检查依赖
command -v ssh-keygen >/dev/null 2>&1 || { echo "$RED Error: ssh-keygen not found $NC"; exit 1; }
# 输入参数
read -p "输入远程服务器IP: " SERVER_IP
read -p "输入用户名: " USERNAME
read -p "密钥文件名(默认id_rsa_custom): " KEY_NAME
KEY_NAME=${KEY_NAME:-id_rsa_custom}
# 生成密钥(非交互模式)
echo -e "${GREEN}正在生成密钥对...${NC}"
ssh-keygen -t rsa -b 4096 -f "$HOME/.ssh/$KEY_NAME" -N "" -C "auto-key-$(date +%Y%m%d)" <<< y
# 部署公钥
echo -e "${GREEN}正在部署公钥到 $SERVER_IP ...${NC}"
ssh-copy-id -i "$HOME/.ssh/${KEY_NAME}.pub" "$USERNAME@$SERVER_IP" 2>&1 || {
echo -e "${RED}部署失败,请检查网络或密码${NC}"
exit 1
}
# 创建SSH配置文件简化登录
cat >> "$HOME/.ssh/config" << EOF
Host $SERVER_IP
HostName $SERVER_IP
User $USERNAME
IdentityFile ~/.ssh/$KEY_NAME
IdentitiesOnly yes
EOF
echo -e "${GREEN}部署完成!测试连接:ssh $USERNAME@$SERVER_IP${NC}"
2 非交互式批量配置脚本(生产环境)
#!/bin/bash
# 用途:通过密码自动批量部署密钥
PASSWORDS_FILE="servers.txt"
# servers.txt格式:ip user password
# 10.0.0.1 root MyP@ss123
# 10.0.0.2 admin Secure_456
while IFS= read -r line; do
IP=$(echo $line | awk '{print $1}')
USER=$(echo $line | awk '{print $2}')
PASS=$(echo $line | awk '{print $3}')
# 使用expect处理交互式密码输入
expect <<-EOF
spawn ssh-copy-id -i ~/.ssh/deploy_key.pub $USER@$IP
expect {
"password:" { send "$PASS\r"; exp_continue }
"yes/no" { send "yes\r"; exp_continue }
eof
}
EOF
# 禁用密码登录
ssh "$USER@$IP" "sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config && sudo systemctl restart sshd"
done < "$PASSWORDS_FILE"
重要提示:生产环境建议使用Ansible等工具代替expect,密码明文存储存在安全风险。
批量配置与安全加固策略
1 基于主机的访问控制
在authorized_keys文件中,可通过from=限制来源IP:
echo 'from="192.168.1.0/24,10.0.0.5" ssh-rsa AAAA... comment' >> ~/.ssh/authorized_keys
2 多因素认证叠加
密钥认证可配合sshguard或fail2ban使用:
sudo apt install fail2ban -y sudo systemctl enable fail2ban
3 密钥轮换自动化脚本
#!/bin/bash
# 每90天自动轮换密钥
if [ $(date +%s) -gt $(cat ~/.ssh/last_rotation 2>/dev/null || echo 0) ]; then
ssh-keygen -t ed25519 -f ~/.ssh/rotated_key -N "" -C "rotation-$(date +%Y%m%d)"
scp ~/.ssh/rotated_key.pub user@server_ip:~/.ssh/authorized_keys_new
ssh user@server_ip "cat ~/.ssh/authorized_keys_new > ~/.ssh/authorized_keys && rm ~/.ssh/authorized_keys_new"
date +%s > ~/.ssh/last_rotation
fi
常见问题与解答(FAQ)
Q1:部署密钥后仍然需要输入密码? A:检查以下问题:
- 客户端:确认
ssh -v user@ip输出中使用了正确密钥 - 服务端:检查
~/.ssh/authorized_keys权限(应为600),父目录~/.ssh权限(应为700) - SELinux/AppArmor:查看
ausearch -m AVC或journalctl -u sshd
Q2:如何同时配置多台服务器的免密登录?
A:使用ssh-agent加载私钥,或通过~/.ssh/config为不同服务器指定不同密钥:
Host server1
HostName 10.0.0.1
IdentityFile ~/.ssh/key1
Host server2
HostName 10.0.0.2
IdentityFile ~/.ssh/key2
Q3:Ed25519算法比RSA更好吗? A:Ed25519提供更高安全级别和更快的签名速度(约5x),且密钥更短,推荐首选ed25519,但需确保服务端支持(OpenSSH 6.5+),旧系统可保留RSA兼容。
Q4:密钥泄露后如何紧急处理? A:立即执行:
- 从
authorized_keys移除对应公钥 - 更新防火墙临时限制来源IP
- 使用
ssh-keygen -R hostname清除客户端known_hosts - 检查
/var/log/secure或/var/log/auth.log确认未发生入侵
Q5:脚本执行时报"Permission denied (publickey)"? A:常见原因:
- 公钥未正确追加(需逐行写入,避免多余空格)
- 服务器SSH配置中
PubkeyAuthentication未启用 - 使用
-i参数未指定正确的私钥路径 - 文件权限错误:
chmod 600 ~/.ssh/authorized_keys
企业级最佳实践建议
1 堡垒机集成方案
通过跳板机统一管理密钥分发:
# 在跳板机配置sshd_config ForceCommand /usr/local/bin/key_audit.sh # 该脚本记录所有SSH Session的Start/End时间及执行命令
2 使用证书认证替代原始密钥
部署OpenSSH证书中心:
# CA签发用户证书 ssh-keygen -s ca_key -I "user_id" -n "user1,user2" -V "+52w" user_key.pub # 服务端信任证书 echo "TrustedUserCAKeys /etc/ssh/ca.pub" >> /etc/ssh/sshd_config
证书认证可精确控制有效期、允许命令等。
3 监控与审计脚本
#!/bin/bash
# 检查所有用户的authorized_keys异常条目
for user in $(awk -F: '$7 ~ /bash|sh/ {print $1}' /etc/passwd); do
if [ -f "/home/$user/.ssh/authorized_keys" ]; then
echo "=== $user ==="
cat /home/$user/.ssh/authorized_keys | grep -vE "^(#|$)"
fi
done > /var/log/ssh_key_audit_$(date +%Y%m%d).log
4 部署检查清单
- [ ] 所有服务器禁用
PasswordAuthentication - [ ] 密钥至少2048位RSA或256位ED25519
- [ ] 私钥存储于HSM或加密卷
- [ ] 每90天自动轮换一次密钥
- [ ] 堡垒机记录所有SSH会话
- [ ] fail2ban配置5次失败后封禁1小时
通过以上Shell脚本方案,您能快速实现SSH密钥认证的自动化部署,从单机配置到企业级批量管理,关键在于坚持最小权限原则和定期审计,建议将本文脚本纳入CI/CD管道,结合基础设施即代码工具(Terraform/Ansible)实现完全自动化的安全运维。