本文档风哥主要介绍Linux系统大规模SSH免密登录与批量管理,包括SSH基础概念、密钥认证原理、批量管理工具、SSH密钥对生成与分发、批量命令执行以及实战案例等内容,风哥教程参考Linux官方文档Networking、Security等内容,适合系统管理员在生产环境中使用。
from PG视频:www.itpux.com
Part01-基础概念与理论知识
1.1 SSH基础概念
SSH(Secure Shell)是一种网络协议,用于在不安全的网络中安全地远程登录到服务器。SSH提供了加密的通信通道,确保数据传输的安全性。
- 远程登录:安全地登录到远程服务器
- 远程执行命令:在远程服务器上执行命令
- 文件传输:安全地传输文件(SCP、SFTP)
- 端口转发:建立安全的隧道
1.2 SSH密钥认证原理
SSH密钥认证是一种基于公钥加密的认证方式,比密码认证更安全:
1. 生成密钥对:公钥和私钥
2. 将公钥复制到远程服务器
3. 登录时,客户端使用私钥加密挑战信息
4. 服务器使用公钥解密,验证身份
# 密钥类型
– RSA:最常用,安全可靠
– DSA: deprecated,不推荐使用
– ECDSA:椭圆曲线加密,更安全,密钥更小
– Ed25519:现代加密算法,安全性高,性能好
1.3 批量管理工具介绍
常用的批量管理工具:
- pssh:并行SSH工具,用于在多台服务器上执行命令
- Ansible:自动化运维工具,支持批量配置和管理
- SaltStack:配置管理和远程执行工具
- Fabric:Python库,用于远程执行命令和部署
- ClusterSSH:同时控制多个SSH会话
Part02-生产环境规划与建议
2.1 SSH基础设施规划
生产环境SSH基础设施规划要点:
– 按功能分组:web服务器、数据库服务器、存储服务器
– 按环境分组:开发、测试、生产
– 按地理位置分组:北京、上海、广州
# 网络架构
– 跳板机:统一入口,加强安全控制
– 网络分段:不同网段隔离
– 防火墙:限制SSH访问
# 认证方式
– 密钥认证:禁用密码认证
– 双因素认证:增强安全性
– 集中认证:使用LDAP或Active Directory
2.2 密钥管理策略
生产环境密钥管理策略要点:
– 使用强密钥:RSA 4096位或Ed25519
– 定期轮换密钥:每3-6个月
– 密钥备份:安全存储私钥
# 密钥分发策略
– 集中管理:使用密钥管理系统
– 权限控制:严格控制谁能访问哪些服务器
– 审计日志:记录密钥使用情况
# 密钥撤销策略
– 员工离职:立即撤销密钥
– 密钥泄露:立即更换密钥
– 定期审查:清理未使用的密钥
2.3 安全考虑因素
生产环境SSH安全考虑因素:
– 更改默认端口:避免端口扫描
– 禁用root登录:使用普通用户+sudo
– 限制登录用户:AllowUsers配置
– 禁用密码认证:PasswordAuthentication no
– 限制登录尝试:MaxAuthTries 3
# 网络安全
– 使用防火墙:只允许特定IP访问SSH
– 网络监控:检测异常登录尝试
– 入侵检测:使用Fail2ban
# 审计与监控
– 登录日志:记录所有SSH登录
– 命令审计:记录执行的命令
– 异常检测:监控异常登录行为
Part03-生产环境项目实施方案
3.1 SSH密钥对生成与分发
3.1.1 生成SSH密钥对
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C “admin@fgedu.net.cn”
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ~/.ssh/id_ed25519.
Your public key has been saved in ~/.ssh/id_ed25519.pub.
# 查看密钥文件
$ ls -la ~/.ssh/
total 16
drwx—— 2 admin admin 4096 Apr 3 08:00 .
drwxr-xr-x 10 admin admin 4096 Apr 3 07:59 ..
-rw——- 1 admin admin 411 Apr 3 08:00 id_ed25519
-rw-r–r– 1 admin admin 99 Apr 3 08:00 id_ed25519.pub
3.1.2 批量分发SSH公钥
$ cat > hosts.txt << 'EOF' 192.168.1.101 192.168.1.102 192.168.1.103 192.168.1.104 192.168.1.105 EOF # 创建批量分发脚本 $ cat > distribute_ssh_key.sh << 'EOF' #!/bin/bash # distribute_ssh_key.sh # from:www.itpux.com.qq1更多学习教程公众号风哥教程itpux_com13257174.wx:itpux-com # web: `http://www.fgedu.net.cn` HOSTS_FILE="hosts.txt" USER="admin" PASSWD="fgedu123" while read host; do echo "Distributing SSH key to $host..." # 使用sshpass自动输入密码 sshpass -p "$PASSWD" ssh-copy-id -i ~/.ssh/id_ed25519.pub $USER@$host if [ $? -eq 0 ]; then echo "Successfully distributed SSH key to $host" else echo "Failed to distribute SSH key to $host" fi done < $HOSTS_FILE EOF # 赋予执行权限 $ chmod +x distribute_ssh_key.sh # 执行分发 $ ./distribute_ssh_key.sh Distributing SSH key to 192.168.1.101... /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/admin/.ssh/id_ed25519.pub" /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 admin@192.168.1.101's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'admin@192.168.1.101'" and check to make sure that only the key(s) you wanted were added. Successfully distributed SSH key to 192.168.1.101 ...
3.2 批量命令执行
3.2.1 使用pssh执行批量命令
$ sudo dnf install -y pssh
# 批量执行命令
$ pssh -h hosts.txt -l admin -i “uname -a”
[192.168.1.101] Sun Apr 3 08:05:00 CST 2026
[192.168.1.101] Linux fgedu-101 5.14.0-362.8.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Oct 20 16:36:52 EDT 2023 x86_64 x86_64 x86_64 GNU/Linux
[192.168.1.102] Sun Apr 3 08:05:01 CST 2026
[192.168.1.102] Linux fgedu-102 5.14.0-362.8.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Oct 20 16:36:52 EDT 2023 x86_64 x86_64 x86_64 GNU/Linux
…
# 批量检查磁盘使用情况
$ pssh -h hosts.txt -l admin -i “df -h”
[192.168.1.101] Filesystem Size Used Avail Use% Mounted on
[192.168.1.101] devtmpfs 3.9G 0 3.9G 0% /dev
[192.168.1.101] tmpfs 3.9G 0 3.9G 0% /dev/shm
[192.168.1.101] tmpfs 3.9G 9.6M 3.9G 1% /run
[192.168.1.101] /dev/sda1 50G 12G 38G 24% /
…
3.2.2 使用Ansible执行批量命令
$ sudo dnf install -y ansible
# 创建Ansible inventory文件
$ cat > inventory.ini << 'EOF'
[web]
192.168.1.101
192.168.1.102
[db]
192.168.1.103
192.168.1.104
[all:vars]
ansible_user=admin
ansible_ssh_private_key_file=~/.ssh/id_ed25519
EOF
# 测试连接
$ ansible all -i inventory.ini -m ping
192.168.1.101 | SUCCESS => {
“changed”: false,
“ping”: “pong”
}
192.168.1.102 | SUCCESS => {
“changed”: false,
“ping”: “pong”
}
…
# 批量执行命令
$ ansible all -i inventory.ini -a “uptime”
192.168.1.101 | CHANGED | rc=0 >>
08:10:00 up 1 day, 2:30, 1 user, load average: 0.00, 0.01, 0.05
192.168.1.102 | CHANGED | rc=0 >>
08:10:01 up 1 day, 2:31, 1 user, load average: 0.02, 0.03, 0.05
…
3.3 主机清单管理
$ cat > dynamic_inventory.py << 'EOF' #!/usr/bin/env python3 # dynamic_inventory.py # from:www.itpux.com.qq113257174.wx:itpux-com # web: `http://www.fgedu.net.cn` import json inventory = { "_meta": { "hostvars": {} }, "web": { "hosts": ["192.168.1.101", "192.168.1.102"] }, "db": { "hosts": ["192.168.1.103", "192.168.1.104"] }, "all": { "children": ["web", "db"] } } print(json.dumps(inventory, indent=2)) EOF # 赋予执行权限 $ chmod +x dynamic_inventory.py # 测试动态主机清单 $ ./dynamic_inventory.py { "_meta": { "hostvars": {} }, "web": { "hosts": ["192.168.1.101", "192.168.1.102"] }, "db": { "hosts": ["192.168.1.103", "192.168.1.104"] }, "all": { "children": ["web", "db"] } } # 使用动态主机清单执行命令 $ ansible all -i dynamic_inventory.py -a "free -m" 192.168.1.101 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 7950 1234 5678 34 1038 6543
Swap: 4096 0 4096
…
Part04-生产案例与实战讲解
4.1 大规模SSH免密登录设置案例
4.1.1 企业级SSH密钥管理
# 环境:100台服务器
# 目标:实现批量SSH免密登录
# 1. 生成主密钥对
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/enterprise_key -C “enterprise@fgedu.net.cn”
# 2. 创建主机清单
$ for i in {1..100}; do echo “192.168.1.$i”; done > hosts.txt
# 3. 创建批量分发脚本
$ cat > enterprise_ssh_setup.sh << 'EOF'
#!/bin/bash
# enterprise_ssh_setup.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: `http://www.fgedu.net.cn`
HOSTS_FILE="hosts.txt"
USER="admin"
KEY_FILE="~/.ssh/enterprise_key.pub"
# 批量分发密钥
while read host; do
echo "Setting up SSH for $host..."
# 使用Ansible分发密钥
ansible $host -m authorized_key -a "user=$USER key={{ lookup('file', '$KEY_FILE') }}"
done < $HOSTS_FILE
# 测试连接
echo "Testing connections..."
ansible all -i $HOSTS_FILE -m ping
EOF
# 4. 执行分发
$ ./enterprise_ssh_setup.sh
Setting up SSH for 192.168.1.1...
Setting up SSH for 192.168.1.2...
...
Testing connections...
192.168.1.1 | SUCCESS => {
“changed”: false,
“ping”: “pong”
}
192.168.1.2 | SUCCESS => {
“changed”: false,
“ping”: “pong”
}
…
4.2 批量部署与配置案例
4.2.1 批量部署Nginx
# 环境:10台web服务器
# 目标:批量安装和配置Nginx
# 1. 创建Ansible playbook
$ cat > deploy_nginx.yml << 'EOF'
---
- hosts: web
become: yes
tasks:
- name: Install Nginx
dnf:
name: nginx
state: present
- name: Start and enable Nginx
service:
name: nginx
state: started
enabled: yes
- name: Create Nginx configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
EOF
# 2. 创建Nginx配置模板
$ cat > nginx.conf.j2 << 'EOF'
user nginx;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name {{ inventory_hostname }};
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
EOF
# 3. 执行部署
$ ansible-playbook -i inventory.ini deploy_nginx.yml
PLAY [web] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
TASK [Install Nginx] ************************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
TASK [Start and enable Nginx] ***************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
TASK [Create Nginx configuration] ***********************************************
changed: [192.168.1.101]
changed: [192.168.1.102]
RUNNING HANDLER [restart nginx] *************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
PLAY RECAP *********************************************************************
192.168.1.101 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.102 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4.3 批量监控与管理案例
4.3.1 批量部署监控代理
# 环境:所有服务器
# 目标:部署Prometheus Node Exporter
# 1. 创建Ansible playbook
$ cat > deploy_node_exporter.yml << 'EOF'
---
- hosts: all
become: yes
tasks:
- name: Download Node Exporter
get_url:
url: https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_expor学习交流加群风哥微信: itpux-comter-1.6.0.linux-amd64.tar.gz
dest: /tmp/node_exporter-1.6.0.linux-amd64.tar.gz
- name: Extract Node Exporter
unarchive:
src: /tmp/node_exporter-1.6.0.linux-amd64.tar.gz
dest: /tmp
remote_src: yes
- name: Copy Node Exporter binary
copy:
src: /tmp/node_exporter-1.6.0.linux-amd64/node_exporter
dest: /usr/local/bin/node_exporter
mode: '0755'
- name: Create Node Exporter service
copy:
content: |
[Unit]
Description=Node Exporter
After=network.target
[Service]
Type=simple
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/node_exporter.service
- name: Create node_exporter user
user:
name: node_exporter
system: yes
shell: /bin/false
- name: Start and enable Node Exporter
systemd:
name: node_exporter
state: started
enabled: yes
daemon_reload: yes
EOF
# 2. 执行部署
$ ansible-playbook -i inventory.ini deploy_node_exporter.yml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Download Node Exporter] **************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Extract Node Exporter] ****************************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Copy Node Exporter binary] ***********************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Create Node Exporter service] ********************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Create node_exporter user] ***********************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
TASK [Start and enable Node Exporter] *******************************************
ok: [192.168.1.101]
ok: [192.168.1.102]
ok: [192.168.1.103]
ok: [192.168.1.104]
PLAY RECAP *********************************************************************
192.168.1.101 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.102 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.103 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.1.104 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Part05-风哥经验总结与分享
5.1 SSH批量管理最佳实践
SSH批量管理最佳实践:
- 使用密钥认证:禁用密码认证,使用SSH密钥
- 集中管理密钥:使用密钥管理系统,定期轮换密钥
- 使用跳板机:统一入口,加强安全控制
- 自动化管理:使用Ansible等工具自动化配置和管理
- 监控与审计:记录SSH登录和命令执行,检测异常行为
- 权限最小化:使用最小权限原则,限制用户访问范围
- 网络隔离:使用防火墙和网络策略,限制SSH访问
- 定期备份:备份SSH配置和密钥,防止丢失
5.2 常见问题与解决方案
## 1. SSH连接缓慢
– 原因:DNS解析问题、GSSAPI认证、反向DNS查找
– 解决方案:在sshd_config中设置UseDNS no,GSSAPIAuthentication no
## 2. 密钥认证失败
– 原因:权限问题、密钥格式错误、selinux问题
– 解决方案:检查文件权限(~/.ssh/目录700,authorized_keys 600),检查密钥格式,关闭selinux或调整上下文
## 3. 批量命令执行超时
– 原因:网络问题、服务器负载高、命令执行时间长
– 解决方案:增加超时时间,优化命令,使用异步执行
## 4. 密钥泄露
– 原因:私钥文件权限不当、员工离职未撤销密钥
– 解决方案:严格控制私钥权限,定期轮换密钥,员工离职立即撤销
## 5. 批量管理工具性能问题
– 原因:服务器数量过多、网络带宽不足、工具配置不当
– 解决方案:增加并发数,优化网络,使用更高效的工具
5.3 工具推荐与使用技巧
推荐SSH批量管理工具与使用技巧:
- Ansible:功能强大的自动化工具,支持配置管理和批量执行
- pssh:轻量级并行SSH工具,适合简单的批量命令执行
- SaltStack:高性能配置管理和远程执行工具
- Fabric:Python库,适合复杂的部署和管理任务
- ClusterSSH:图形化工具,适合同时管理多个SSH会话
- OpenSSH:内置工具,支持SSH密钥管理和配置
风哥提示:
风哥提示:
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
