ssh 命令详解#
ssh(Secure Shell)是 Linux 系统中用于安全远程登录和执行命令的协议和工具,是系统管理员和开发人员最常用的网络工具之一。它提供了加密的通信通道,确保数据传输的安全性。
入门#
基本用法#
# 远程登录到服务器
ssh user@hostname
# 使用 IP 地址登录
ssh user@192.168.1.100
# 指定端口登录
ssh -p 2222 user@hostname
# 执行远程命令
ssh user@hostname "command"
# 使用私钥登录
ssh -i /path/to/private_key user@hostname常用选项#
| 选项 | 说明 |
|---|---|
-p | 指定端口号 |
-i | 指定私钥文件 |
-l | 指定登录用户名 |
-v | 显示详细输出(调试模式) |
-q | 静默模式 |
-C | 启用压缩 |
-X | 启用 X11 转发 |
-L | 本地端口转发 |
-R | 远程端口转发 |
-D | 动态端口转发(SOCKS 代理) |
基本示例#
# 登录到远程服务器
ssh root@server.example.com
# 使用特定端口登录
ssh -p 2222 user@server.example.com
# 执行远程命令
ssh user@server.example.com "ls -la /tmp"
# 使用私钥登录
ssh -i ~/.ssh/id_rsa user@server.example.com中级#
SSH 密钥管理#
# 生成 SSH 密钥对
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 生成 ED25519 密钥(推荐)
ssh-keygen -t ed25519 -C "your_email@example.com"
# 查看公钥内容
cat ~/.ssh/id_rsa.pub
# 复制公钥到远程服务器
ssh-copy-id user@hostname
# 手动复制公钥
ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub
# 查看已保存的指纹
ssh-keygen -l -f ~/.ssh/known_hostsSSH 配置文件#
# 编辑 SSH 配置文件
nano ~/.ssh/config
# 配置示例:
# Host server1
# HostName server1.example.com
# User admin
# Port 2222
# IdentityFile ~/.ssh/id_rsa_server1
#
# Host server2
# HostName 192.168.1.100
# User user
# Port 22
# 使用配置文件登录
ssh server1
# 测试配置文件
ssh -F ~/.ssh/config server1端口转发#
# 本地端口转发(将远程端口映射到本地)
ssh -L 8080:localhost:80 user@remote_host
# 远程端口转发(将本地端口映射到远程)
ssh -R 8080:localhost:80 user@remote_host
# 动态端口转发(SOCKS 代理)
ssh -D 1080 user@remote_host
# 绑定到所有接口
ssh -g -L 8080:localhost:80 user@remote_host
# 转发到其他主机
ssh -L 8080:internal_host:80 user@remote_host高级#
SSH 隧道和代理#
# 创建 SSH 隧道访问内网服务
ssh -L 3306:internal_db:3306 user@jump_server
# 通过 SSH 隧道访问 Web 服务
ssh -L 8080:localhost:80 user@remote_host
# 使用 SSH 作为 SOCKS 代理
ssh -D 1080 -N user@remote_host
# 配置浏览器使用 SOCKS 代理
# 代理地址: localhost:1080
# 代理类型: SOCKS5
# 反向隧道(让远程服务器访问本地服务)
ssh -R 8080:localhost:80 user@remote_hostSSH 会话管理#
# 启动 SSH 会话并保持后台运行
ssh -f -N user@hostname
# 使用 autossh 自动重连
autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" user@hostname
# 使用 tmux/screen 保持会话
ssh user@hostname "tmux new -s session_name"
# 附加到现有会话
ssh user@hostname "tmux attach -t session_name"
# 使用 ControlMaster 复用连接
# 在 ~/.ssh/config 中添加:
# ControlMaster auto
# ControlPath ~/.ssh/cm-%r@%h:%p
# ControlPersist 10mSSH 安全配置#
# 编辑服务器 SSH 配置
sudo nano /etc/ssh/sshd_config
# 推荐配置:
# Port 2222 # 更改默认端口
# PermitRootLogin no # 禁止 root 登录
# PasswordAuthentication no # 禁用密码认证
# PubkeyAuthentication yes # 启用公钥认证
# AllowUsers user1 user2 # 限制允许的用户
# ClientAliveInterval 300 # 客户端存活间隔
# ClientAliveCountMax 2 # 最大存活次数
# 重启 SSH 服务
sudo systemctl restart sshd
# 限制登录尝试次数
sudo nano /etc/ssh/sshd_config
# MaxAuthTries 3
# 使用 fail2ban 防止暴力破解
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban大师#
SSH 批量管理#
#!/bin/bash
# SSH 批量管理脚本
SERVERS=("server1.example.com" "server2.example.com" "server3.example.com")
COMMAND="uptime"
# 在所有服务器上执行命令
for SERVER in "${SERVERS[@]}"; do
echo "=== $SERVER ==="
ssh user@$SERVER "$COMMAND"
echo ""
done
# 批量上传文件
for SERVER in "${SERVERS[@]}"; do
echo "Uploading to $SERVER..."
scp local_file user@$SERVER:/remote/path/
done
# 批量下载文件
for SERVER in "${SERVERS[@]}"; do
echo "Downloading from $SERVER..."
scp user@$SERVER:/remote/path/file local_path/
doneSSH 自动化脚本#
#!/bin/bash
# SSH 自动化部署脚本
SERVER="user@server.example.com"
APP_DIR="/var/www/myapp"
BACKUP_DIR="/var/backups/myapp"
# 远程备份
backup_remote() {
ssh $SERVER "mkdir -p $BACKUP_DIR && tar -czf $BACKUP_DIR/backup_$(date +%Y%m%d_%H%M%S).tar.gz -C $APP_DIR ."
echo "Backup completed"
}
# 远程部署
deploy_remote() {
echo "Deploying to $SERVER..."
# 上传文件
scp -r ./dist/* $SERVER:$APP_DIR/
# 执行远程命令
ssh $SERVER "cd $APP_DIR && npm install && pm2 restart myapp"
echo "Deployment completed"
}
# 远程监控
monitor_remote() {
while true; do
ssh $SERVER "pm2 status"
sleep 10
done
}
case "$1" in
backup)
backup_remote
;;
deploy)
deploy_remote
;;
monitor)
monitor_remote
;;
*)
echo "Usage: $0 {backup|deploy|monitor}"
exit 1
;;
esacSSH 密钥轮换#
#!/bin/bash
# SSH 密钥轮换脚本
OLD_KEY="$HOME/.ssh/id_rsa_old"
NEW_KEY="$HOME/.ssh/id_rsa_new"
SERVERS=("server1.example.com" "server2.example.com")
# 生成新密钥
generate_new_key() {
echo "Generating new SSH key..."
ssh-keygen -t ed25519 -f $NEW_KEY -N "" -C "new_key_$(date +%Y%m%d)"
echo "New key generated"
}
# 分发新密钥
distribute_new_key() {
echo "Distributing new key to servers..."
for SERVER in "${SERVERS[@]}"; do
echo "Adding new key to $SERVER..."
ssh-copy-id -i ${NEW_KEY}.pub user@$SERVER
done
}
# 测试新密钥
test_new_key() {
echo "Testing new key..."
for SERVER in "${SERVERS[@]}"; do
if ssh -i $NEW_KEY -o PasswordAuthentication=no user@$SERVER "echo 'Success'" > /dev/null 2>&1; then
echo "✓ New key works on $SERVER"
else
echo "✗ New key failed on $SERVER"
return 1
fi
done
}
# 移除旧密钥
remove_old_key() {
echo "Removing old key from servers..."
for SERVER in "${SERVERS[@]}"; do
echo "Removing old key from $SERVER..."
ssh user@$SERVER "sed -i '/$(cat ${OLD_KEY}.pub | awk '{print $2}')/d' ~/.ssh/authorized_keys"
done
}
# 主函数
main() {
generate_new_key
distribute_new_key
if test_new_key; then
read -p "Remove old key? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
remove_old_key
fi
else
echo "Key rotation failed. Old key still active."
fi
}
main无敌#
企业级 SSH 管理系统#
#!/bin/bash
# 企业级 SSH 管理系统
CONFIG_FILE="/etc/ssh_manager/config.conf"
LOG_FILE="/var/log/ssh_manager.log"
KEY_DIR="/etc/ssh_manager/keys"
SERVER_DB="/etc/ssh_manager/servers.db"
mkdir -p $KEY_DIR
# 初始化服务器数据库
init_server_db() {
if [ ! -f "$SERVER_DB" ]; then
echo "hostname,user,port,key_file" > $SERVER_DB
echo "server1.example.com,admin,22,id_rsa_server1" >> $SERVER_DB
echo "server2.example.com,admin,2222,id_rsa_server2" >> $SERVER_DB
echo "Server database initialized"
fi
}
# 添加服务器
add_server() {
local hostname=$1
local user=$2
local port=$3
local key_name=$4
echo "$hostname,$user,$port,$key_name" >> $SERVER_DB
echo "Server $hostname added"
}
# 列出所有服务器
list_servers() {
echo "=== Server List ==="
tail -n +2 $SERVER_DB | while IFS=, read -r hostname user port key_file; do
echo "Host: $hostname, User: $user, Port: $port, Key: $key_file"
done
}
# 在所有服务器上执行命令
execute_on_all() {
local command=$1
tail -n +2 $SERVER_DB | while IFS=, read -r hostname user port key_file; do
echo "=== $hostname ==="
ssh -p $port -i $KEY_DIR/$key_file $user@$hostname "$command"
echo ""
done
}
# 批量部署
batch_deploy() {
local source_dir=$1
local target_dir=$2
tail -n +2 $SERVER_DB | while IFS=, read -r hostname user port key_file; do
echo "Deploying to $hostname..."
scp -P $port -i $KEY_DIR/$key_file -r $source_dir/* $user@$hostname:$target_dir/
ssh -p $port -i $KEY_DIR/$key_file $user@$hostname "cd $target_dir && ./deploy.sh"
done
}
# 生成管理报告
generate_report() {
local report_file="/tmp/ssh_report_$(date +%Y%m%d_%H%M%S).txt"
echo "SSH Management Report - $(date)" > $report_file
echo "============================" >> $report_file
echo "" >> $report_file
echo "Server Status:" >> $report_file
tail -n +2 $SERVER_DB | while IFS=, read -r hostname user port key_file; do
if ssh -p $port -i $KEY_DIR/$key_file -o ConnectTimeout=5 $user@$hostname "echo 'OK'" > /dev/null 2>&1; then
echo "✓ $hostname - Online" >> $report_file
else
echo "✗ $hostname - Offline" >> $report_file
fi
done
echo "" >> $report_file
echo "Report saved to: $report_file"
}
# 主函数
main() {
init_server_db
case "$1" in
add)
add_server "$2" "$3" "$4" "$5"
;;
list)
list_servers
;;
exec)
execute_on_all "$2"
;;
deploy)
batch_deploy "$2" "$3"
;;
report)
generate_report
;;
*)
echo "Usage: $0 {add|list|exec|deploy|report}"
exit 1
;;
esac
}
main "$@"SSH 审计和监控#
#!/bin/bash
# SSH 审计和监控系统
AUTH_LOG="/var/log/auth.log"
AUDIT_REPORT="/var/log/ssh_audit_$(date +%Y%m%d).log"
# 分析 SSH 登录尝试
analyze_login_attempts() {
echo "=== SSH Login Analysis ===" >> $AUDIT_REPORT
echo "Date: $(date)" >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
# 成功登录
echo "Successful Logins:" >> $AUDIT_REPORT
grep "Accepted" $AUTH_LOG | tail -20 >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
# 失败登录
echo "Failed Login Attempts:" >> $AUDIT_REPORT
grep "Failed" $AUTH_LOG | tail -20 >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
# 按用户统计
echo "Logins by User:" >> $AUDIT_REPORT
grep "Accepted" $AUTH_LOG | awk '{print $9}' | sort | uniq -c | sort -rn >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
# 按IP统计
echo "Logins by IP:" >> $AUDIT_REPORT
grep "Accepted" $AUTH_LOG | awk '{print $11}' | sort | uniq -c | sort -rn | head -10 >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
# 暴力破解检测
echo "Potential Brute Force Attacks:" >> $AUDIT_REPORT
grep "Failed" $AUTH_LOG | awk '{print $9}' | sort | uniq -c | sort -rn | head -10 >> $AUDIT_REPORT
}
# 监控活跃 SSH 会话
monitor_active_sessions() {
echo "=== Active SSH Sessions ===" >> $AUDIT_REPORT
who >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
echo "SSH Processes:" >> $AUDIT_REPORT
ps aux | grep sshd | grep -v grep >> $AUDIT_REPORT
echo "" >> $AUDIT_REPORT
}
# 检查 SSH 配置安全性
check_ssh_config() {
echo "=== SSH Configuration Security Check ===" >> $AUDIT_REPORT
CONFIG_FILE="/etc/ssh/sshd_config"
if [ -f "$CONFIG_FILE" ]; then
echo "Checking $CONFIG_FILE..." >> $AUDIT_REPORT
# 检查 root 登录
if grep -q "^PermitRootLogin yes" $CONFIG_FILE; then
echo "⚠ WARNING: Root login is enabled" >> $AUDIT_REPORT
else
echo "✓ Root login is disabled" >> $AUDIT_REPORT
fi
# 检查密码认证
if grep -q "^PasswordAuthentication yes" $CONFIG_FILE; then
echo "⚠ WARNING: Password authentication is enabled" >> $AUDIT_REPORT
else
echo "✓ Password authentication is disabled" >> $AUDIT_REPORT
fi
# 检查默认端口
if grep -q "^Port 22" $CONFIG_FILE; then
echo "⚠ WARNING: Default port 22 is in use" >> $AUDIT_REPORT
else
echo "✓ Non-default port is configured" >> $AUDIT_REPORT
fi
fi
}
# 生成安全报告
generate_security_report() {
analyze_login_attempts
monitor_active_sessions
check_ssh_config
echo "Security report generated: $AUDIT_REPORT"
}
# 实时监控
realtime_monitor() {
echo "Starting real-time SSH monitoring..."
tail -f $AUTH_LOG | grep --line-buffered -E "Accepted|Failed" | while read line; do
echo "$(date '+%Y-%m-%d %H:%M:%S') - $line"
done
}
# 主函数
main() {
case "$1" in
audit)
generate_security_report
;;
monitor)
realtime_monitor
;;
*)
echo "Usage: $0 {audit|monitor}"
exit 1
;;
esac
}
main "$@"SSH 灾难恢复系统#
#!/bin/bash
# SSH 灾难恢复系统
BACKUP_DIR="/var/backups/ssh_recovery"
RECOVERY_LOG="/var/log/ssh_recovery.log"
# 备份 SSH 配置和密钥
backup_ssh_config() {
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="$BACKUP_DIR/ssh_backup_$timestamp.tar.gz"
mkdir -p $BACKUP_DIR
echo "Backing up SSH configuration..."
tar -czf $backup_file \
/etc/ssh/ \
~/.ssh/ \
/var/log/auth.log
echo "Backup created: $backup_file"
}
# 恢复 SSH 配置
restore_ssh_config() {
local backup_file=$1
if [ ! -f "$backup_file" ]; then
echo "Backup file not found: $backup_file"
return 1
fi
echo "Restoring SSH configuration from $backup_file..."
# 停止 SSH 服务
sudo systemctl stop sshd
# 恢复文件
sudo tar -xzf $backup_file -C /
# 重启 SSH 服务
sudo systemctl start sshd
echo "SSH configuration restored"
}
# 紧急访问设置
setup_emergency_access() {
echo "Setting up emergency access..."
# 创建临时密钥
local emergency_key="$HOME/.ssh/emergency_key"
ssh-keygen -t ed25519 -f $emergency_key -N "" -C "emergency_$(date +%Y%m%d)"
# 添加到 authorized_keys
cat ${emergency_key}.pub >> ~/.ssh/authorized_keys
echo "Emergency access configured"
echo "Private key: $emergency_key"
echo "Remember to remove this key after emergency!"
}
# 测试 SSH 连接
test_ssh_connection() {
local server=$1
echo "Testing SSH connection to $server..."
if ssh -o ConnectTimeout=5 -o BatchMode=yes $server "echo 'Connection successful'" > /dev/null 2>&1; then
echo "✓ SSH connection successful"
return 0
else
echo "✗ SSH connection failed"
return 1
fi
}
# 自动恢复
auto_recovery() {
local server=$1
echo "Attempting automatic recovery for $server..."
# 尝试使用备用密钥
if [ -f "$HOME/.ssh/emergency_key" ]; then
echo "Trying emergency key..."
if ssh -i $HOME/.ssh/emergency_key $server "echo 'Success'" > /dev/null 2>&1; then
echo "Emergency access successful"
return 0
fi
fi
# 尝试恢复配置
local latest_backup=$(ls -t $BACKUP_DIR/ssh_backup_*.tar.gz | head -1)
if [ -n "$latest_backup" ]; then
echo "Restoring from latest backup..."
restore_ssh_config $latest_backup
test_ssh_connection $server
fi
}
# 主函数
main() {
case "$1" in
backup)
backup_ssh_config
;;
restore)
restore_ssh_config "$2"
;;
emergency)
setup_emergency_access
;;
test)
test_ssh_connection "$2"
;;
recover)
auto_recovery "$2"
;;
*)
echo "Usage: $0 {backup|restore|emergency|test|recover}"
exit 1
;;
esac
}
main "$@"最佳实践#
- 使用密钥认证:优先使用 SSH 密钥而非密码认证
- 禁用 root 登录:禁止直接使用 root 账户登录
- 更改默认端口:使用非标准端口减少攻击面
- 定期更新密钥:定期轮换 SSH 密钥
- 使用配置文件:使用
~/.ssh/config简化连接管理 - 启用日志审计:记录和监控 SSH 登录活动
- 使用 fail2ban:防止暴力破解攻击
- 限制访问:使用防火墙和
AllowUsers限制访问
注意事项#
- SSH 私钥必须妥善保管,不要泄露给他人
- 在生产环境操作前先在测试环境验证
- 修改 SSH 配置后确保能正常登录再断开连接
- 使用
-v选项调试连接问题时注意保护敏感信息 - 端口转发可能带来安全风险,谨慎使用
- 定期检查
~/.ssh/known_hosts文件 - 注意 SSH 协议版本,优先使用 SSH-2
- 在自动化脚本中使用 SSH 时考虑错误处理