Linux 下 OpenSSH 基础应用指南:从配置到安全最佳实践
概述
OpenSSH 是 SSH(Secure Shell)协议 的一个免费开源实现,核心就一件事:给远程服务器管控、跨主机传文件提供一条加密的通信通道。在 Linux 服务器运维里,OpenSSH 是离不开的工具——它彻底顶替了 Telnet、FTP、rsh 这些明文传输协议(那些协议会把密码和数据裸奔出去,安全风险很大),靠非对称加密、身份认证这些机制,保证你远程操作是安全的。
关于 OpenSSH,有几个常见的误会得先掰扯清楚:
- 跟 OpenSSL 不是一回事:俩名字像,但其实是不同的项目——OpenSSH 只管”安全远程通信”,OpenSSL 管的是”加密算法库和证书管理”,顶多目标(都提供开源加密工具)有点接近;
- 它源自 OpenBSD 项目:OpenSSH 最早是从 OpenBSD 系统里出来的,现在已经是所有主流 Linux 发行版(Ubuntu、CentOS、Debian 等)默认的远程管理工具了;
- 功能不止登录:除了远程登录(ssh 命令),它还带着密钥生成(ssh-keygen)、公钥分发(ssh-copy-id)、加密传文件(scp)这一整套工具,组成了完整的远程运维生态。
这篇文章打算从”核心配置文件怎么看""安全上怎么最好地实践""常用命令怎么实操”三个角度,把 OpenSSH 的基础用法理一遍,帮你把远程服务器的安全管理弄明白。
一、核心配置文件:sshd_config 详解
OpenSSH 服务端(sshd)的一举一动都由 /etc/ssh/sshd_config 这个配置文件管着,端口、认证方式、日志策略全在里面。下面把最关键的配置项按”安全优先级”排了序说明(默认值以主流发行版为准):
| 配置项 | 默认值 | 核心说明 | 安全建议 |
|---|---|---|---|
| Protocol | 2 | 指定 SSH 协议版本,2 是安全版本(支持 AES 加密、公钥认证),1 为老旧版本(仅支持 DES 加密,已淘汰) | 强制设为 2,禁止 Protocol 1(避免兼容性漏洞) |
| Port | 22 | SSH 服务监听的端口号(默认 22,是黑客扫描的高频目标) | 修改为非默认端口(如 2022、50022),减少暴力破解尝试 |
| ListenAddress | 0.0.0.0(IPv4)、::(IPv6) | 指定服务监听的 IP 地址(0.0.0.0 表示监听所有 IPv4 地址) | 若服务器仅对内网提供服务,设为内网 IP(如 192.168.0.100),禁止公网访问 |
| PermitRootLogin | prohibit-password(部分系统为 yes) | 是否允许 root 用户远程登录:- yes:允许 root 登录(风险高)- no:禁止 root 登录(推荐)- prohibit-password:允许 root 但禁止密码认证 | 设为 no,禁止 root 直接登录(通过普通用户 sudo 提权,降低风险) |
| PasswordAuthentication | yes | 是否允许 “密码认证”(输入用户名 + 密码登录) | 设为 no,强制使用 “公钥认证”(密码易被暴力破解,公钥更安全) |
| PubkeyAuthentication | yes | 是否允许 “公钥认证”(通过密钥对登录,无需输入密码) | 保持 yes,这是最安全的认证方式(需配合 AuthorizedKeysFile 配置) |
| AuthorizedKeysFile | .ssh/authorized_keys .ssh/authorized_keys2 | 存放用户公钥的路径(默认在用户家目录下的 .ssh 文件夹中) | 保持默认即可,需确保 .ssh 目录权限为 700、公钥文件权限为 600(避免其他人修改) |
| PermitEmptyPasswords | no | 是否允许 “空密码用户” 登录 | 保持 no(空密码无任何安全防护,绝对禁止) |
| MaxAuthTries | 6 | 单个连接的最大认证失败次数(如密码输错次数) | 设为 3(减少暴力破解的尝试机会,失败即断开连接) |
| MaxSessions | 10 | 单个连接允许的并行会话数 | 按实际需求调整(如运维人员常用 2-3 个会话,设为 5 足够) |
| LoginGraceTime | 2m(120 秒) | 用户需在指定时间内完成认证,超时则断开连接 | 设为 30s(缩短黑客的尝试窗口,避免资源占用) |
| ClientAliveInterval | 0 | 若客户端无数据传输,服务端每隔多久发送 “存活检测” 消息(0 表示不发送) | 设为 300(5 分钟),避免空闲会话长期占用资源 |
| ClientAliveCountMax | 3 | 存活检测无响应时,最多重试次数(超过则断开连接) | 保持默认 3(15 分钟无响应则断开,兼顾稳定性与安全性) |
| UseDNS | no(部分系统为 yes) | 是否对客户端 IP 进行反向 DNS 解析(验证主机名与 IP 一致性) | 设为 no(DNS 解析可能延迟连接,且对内网环境无意义) |
| AllowUsers / AllowGroups | 未配置(允许所有用户) | 仅允许指定用户 / 组登录(如 AllowUsers admin@192.168.0.0/24) | 强烈配置,限制仅运维用户(如 admin)从内网登录,拒绝其他用户 |
| DenyUsers / DenyGroups | 未配置(允许所有用户) | 禁止指定用户 / 组登录(如 DenyUsers guest) | 配合 AllowUsers 使用,双重限制风险用户 |
| Subsystem sftp | /usr/lib/openssh/sftp-server | SFTP 服务的后端程序路径(用于加密文件传输) | 保持默认即可,若需限制 SFTP 目录,可配置 ChrootDirectory |
配置生效方法
改完 /etc/ssh/sshd_config,得重启 sshd 服务才能让配置生效(不同发行版命令稍微有点差别):
# Ubuntu/Debian 系统
sudo systemctl restart sshd
# CentOS/RHEL 系统
sudo systemctl restart sshd
# 验证服务状态(确保重启成功)
sudo systemctl status sshd
二、OpenSSH 安全最佳实践:躲开 90% 的风险
远程服务器被攻破,主要就是 SSH 暴力破解和弱密码登录这两招。照着下面几条最佳实践做,安全性能上一个大台阶:
1. 关掉密码认证,强制用公钥登录
密码认证很容易被暴力破解(黑客拿字典一批一批地试),公钥认证是建立在非对称加密之上的(私钥只在你自己客户端上,公钥放服务器),安全得多:
- 配置步骤:在 sshd_config 里把 PasswordAuthentication 设成 no,然后重启 sshd;
- 前提:已经给这个用户配好公钥了(看下文”ssh-keygen 与 ssh-copy-id 命令”)。
2. 改掉默认端口,少被扫到
默认端口 22 是黑客扫描的重点关照对象,换成个不常见的端口(比如 2022、50022)就能避开大部分无差别攻击:
- 配置步骤:在 sshd_config 里设 Port 2022,重启 sshd;
- 注意:防火墙规则(比如 ufw、firewalld)也得同步放开新端口,不然就连不上了。
3. 别让 root 直接登录,用普通用户提权
root 是系统里权限最高的用户,一旦被破解后果很严重,建议:
- 配置步骤:在 sshd_config 里把 PermitRootLogin 设成 no,重启 sshd;
- 替代方案:用普通用户(比如 admin)登录,要干特权操作就 sudo(得保证这个用户在 sudoers 列表里)。
4. 限制登录用户与来源 IP
通过 AllowUsers / AllowGroups 限制仅指定用户从内网登录,拒绝公网或无关用户:
# 示例:仅允许 admin 用户从 192.168.0.0/24 内网登录
AllowUsers admin@192.168.0.*
# 示例:仅允许 ssh-users 组的成员登录
AllowGroups ssh-users
5. 配置防火墙,仅开放必要端口
结合 Linux 防火墙(ufw 或 firewalld),仅允许信任 IP 访问 SSH 端口:
# Ubuntu 示例(ufw 防火墙):仅允许 192.168.0.0/24 访问 2022 端口
sudo ufw allow from 192.168.0.0/24 to any port 2022 proto tcp
sudo ufw enable # 启用防火墙
# CentOS 示例(firewalld 防火墙):仅允许 192.168.0.0/24 访问 2022 端口
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.0.0/24" port port="2022" protocol="tcp" accept' --permanent
sudo firewall-cmd --reload # 重载防火墙规则
6. 生成强密码(若仍需密码认证)
如果因为特殊原因还得留着密码认证,那务必用”大小写 + 数字 + 特殊字符”的强密码,可以用下面这条命令直接生成随机强密码:
# 生成 30 位包含大小写、数字、下划线的强密码
tr -dc A-Za-z0-9\_ < /dev/urandom | head -c 30 | xargs
7. 限制 SSH 并发连接和认证次数
别让黑客用一大波并发连接把服务器资源耗光:
- 在 sshd_config 里把 MaxAuthTries 设成 3(最多失败 3 次);
- MaxSessions 设成 5(单个连接最多 5 个会话);
- MaxStartups 设成 5:50:10(连到 5 个时开始拒绝 50%,到 10 个时全部拒绝)。
三、OpenSSH 常用命令:从登录到传文件
OpenSSH 自带了一整套客户端工具,下面把日常运维最常用到的命令一个个过一遍:
1. ssh:远程登录服务器
ssh 是核心命令,用来连远程 SSH 服务端,基本语法:
# 基本用法:ssh 用户名@服务器IP/域名 -p 端口号
ssh admin@192.168.0.100 -p 2022
# 选项说明:
# -p <port>:指定 SSH 服务端监听的端口(默认 22,若修改过端口必须指定)
# -X:启用 X11 转发(允许在远程服务器运行图形化程序,如 gedit)
# -Y:启用“信任的 X11 转发”(比 -X 权限更高,适合需要图形化的场景)
# -t:强制分配伪终端(用于在远程执行 sudo 等需要交互的命令)
# 示例 1:连接默认端口 22 的服务器
ssh admin@192.168.0.100
# 示例 2:连接端口 2022 的服务器,并启用 X11 转发
ssh admin@192.168.0.100 -p 2022 -X
# 示例 3:直接在远程服务器执行命令(执行后断开连接)
ssh admin@192.168.0.100 "df -h" # 查看远程服务器磁盘使用情况
2. ssh-keygen:生成密钥对(公钥 + 私钥)
用来生成公钥认证需要的密钥对(私钥留在客户端,公钥传到服务器):
# 基本用法:生成 RSA 算法的密钥对(最常用,兼容性好)
ssh-keygen -t rsa
# 选项说明:
# -t <type>:指定密钥算法,可选 rsa(经典)、ed25519(更安全、密钥更小)
# -b <bits>:指定密钥长度(RSA 推荐 2048 或 4096 位,ed25519 无需指定)
# -C <comment>:添加注释(如邮箱,便于区分不同密钥)
# 示例 1:生成 4096 位 RSA 密钥,添加注释 "admin@local"
ssh-keygen -t rsa -b 4096 -C "admin@local"
# 示例 2:生成 ed25519 密钥(更安全,适合现代系统)
ssh-keygen -t ed25519 -C "admin@local"
生成过程说明:
- 跑完命令,它会问你”密钥存哪儿”(默认 ~/.ssh/id_rsa,这是私钥;公钥是 ~/.ssh/id_rsa.pub);
- 再问你”设个密码不”(可选项,给私钥加个密码,万一私钥泄露也不至于被人直接拿去用);
- 生成完之后,~/.ssh 目录下会多出两个文件:
- id_rsa:私钥(绝对不能给别人看,权限得设成 600);
- id_rsa.pub:公钥(可以公开,要传到远程服务器上去)。
3. ssh-copy-id:将公钥上传到远程服务器
ssh-copy-id 就是把上传公钥这事儿简化的工具,不用你手动复制公钥内容,直接把本地公钥加到远程服务器的 authorized_keys 文件里:
# 基本用法:ssh-copy-id 用户名@服务器IP/域名 -p 端口号
ssh-copy-id admin@192.168.0.100 -p 2022
# 选项说明:
# -i <key_file>:指定要上传的公钥文件(默认上传 ~/.ssh/id_rsa.pub)
# 示例:上传 ed25519 公钥(非默认路径)
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@192.168.0.100 -p 2022
验证公钥登录:
上传公钥后,执行 ssh admin@192.168.0.100 -p 2022,如果不用输密码就直接进去了,说明公钥认证配好了。
4. scp:加密传输文件 / 目录
scp 基于 SSH 协议做加密传文件,顶替了老式的 FTP(明文传输),基本语法:
# 语法 1:从远程服务器下载文件到本地
scp -P <端口号> 用户名@服务器IP:远程文件路径 本地保存路径
# 语法 2:从本地上传文件到远程服务器
scp -P <端口号> 本地文件路径 用户名@服务器IP:远程保存路径
# 选项说明:
# -P <port>:指定 SSH 端口(注意是大写 P,与 ssh 命令的小写 p 区分)
# -r:递归传输目录(传输文件夹时必须加此选项)
# -p:保持源文件的属性(修改时间、权限等)
# -q:静默模式(不显示传输进度,适合脚本中使用)
# 示例 1:从远程服务器下载 /home/admin/logs 目录到本地 ~/downloads
scp -P 2022 -r admin@192.168.0.100:/home/admin/logs ~/downloads
# 示例 2:将本地 ~/docs/report.pdf 上传到远程服务器 /home/admin/docs
scp -P 2022 -p ~/docs/report.pdf admin@192.168.0.100:/home/admin/docs
# 示例 3:静默模式上传多个文件到远程服务器
scp -P 2022 -q ~/files/*.txt admin@192.168.0.100:/home/admin/files
5. 密钥认证测试(以 GitHub 为例)
如果你想验证本地密钥能不能正常用于远程服务(比如 GitHub、GitLab),可以用 ssh -T 测一下(-T 意思是”不分配终端”,只测连接):
# 测试与 GitHub 的 SSH 连接(验证公钥是否已添加到 GitHub 账户)
ssh -T git@github.com
# 成功提示:Hi username! You've