前言:SSH,远程服务器管理的核心

SSH(Secure Shell)是通过网络安全连接和管理远程服务器的协议。它通过加密通信保护数据,是现代服务器运维中最重要的工具之一。本篇将从SSH基础到高级用法全面讲解。

1. SSH基础

1.1 SSH基本连接

# 基本连接
ssh username@hostname

# 指定端口连接
ssh -p 2222 username@hostname

# 通过IP地址连接
ssh user@192.168.1.100

# 详细调试模式
ssh -v username@hostname
ssh -vvv username@hostname  # 更详细信息

1.2 SSH服务器安装与状态检查

# Ubuntu/Debian
sudo apt update
sudo apt install openssh-server

# RHEL/CentOS
sudo dnf install openssh-server

# 检查SSH服务器状态
sudo systemctl status sshd

# 启动/停止/重启服务
sudo systemctl start sshd
sudo systemctl stop sshd
sudo systemctl restart sshd

# 开机自动启动
sudo systemctl enable sshd

1.3 断开SSH连接

# 正常退出
exit
logout
Ctrl + D

# 会话卡住时强制断开
~.    # 按Enter后输入~.

2. SSH密钥认证

2.1 生成密钥对

# 生成RSA密钥(默认)
ssh-keygen -t rsa -b 4096

# 生成Ed25519密钥(推荐,更安全更快)
ssh-keygen -t ed25519

# 指定文件名生成
ssh-keygen -t ed25519 -f ~/.ssh/myserver_key

# 添加注释
ssh-keygen -t ed25519 -C "admin@company.com"

# 查看生成的文件
ls -la ~/.ssh/
# id_ed25519      - 私钥(绝不分享)
# id_ed25519.pub  - 公钥(注册到服务器)

2.2 将公钥注册到服务器

# 使用ssh-copy-id(最简单的方法)
ssh-copy-id username@hostname
ssh-copy-id -i ~/.ssh/myserver_key.pub username@hostname

# 手动注册
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 或在服务器上直接操作
# 将公钥内容添加到~/.ssh/authorized_keys文件

# 权限设置(重要!)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

2.3 密钥认证连接

# 使用默认密钥连接
ssh username@hostname

# 指定特定密钥
ssh -i ~/.ssh/myserver_key username@hostname

# 避免输入密码短语(ssh-agent)
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
ssh-add -l  # 查看已注册的密钥

3. SSH配置文件

3.1 客户端配置(~/.ssh/config)

# ~/.ssh/config 示例
# Web服务器
Host webserver
    HostName 192.168.1.10
    User admin
    Port 22
    IdentityFile ~/.ssh/webserver_key

# 开发服务器(使用别名)
Host dev
    HostName dev.company.com
    User developer
    Port 2222

# DB服务器(通过跳板机)
Host dbserver
    HostName 10.0.0.50
    User dbadmin
    ProxyJump webserver

# 所有主机通用设置
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes

# 现在可以简单连接
# ssh webserver
# ssh dev

3.2 服务器配置(/etc/ssh/sshd_config)

# 主要安全设置
# 更改端口
Port 2222

# 禁用root登录
PermitRootLogin no

# 禁用密码认证(仅允许密钥认证)
PasswordAuthentication no

# 禁止空密码
PermitEmptyPasswords no

# 仅允许特定用户
AllowUsers admin deploy

# 仅允许特定组
AllowGroups sshusers

# 限制登录尝试
MaxAuthTries 3

# 最大会话数
MaxSessions 5

# 禁用X11转发
X11Forwarding no

# 应用设置
sudo sshd -t  # 语法检查
sudo systemctl restart sshd

4. 文件传输:SCP和SFTP

4.1 SCP(安全复制)

# 本地 → 远程(文件)
scp file.txt user@host:/path/to/destination/

# 本地 → 远程(目录)
scp -r mydir/ user@host:/path/to/destination/

# 远程 → 本地
scp user@host:/path/to/file.txt ./local/

# 使用其他端口
scp -P 2222 file.txt user@host:/path/

# 使用特定密钥
scp -i ~/.ssh/mykey file.txt user@host:/path/

# 压缩传输(适用于大文件)
scp -C largefile.zip user@host:/path/

# 带宽限制(KB/s)
scp -l 1000 file.txt user@host:/path/

# 服务器间传输
scp user1@host1:/file.txt user2@host2:/path/

4.2 SFTP(SSH文件传输协议)

# SFTP连接
sftp user@host
sftp -P 2222 user@host

# SFTP命令
sftp> pwd           # 远程当前目录
sftp> lpwd          # 本地当前目录
sftp> ls            # 远程文件列表
sftp> lls           # 本地文件列表
sftp> cd /path      # 切换远程目录
sftp> lcd /path     # 切换本地目录
sftp> get file.txt  # 下载
sftp> get -r dir/   # 下载目录
sftp> put file.txt  # 上传
sftp> put -r dir/   # 上传目录
sftp> rm file.txt   # 删除
sftp> mkdir newdir  # 创建目录
sftp> exit          # 退出

4.3 rsync over SSH

# 基本同步
rsync -avz source/ user@host:/destination/

# 同步已删除的文件
rsync -avz --delete source/ user@host:/destination/

# 使用其他端口
rsync -avz -e "ssh -p 2222" source/ user@host:/dest/

# 显示进度
rsync -avz --progress source/ user@host:/dest/

# 测试运行(dry-run)
rsync -avzn source/ user@host:/dest/

5. SSH隧道(端口转发)

5.1 本地端口转发

将本地机器的端口通过远程服务器连接到其他服务器。

# 语法:ssh -L [本地端口]:[目标主机]:[目标端口] [SSH服务器]

# 示例:通过本地3306连接远程DB服务器
ssh -L 3306:localhost:3306 user@sshserver

# 示例:访问远程服务器后面的其他服务器
ssh -L 8080:internal-web.lan:80 user@sshserver

# 后台运行
ssh -fNL 3306:localhost:3306 user@sshserver

# 现在可以通过localhost:3306连接DB
mysql -h localhost -P 3306 -u dbuser -p

5.2 远程端口转发

将远程服务器的端口连接到本地机器。

# 语法:ssh -R [远程端口]:[本地主机]:[本地端口] [SSH服务器]

# 示例:将远程服务器的8080转发到本地的80
ssh -R 8080:localhost:80 user@sshserver

# 从外部访问远程服务器的8080时转发到本地80

# 后台运行
ssh -fNR 8080:localhost:80 user@sshserver

5.3 动态端口转发(SOCKS代理)

# 创建SOCKS代理
ssh -D 1080 user@sshserver

# 后台运行
ssh -fND 1080 user@sshserver

# 在浏览器或应用程序中配置SOCKS5代理
# 代理:localhost:1080

5.4 跳板主机(代理跳转)

# 使用-J选项(OpenSSH 7.3+)
ssh -J jumphost user@targetserver

# 多个跳板主机
ssh -J jump1,jump2 user@target

# 旧方法(-o ProxyCommand)
ssh -o ProxyCommand="ssh -W %h:%p jumphost" user@target

# 在~/.ssh/config中配置
Host internal
    HostName 10.0.0.50
    User admin
    ProxyJump jumphost

6. SSH安全加固

6.1 sshd_config安全设置

# /etc/ssh/sshd_config

# 禁用密码认证(仅允许密钥)
PasswordAuthentication no
ChallengeResponseAuthentication no

# 禁止root登录
PermitRootLogin no

# 禁止空密码
PermitEmptyPasswords no

# 禁用键盘交互认证
KbdInteractiveAuthentication no

# 仅允许协议版本2(默认)
Protocol 2

# 限制登录尝试
MaxAuthTries 3
LoginGraceTime 30

# 仅允许特定IP连接(sshd_config或防火墙)
# AllowUsers admin@192.168.1.0/24

# 限制TCP转发
AllowTcpForwarding no
AllowAgentForwarding no

# 仅允许强加密算法
Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# 应用前语法检查
sudo sshd -t
sudo systemctl restart sshd

6.2 安装Fail2Ban

# Ubuntu/Debian
sudo apt install fail2ban

# RHEL/CentOS
sudo dnf install fail2ban

# 创建配置文件
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# 编辑/etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log   # Debian/Ubuntu
# logpath = /var/log/secure   # RHEL/CentOS
maxretry = 3
bantime = 3600
findtime = 600

# 启动服务
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# 检查状态
sudo fail2ban-client status sshd

6.3 双因素认证(2FA)

# 安装Google Authenticator
sudo apt install libpam-google-authenticator

# 初始化设置
google-authenticator

# PAM配置(/etc/pam.d/sshd)
auth required pam_google_authenticator.so

# sshd_config设置
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

# 重启服务
sudo systemctl restart sshd

7. SSH代理和密钥管理

7.1 使用SSH代理

# 启动代理
eval $(ssh-agent)

# 添加密钥
ssh-add                      # 默认密钥
ssh-add ~/.ssh/mykey        # 特定密钥
ssh-add -t 3600 ~/.ssh/key  # 1小时后自动删除

# 查看已注册的密钥
ssh-add -l

# 删除密钥
ssh-add -d ~/.ssh/mykey     # 特定密钥
ssh-add -D                  # 所有密钥

# 终止代理
ssh-agent -k

7.2 SSH代理转发

# 使用-A选项进行代理转发
ssh -A user@server1

# 现在可以从server1使用本地密钥连接其他服务器
ssh user@server2

# 在~/.ssh/config中配置
Host server1
    ForwardAgent yes

# 注意:仅在可信服务器上使用

7.3 密钥管理最佳实践

# 按用途分离密钥
ssh-keygen -t ed25519 -f ~/.ssh/work_key -C "work"
ssh-keygen -t ed25519 -f ~/.ssh/personal_key -C "personal"

# 设置强密码短语
ssh-keygen -t ed25519 -f ~/.ssh/mykey
# (交互式输入密码短语)

# 检查密钥权限
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
chmod 700 ~/.ssh

# 更换旧密钥
# 1. 生成新密钥
# 2. 在服务器上注册新密钥
# 3. 测试
# 4. 删除旧密钥

8. 远程服务器管理技巧

8.1 会话保持(keepalive)

# 客户端配置(~/.ssh/config)
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

# 服务器配置(/etc/ssh/sshd_config)
ClientAliveInterval 60
ClientAliveCountMax 3

8.2 与tmux/screen配合使用

# 创建tmux会话
tmux new -s mysession

# 分离会话(Ctrl+B, D)
# SSH连接断开后工作继续

# 重新连接后恢复会话
tmux attach -t mysession

# 列出会话
tmux ls

8.3 同时管理多台服务器

# 在多台服务器上执行相同命令
for server in server1 server2 server3; do
    ssh $server "uptime"
done

# 使用parallel-ssh
pssh -h hosts.txt -l user "uptime"

# 使用Ansible(推荐)
ansible all -m ping
ansible all -a "uptime"

8.4 SSH连接复用

# ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600

# 创建socket目录
mkdir -p ~/.ssh/sockets

# 首次连接后,后续连接更快

9. 故障排除

9.1 常见错误

# Permission denied (publickey)
# → 检查密钥权限
chmod 600 ~/.ssh/id_*
chmod 700 ~/.ssh

# Host key verification failed
# → 从known_hosts中删除该主机
ssh-keygen -R hostname

# Connection refused
# → 检查SSH服务器是否运行
sudo systemctl status sshd

# Connection timed out
# → 检查防火墙
sudo ufw status
sudo firewall-cmd --list-all

9.2 调试模式

# 客户端调试
ssh -v user@host    # 基本
ssh -vv user@host   # 详细
ssh -vvv user@host  # 非常详细

# 服务器调试(前台运行)
sudo /usr/sbin/sshd -d -p 2222

10. 实践:SSH安全检查清单

# 1. 设置密钥认证
ssh-keygen -t ed25519
ssh-copy-id user@server

# 2. 禁用密码认证
# /etc/ssh/sshd_config
PasswordAuthentication no

# 3. 禁止root登录
PermitRootLogin no

# 4. 更改端口(可选)
Port 2222

# 5. 配置防火墙
sudo ufw allow 2222/tcp
sudo ufw enable

# 6. 安装Fail2Ban
sudo apt install fail2ban

# 7. 应用设置
sudo sshd -t && sudo systemctl restart sshd

# 8. 测试
ssh -p 2222 user@server

总结

SSH是远程服务器管理的核心工具。使用密钥认证、应用适当的安全设置、利用隧道功能,可以实现安全高效的服务器管理。下一篇我们将通过Shell脚本基础开始服务器管理自动化之旅。