SSH访问:安全远程服务器管理完整技术指南
SSH(安全外壳协议)是一种加密网络协议,可在两台联网主机之间建立加密隧道,支持在不受信任的网络上进行经过身份验证的命令执行、文件传输和端口转发。默认情况下,它运行在TCP端口22上,并以提供机密性、完整性和单次握手中双向身份验证的协议取代了明文前身——Telnet、rsh和FTP。
对于任何管理VPS或独立服务器的管理员而言,SSH不是可选的基础设施——它是主要的控制平面。您围绕SSH做出的每一个配置决策都会直接影响服务器的攻击面、运营可靠性和合规状态。
SSH的工作原理:协议架构
在协议层面理解SSH,是能够正确配置它的管理员与留下可利用漏洞的管理员之间的本质区别。
三层模型
SSH由RFC 4251–4254定义,在TCP之上运行三个不同的子层:
- SSH传输层协议——处理服务器身份验证、密钥交换、加密协商和MAC(消息认证码)设置。这是发生加密握手的层。
- SSH用户认证协议——运行在传输层之上,使用
publickey、password、keyboard-interactive或gssapi-with-mic等方法处理客户端到服务器的身份验证。 - SSH连接协议——将加密隧道多路复用为逻辑通道,每个通道承载一个shell会话、SFTP子系统、转发端口或代理连接。
握手详解
当您运行ssh user@host时,在看到提示符之前会执行以下序列:
- 建立到服务器配置端口的TCP连接。
- 版本交换——客户端和服务器交换协议版本字符串(
SSH-2.0-OpenSSH_9.x)。 - 算法协商(
SSH_MSG_KEXINIT)——双方通告支持的密钥交换算法、主机密钥类型、密码、MAC和压缩方法。每个列表中第一个双方都支持的选项胜出。 - 密钥交换(KEX)——通常为Diffie-Hellman或椭圆曲线Diffie-Hellman(ECDH)。双方在不传输共享密钥的情况下推导出共享密钥,从而生成会话密钥。
- 服务器主机密钥验证——服务器使用其私有主机密钥对某个值进行签名。客户端根据其
~/.ssh/known_hosts文件检查此签名。不匹配将触发警告,并默认阻止连接。 - 加密激活——所有后续流量均使用协商的密码(例如
chacha20-poly1305)和MAC进行加密和完整性保护。 - 用户认证——客户端使用协商的方法尝试身份验证。使用
publickey认证时,客户端用其私钥对挑战进行签名;服务器使用存储的公钥进行验证。 - 通道打开——打开shell、SFTP子系统或exec通道,会话开始。
在本地网络上,整个过程通常在100毫秒内完成。
SSH中的对称与非对称密码学
一个常见的误解是SSH对所有流量”使用公钥加密”。事实并非如此。各角色是不同的:
| 密码学角色 | 算法类型 | 用途 |
|---|
| — | — | — |
|---|
| 密钥交换 | 非对称(ECDH、DH) | 在不传输的情况下推导共享会话密钥 |
|---|
| 会话加密 | 对称(AES-GCM、ChaCha20) | 高效加密批量数据 |
|---|
| 服务器身份验证 | 非对称(RSA、Ed25519、ECDSA) | 通过主机密钥签名证明服务器身份 |
|---|
| 客户端身份验证 | 非对称(RSA、Ed25519) | 通过密钥对挑战证明客户端身份 |
|---|
| 完整性验证 | HMAC(SHA-256、SHA-512)或AEAD | 检测加密数据包的篡改 |
|---|
SSH与传统远程访问协议对比
| 功能 | SSH | Telnet | FTP | RDP |
|---|
| — | — | — | — | — |
|---|
| 加密 | 完整(传输层+认证层) | 无 | 无(数据);可选TLS | TLS/RC4 |
|---|
| 身份验证 | 密码、密钥对、证书、GSSAPI | 密码(明文) | 密码(明文) | 密码、智能卡、NLA |
|---|
| 端口 | 22(可配置) | 23 | 21(控制),20(数据) | 3389 |
|---|
| 文件传输 | 内置SFTP、SCP | 否 | 是(不安全) | 剪贴板/驱动器重定向 |
|---|
| 端口转发 | 是(本地、远程、动态) | 否 | 否 | 有限 |
|---|
| MFA支持 | 是(通过PAM、TOTP) | 否 | 极少 | 是 |
|---|
| 防火墙穿透 | 单个TCP端口 | 单个TCP端口 | 需要被动模式配置 | 单个TCP端口 |
|---|
| 主要用途 | Linux/Unix服务器管理 | 传统系统 | 文件传输(传统) | Windows桌面/服务器 |
|---|
生成SSH密钥对
SSH密钥对是安全、可扩展服务器访问的基础。密码身份验证容易受到暴力破解攻击和凭证填充攻击;而基于密钥的身份验证则不会。
选择正确的密钥算法
Ed25519是当前的最佳实践。它使用Curve25519椭圆曲线密码学,生成紧凑的256位密钥,在同等安全级别下比RSA更快,并且受OpenSSH 6.5+(2014年发布)支持。
ssh-keygen -t ed25519 -C "admin@yourhost.example.com"仅在需要与不支持Ed25519的传统系统兼容时才使用RSA:
ssh-keygen -t rsa -b 4096 -C "admin@yourhost.example.com"不要使用DSA(限于1024位,已被破解)或使用NIST曲线的ECDSA(对NIST曲线参数来源存在疑虑)。Ed25519是新部署的明确选择。
密钥生成演练
ssh-keygen -t ed25519 -C "ops-team-key-2025"系统将提示您输入:
- 文件位置——默认为
~/.ssh/id_ed25519。接受默认值,或为多密钥环境指定自定义路径。 - 密码短语——务必设置。密码短语使用AES-256-CBC(或较新OpenSSH中的bcrypt)对静态私钥进行加密。如果您的私钥文件被盗,密码短语是最后一道防线。
这将生成两个文件:
~/.ssh/id_ed25519——私钥。切勿共享。权限必须为600。
~/.ssh/id_ed25519.pub——公钥。这是您分发到服务器的内容。
使用~/.ssh/config管理多个密钥
在管理多台服务器或账户时,使用SSH配置文件,避免在每次连接时指定标志:
# ~/.ssh/config
Host prod-web
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
Port 2222
Host staging
HostName 203.0.113.20
User ubuntu
IdentityFile ~/.ssh/id_ed25519_staging
配置完成后,ssh prod-web会自动扩展为完整的连接参数。
将公钥部署到服务器
方法一:ssh-copy-id(推荐用于初始设置)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your_server_ip
这会将公钥追加到远程主机的~/.ssh/authorized_keys,并自动设置正确的权限。
方法二:手动部署(当ssh-copy-id不可用时)
cat ~/.ssh/id_ed25519.pub | ssh user@your_server_ip
"mkdir -p ~/.ssh && chmod 700 ~/.ssh &&
cat >> ~/.ssh/authorized_keys &&
chmod 600 ~/.ssh/authorized_keys"
方法三:云服务商控制台或API
大多数云服务商和托管控制面板允许您在实例配置期间注入公钥。这是自动化基础设施的正确方法——密钥在实例启动之前就已存在,消除了需要SSH来部署SSH密钥的先有鸡还是先有蛋的问题。
authorized_keys文件格式
~/.ssh/authorized_keys中的每一行是一个公钥,可选择以选项为前缀:
restrict,command="/usr/local/bin/backup.sh" ssh-ed25519 AAAA... backup-key
from="192.168.1.0/24" ssh-ed25519 AAAA... ops-key
restrict选项禁用该密钥的端口转发、代理转发和PTY分配——适用于不应具有交互式shell访问权限的部署密钥或备份自动化账户。
加固SSH服务器:/etc/ssh/sshd_config
默认的OpenSSH安装是可用的,但未经加固。以下配置代表生产级基线。将更改应用于/etc/ssh/sshd_config,然后验证并重新加载:
sshd -t && systemctl reload sshd
在重新加载之前,务必运行sshd -t——sshd_config中的语法错误不会导致正在运行的守护进程崩溃,但会阻止其在重启后重新启动,从而将您锁定在外。
推荐的sshd_config加固配置块
# /etc/ssh/sshd_config - Production hardening baseline
Port 2222
AddressFamily inet
ListenAddress 0.0.0.0
# Host keys - prefer Ed25519
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# Cryptographic hardening
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Authentication
PermitRootLogin no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
# Session hardening
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 5
ClientAliveInterval 300
ClientAliveCountMax 2
TCPKeepAlive no
# Disable unused features
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
GatewayPorts no
# Restrict access
AllowUsers deploy ops-user
Banner /etc/ssh/banner.txt
关键加固决策说明
PermitRootLogin no——通过SSH进行root登录是高价值攻击目标。请使用普通用户并通过sudo提升权限。如果您确实需要通过特定密钥进行root级别访问(例如用于自动化),请使用PermitRootLogin prohibit-password,允许仅密钥的root登录,同时阻止密码尝试。
AllowTcpForwarding no——如果您的服务器不是堡垒机或跳板机,请禁用TCP转发。否则,拥有有效SSH会话的攻击者可以将您的服务器用作代理,访问内部网络资源。
TCPKeepAlive no与ClientAliveInterval——TCPKeepAlive在TCP层运行,对网络中间设备可见。ClientAliveInterval通过加密的SSH通道发送保活消息,既更可靠,也更私密。
LoginGraceTime 30——缩短未经身份验证的连接占用服务器槽位的时间窗口。默认的120秒过长。
AllowUsers——仅将合法需要SSH访问的账户列入白名单。这是一个在任何身份验证尝试之前生效的硬性门控。
更改默认SSH端口
将SSH从端口22迁移不会提高针对有针对性攻击者的安全性——任何端口扫描都能找到它。但它确实能消除大量专门针对端口22的自动化机会性暴力破解机器人。这能有效减少日志噪音和服务器负载。
# In /etc/ssh/sshd_config
Port 2222
在重新加载之前,在防火墙中开放新端口:
# UFW
ufw allow 2222/tcp
ufw delete allow 22/tcp
# firewalld
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --permanent --remove-service=ssh
firewall-cmd --reload
# iptables
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
iptables -D INPUT -p tcp --dport 22 -j ACCEPT
如果您的服务器运行SELinux,还必须更新SELinux端口上下文:
semanage port -a -t ssh_port_t -p tcp 2222
连接到服务器
基本连接
ssh user@your_server_ip
连接到非默认端口
ssh -p 2222 user@your_server_ip
使用特定密钥连接
ssh -i ~/.ssh/id_ed25519_prod user@your_server_ip
调试的详细模式
ssh -vvv user@your_server_ip
-vvv标志会打印握手、身份验证尝试和通道协商的每个步骤。当连接意外失败时,它是首选的排查工具。
通过SSH进行安全文件传输
SCP(安全复制协议)
SCP是一个简单的非交互式文件复制工具。它速度快且广泛可用,但没有断点续传功能,错误处理也有限。
将本地文件复制到远程服务器:
scp -P 2222 /local/path/file.tar.gz user@your_server_ip:/remote/path/
将远程文件复制到本地:
scp -P 2222 user@your_server_ip:/remote/path/file.tar.gz /local/path/
递归目录复制:
scp -rp -P 2222 /local/directory/ user@your_server_ip:/remote/directory/
注意:OpenSSH项目在OpenSSH 9.0中弃用了传统SCP协议。现代scp现在默认在底层使用SFTP协议。命令界面保持不变,但底层传输更加健壮。
SFTP(SSH文件传输协议)
SFTP是一个功能完整的文件传输子系统,支持目录列表、权限管理和断点续传。它是交互式文件管理的正确选择。
sftp -P 2222 user@your_server_ip
交互式会话中的常用SFTP命令:
sftp> ls -la # List remote directory
sftp> lls # List local directory
sftp> put localfile.txt /remote/path/ # Upload file
sftp> get /remote/file.txt ./ # Download file
sftp> mput *.log /remote/logs/ # Upload multiple files
sftp> mkdir /remote/newdir # Create remote directory
sftp> chmod 640 /remote/file.txt # Change remote permissions
sftp> bye # Exit
通过SSH使用rsync(生产环境推荐)
对于目录同步、增量备份或大型数据集,通过SSH使用rsync比SCP或SFTP效率高得多。它只传输已更改的块,而不是整个文件。
rsync -avz --progress -e "ssh -p 2222 -i ~/.ssh/id_ed25519"
/local/data/ user@your_server_ip:/remote/data/
-z标志启用传输中的压缩。对于已压缩的数据(归档文件、镜像),请省略它——对已压缩数据进行压缩会浪费CPU而不会减少传输大小。
SSH端口转发与隧道
端口转发是SSH最强大且最未被充分利用的功能之一。它允许您安全地访问未直接暴露于互联网的服务。
本地端口转发
将本地端口转发到远程服务。示例:访问绑定到服务器本地主机的远程MySQL实例(端口3306):
ssh -L 3307:127.0.0.1:3306 user@your_server_ip -N
现在,本地机器上的mysql -h 127.0.0.1 -P 3307通过加密隧道连接到远程MySQL。
远程端口转发
将本地服务暴露给远程服务器。适用于测试webhook或共享本地开发服务器:
ssh -R 8080:127.0.0.1:3000 user@your_server_ip -N
动态端口转发(SOCKS代理)
将SSH连接转换为SOCKS5代理,通过服务器路由任意TCP流量:
ssh -D 1080 user@your_server_ip -N
将您的浏览器或应用程序配置为使用SOCKS5 127.0.0.1:1080。
SSH代理与代理转发
ssh-agent将解密的私钥保存在内存中,这样您就不必在每次连接时重新输入密码短语。
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
代理转发(ssh -A)允许远程服务器使用您的本地代理向第三台服务器进行身份验证。这对堡垒机架构很有用,但存在风险:中间服务器上的root用户可以使用您转发的代理套接字。建议改用ProxyJump:
ssh -J bastion.example.com user@internal-server.example.com
ProxyJump通过堡垒机路由TCP连接,而不会将您的代理暴露给它。
排查常见SSH问题
连接被拒绝(ssh: connect to host ... port 22: Connection refused)
系统性诊断:
验证SSH守护进程是否正在运行:systemctl status sshdss -tlnp | grep sshdufw status或iptables -L -n | grep 22ping your_server_ip权限被拒绝(publickey)
这是最常见的SSH错误。请按照以下检查清单逐项排查:
# On the server, check authorized_keys permissions
ls -la ~/.ssh/
stat ~/.ssh/authorized_keys
# Fix permissions if wrong
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
# Verify the public key is actually present
cat ~/.ssh/authorized_keys
# Check sshd logs for the specific rejection reason
journalctl -u sshd -n 50 --no-pager
# or
tail -50 /var/log/auth.log除权限问题外的常见原因:
authorized_keys文件包含错误的密钥(例如,您复制了私钥而不是.pub文件)。
sshd_config中的StrictModes yes(默认值)会在主目录权限过于开放时拒绝连接——chmod 755 ~是允许的最大值。
sshd_config中的AllowUsers或AllowGroups排除了连接用户。
SELinux阻止访问~/.ssh/——检查ausearch -m avc -ts recent。
SSH连接超时
# In /etc/ssh/sshd_config (server side)
ClientAliveInterval 60
ClientAliveCountMax 3
# In ~/.ssh/config (client side)
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
ClientAliveInterval每60秒通过加密通道发送一个空数据包。在连续ClientAliveCountMax次未收到响应后,服务器终止连接。这可防止僵尸会话积累。
主机密钥验证失败
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
此警告意味着服务器的主机密钥与~/.ssh/known_hosts中存储的内容不再匹配。合法原因包括服务器重新安装或IP地址重新分配。恶意原因包括中间人攻击。在继续操作之前请进行调查。
如果您已确认服务器是合法重新安装的:
ssh-keygen -R your_server_ip
然后重新连接,并在接受之前根据服务器控制台或服务商仪表板验证新的主机密钥指纹。
SSH的多因素身份验证
基于密钥的身份验证很强大,但添加TOTP(基于时间的一次性密码)第二因素可以创建纵深防御。即使私钥及其密码短语被泄露,攻击者也无法在没有TOTP令牌的情况下进行身份验证。
在服务器上安装并配置libpam-google-authenticator:
apt install libpam-google-authenticator
google-authenticator
然后配置PAM和sshd_config:
# /etc/pam.d/sshd - add this line
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config
UsePAM yes
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
使用AuthenticationMethods publickey,keyboard-interactive,用户必须同时提供有效的密钥和TOTP代码。这是高价值服务器的正确生产配置。
SSH证书颁发机构:扩展密钥管理
在拥有数十台服务器和多名管理员的环境中,管理单独的authorized_keys条目在运营上变得难以为继。SSH证书解决了这个问题。
SSH证书颁发机构(CA)对用户和主机密钥进行签名。服务器信任CA的公钥,而不是单个用户密钥。添加新管理员只需对其公钥进行签名——无需更改任何服务器的authorized_keys文件。
# Create a CA key pair (store the private key offline or in a secrets manager)
ssh-keygen -t ed25519 -f /etc/ssh/ca_key -C "infrastructure-ca-2025"
# Sign a user's public key, valid for 7 days, for specific principals
ssh-keygen -s /etc/ssh/ca_key
-I "alice-ops-cert"
-n alice,deploy
-V +7d
~/.ssh/id_ed25519.pub
在每台服务器上,配置对CA的信任:
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub
这就是大规模基础设施(包括云服务商和企业)在无需逐服务器密钥管理的情况下管理SSH访问的方式。
实用决策矩阵:按用例划分的SSH配置
用例
密钥类型
端口
密码认证
Root登录
转发
MFA
—
—
—
—
—
—
—
个人VPS
Ed25519
2222+
禁用
禁止
禁用
可选
生产Web服务器
Ed25519
非默认
禁用
否
禁用
必需
堡垒机/跳板机
Ed25519
22或自定义
禁用
否
受控
必需
CI/CD自动化
Ed25519(部署密钥)
非默认
禁用
否
禁用
否(仅密钥)
数据库服务器
Ed25519
非默认
禁用
否
仅本地
必需
开发服务器
Ed25519
默认或自定义
可选
否
可选
可选
在AlexHost基础设施上设置SSH
当您通过AlexHost配置VPS或独立服务器时,SSH访问默认已配置。初始root密码通过配置邮件发送,建议的第一步操作是:
以root身份登录,创建非root管理用户,并将您的公钥添加到该用户的~/.ssh/authorized_keys。
应用上述记录的sshd_config加固基线。
禁用密码身份验证和root登录。
在运营可行的情况下,配置防火墙将SSH访问限制为已知IP范围。
如果您希望在SSH旁边使用图形化管理层,AlexHost的带cPanel的VPS和VPS控制面板选项为常见任务提供Web界面,同时保留SSH以实现完整的管理控制。
对于需要保护同一服务器上运行的Web应用程序的环境,将SSH加固与正确配置的SSL证书相结合,可以同时覆盖管理和应用程序传输层。
技术要点检查清单
在认为您的SSH配置已达到生产就绪状态之前,请验证以下每一项:
密钥管理
私钥最低使用Ed25519或RSA-4096
所有私钥均受强密码短语保护
~/.ssh/目录具有700权限;authorized_keys具有600restrict和command=选项服务器配置
PasswordAuthentication no已设置并激活
已强制执行PermitRootLogin no或prohibit-passwordAllowUsers或AllowGroups将访问限制为指定账户
LoginGraceTime设置为30秒或更短
每次配置更改后sshd -t均无错误通过
密码学加固
KexAlgorithms排除diffie-hellman-group1-sha1和diffie-hellman-group14-sha1Ciphers排除3des-cbc、arcfour和blowfish-cbcMACs仅使用-etm(先加密后MAC)变体运营安全
- SSH认证日志受到监控(
/var/log/auth.log或journalctl -u sshd) - 已配置
fail2ban或同等工具以阻止重复身份验证失败 - 主机密钥指纹已记录并带外存储以供验证
- 生产系统上所有交互式用户会话均已启用MFA
- 拥有五台以上服务器或三名以上管理员的环境已使用SSH CA
常见问题
SSH密钥与SSH证书有什么区别?
SSH密钥要求每台服务器在authorized_keys中存储用户的公钥。SSH证书由证书颁发机构签名;服务器信任CA而不是单个密钥。证书可扩展到大型集群,无需逐服务器密钥管理,并支持过期时间,使撤销变得简单直接。
为什么即使密钥正确,Permission denied (publickey)仍然出现?
最常见的原因是~/.ssh/(必须为700)或authorized_keys(必须为600)的文件权限不正确、主目录对所有人可写(被StrictModes阻止),或sshd_config中的AllowUsers指令排除了连接账户。请检查服务器上的journalctl -u sshd以获取具体的拒绝原因。
将SSH端口从22更改是真正的安全措施吗?
它能消除针对端口22的自动化机会性攻击,这能有效减少日志噪音和身份验证失败尝试。它无法防御执行端口扫描的有针对性攻击者。它应与fail2ban、仅密钥身份验证和防火墙IP白名单相结合,以实现有意义的安全改进。
客户端没有静态IP地址可以使用SSH吗?
可以。基于密钥的身份验证不需要固定的客户端IP。如果您想按IP限制,请在authorized_keys中使用from=选项或防火墙规则。对于动态IP,建议在连接之前使用VPN建立稳定的网络身份,而不是将SSH开放给整个互联网。
如果被锁定在外,恢复SSH访问最安全的方法是什么?
通过您的托管服务商的带外控制台(VNC、IPMI或KVM over IP)访问服务器。从那里挂载文件系统,纠正sshd_config或authorized_keys问题,然后重启SSH守护进程。在AlexHost的VPS和独立服务器套餐中,服务商控制台可通过客户门户访问,不依赖SSH是否正常运行。
