📖 导读:这篇文章面向第一次接触 SSH 的新手。正文保留原技术内容,对出现的专业名词和概念用 💡 注 的形式补充通俗解释,帮你扫清理解障碍。命令部分可以直接照抄使用。

SSH(Secure Shell)是一种加密的网络协议,用于在不安全的网络上安全地运行网络服务。它最常用于远程登录到计算机系统,执行命令,也支持文件传输、端口转发等功能。SSH 是系统管理员、开发人员和运维工程师的必备工具。

💡 注(网络协议):协议就是两台计算机约定好"怎么互相说话"的规则–数据以什么格式发送、对方怎么回应。SSH 是其中一种专门用于"安全远程操作"的协议。

💡 注(加密):加密就是把原本明文的数据用数学方法打乱成一串乱码,只有持有"钥匙"的人才能还原。这样即使数据在网络传输途中被别人截获,看到的也是乱码,无法读懂内容。

💡 注(远程登录):就是你在自己的电脑上,通过网络操作另一台电脑,效果就像坐在那台电脑前敲键盘一样。常用于管理服务器–服务器通常放在机房或云端,你没法物理接触。


1. 什么是 SSH?

SSH 是 Secure Shell 的缩写,它替代了早期的 Telnet、rlogin 等不安全的远程登录协议。SSH 通过对所有通信数据进行加密和认证,防止了中间人攻击、窃听、连接劫持等风险。

💡 注(三种攻击通俗解释)

  • 窃听:别人在网络上"偷听"你发的数据。早期 Telnet 明文传输,密码都能被直接读出来。
  • 中间人攻击:攻击者冒充服务器(或客户端)插在你们中间,转发并窃取信息。
  • 连接劫持:攻击者在你已经连上之后,强行接管你的连接。

SSH 的加密和认证机制能防住这三种。

SSH 的主要组件

  • SSH 客户端:用于发起连接的软件,如 OpenSSH 客户端(ssh 命令)、PuTTY、Termius 等。
  • SSH 服务器:运行在远程主机上的守护进程(sshd),接受客户端的连接请求。
  • 加密技术:SSH 使用公钥密码学进行身份认证,并使用对称加密(如 AES)保护会话数据。
  • 协议版本:目前主流的是 SSH-2,修复了 SSH-1 中的安全漏洞。

💡 注(守护进程 daemon):守护进程就是一直在后台运行、默默等待任务的服务程序。sshd 里的 d 就代表 daemon。它开机就启动,一直监听"有没有人来连接",有人连就处理。

💡 注(公钥密码学 / 对称加密):这是两种加密方式,后文"密钥认证"会详细讲公钥密码学。这里先知道:对称加密 = 加密和解密用同一把钥匙(速度快,用来加密会话内容);公钥密码学 = 一对钥匙,一把公开一把保密(用来做身份认证)。

SSH 工作原理简述

  1. 连接建立:客户端向服务器发起 TCP 连接(默认端口 22)。
  2. 版本协商:双方交换协议版本。
  3. 密钥交换:通过 Diffie-Hellman 算法生成共享密钥,用于后续对称加密。
  4. 服务器认证:客户端验证服务器的主机密钥(通常存储在 ~/.ssh/known_hosts 中)。
  5. 用户认证:客户端通过密码、公钥等方式向服务器证明身份。
  6. 会话交互:认证成功后,双方建立加密通道,用户即可执行命令或传输文件。

💡 注(端口 port):端口可以理解为一台电脑上"信箱的编号"。一台电脑同时跑很多网络服务,IP 地址只定位到电脑,端口号定位到电脑上的具体服务。SSH 默认用 22 号端口。后面会看到很多 -p 端口号 的用法就是指定端口。

💡 注(主机密钥):服务器自带的"身份证",用于让客户端确认"我连的确实是这台服务器,没被冒充"。第一次连接时客户端会把这个身份证记下来(存在 known_hosts 文件里),下次再连如果身份证变了就会警告。


2. 如何安装 SSH

💡 注(OpenSSH):OpenSSH 是 SSH 协议最主流的免费开源实现,绝大多数系统里的 ssh 命令都来自它。

Linux (Debian/Ubuntu)

sudo apt update
sudo apt install openssh-client    # 仅客户端
sudo apt install openssh-server    # 仅服务器(如需作为服务端)

💡 注(sudo)sudo 表示"以管理员权限运行",安装软件需要权限所以前面要加它。会让你输密码,输入时不显示字符是正常的。

macOS

macOS 默认已安装 OpenSSH 客户端。如需启动服务器(远程登录),在 系统设置 -> 通用 -> 共享 中开启"远程登录"。

Windows

Windows 10 版本 1809 及更高版本内置了 OpenSSH 客户端,可通过 PowerShell 安装:

# 安装客户端
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# 安装服务器(可选)
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

也可使用第三方工具如 PuTTY、Git Bash 中的 SSH。


3. SSH 的基本用法

3.1 连接远程主机

ssh user@hostname
  • user:远程主机上的用户名
  • hostname:远程主机的 IP 地址或域名

例如:

ssh alice@192.168.1.100

首次连接时,会提示确认主机密钥,输入 yes 后即可输入密码登录。

💡 注(首次连接提示):第一次连一台新服务器时,SSH 会说"我不认识这台机器,它的指纹是 xxx,要继续吗?“这是在让你确认服务器身份。输 yes 就会把它记到 known_hosts,以后不再问(除非它变了–那可能是被冒充,会警告)。

3.2 指定端口

如果 SSH 服务器运行在非默认端口(如 2222),使用 -p 选项:

ssh -p 2222 user@hostname

3.3 执行远程命令

直接在 ssh 命令后加上要执行的命令,命令将在远程主机上运行,然后退出:

ssh user@hostname "ls -la /var/log"

3.4 启用调试输出

遇到连接问题时,可使用 -v(详细)模式,或 -vvv 获取更详细的调试信息:

ssh -v user@hostname

4. 密钥认证(免密登录)

使用 SSH 密钥对替代密码登录,更安全且方便自动化。

💡 注(密钥对–重要概念):密钥认证的核心是一对钥匙–公钥私钥

  • 可以这样理解:公钥相当于一把"锁”(可以给别人),私钥相当于"开这把锁的钥匙"(只自己保留)。
  • 你把公钥放到服务器上(相当于给服务器装了把锁),自己保留私钥。
  • 连接时,服务器用公钥出一道题考你,只有持有私钥的人才能答对,答对就放行–全程不传密码。
  • 私钥文件绝不能给别人,公钥可以随便公开。

4.1 生成密钥对

使用 ssh-keygen 生成 RSA(或 Ed25519)密钥对:

ssh-keygen -t ed25519 -C "your_email@example.com"
  • -t ed25519:指定密钥类型(推荐 Ed25519,性能好且安全)
  • -C:添加注释,通常填写邮箱 按提示选择保存路径(默认 ~/.ssh/id_ed25519)和设置密码短语(可选)。

💡 注(~ 符号)~ 在类 Unix 系统(Linux/macOS)里代表"当前用户的家目录",相当于 /home/你的用户名(macOS 是 /Users/你的用户名)。所以 ~/.ssh 就是家目录下的 .ssh 文件夹。Windows 上 ~ 通常对应 C:\Users\你的用户名

💡 注(密码短语 passphrase):这是给私钥文件再加一层密码保护。即使别人偷到你的私钥文件,没有这个短语也用不了。可以留空(图省事),但填了更安全。

4.2 复制公钥到远程主机

使用 ssh-copy-id 命令自动将公钥添加到远程主机的 ~/.ssh/authorized_keys 中:

ssh-copy-id user@hostname

若系统无此命令,可手动复制公钥内容并追加到远程 ~/.ssh/authorized_keys

cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

💡 authorized_keys 就是服务器上"登记哪些公钥可以登录我"的名单文件。你的公钥加进去后,服务器就认得你了。

4.3 配置权限

确保远程主机的 ~/.ssh 目录权限为 700,authorized_keys 文件权限为 600:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

💡 注(权限数字):Linux 文件权限用三位数字表示,分别对应"文件主人 / 同组用户 / 其他人"能做什么。每个数字由 读(4)+写(2)+执行(1) 组合而成:

  • 700 = 主人能读能写能执行(7=4+2+1),其他人啥也不能干(0)。
  • 600 = 主人能读能写(6=4+2),其他人啥也不能干(0)。
  • SSH 对权限很敏感:如果权限太松(别人能读你的密钥文件),它会拒绝工作。这是安全保护。

完成上述步骤后,再次连接将不再提示输入密码。


5. SSH 客户端配置文件

通过 ~/.ssh/config 文件可以为不同的主机设置别名、端口、密钥等,简化连接命令。

示例配置文件:

Host myserver
    HostName 192.168.1.100
    User alice
    Port 2222
    IdentityFile ~/.ssh/mykey_ed25519

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_ed25519

配置后,可直接使用 ssh myserver 连接,无需输入冗长的参数。

💡 :这个配置文件是纯文本,没有也照样能用 SSH,只是有了它更省事–给常连的服务器起个短别名,记不住的 IP、端口、密钥路径都写进去,以后 ssh myserver 一条命令搞定。


6. 文件传输

6.1 scp(基于 SSH 的远程复制)

# 从本地复制到远程
scp /local/file.txt user@hostname:/remote/path/

# 从远程复制到本地
scp user@hostname:/remote/file.txt /local/path/

# 复制整个目录(加 -r 选项)
scp -r /local/dir user@hostname:/remote/dir

6.2 sftp(交互式文件传输)

sftp user@hostname

进入 SFTP 提示符后,可使用 getputlscd 等命令操作文件。

💡 注(scp vs sftp)scp 是"一次性传文件"–一条命令传完就结束;sftp 是"交互式"–进去后可以反复下命令传多个文件,像用 FTP 一样。日常传一两个文件用 scp 更快。


7. SSH 代理(ssh-agent)

ssh-agent 是一个缓存私钥的程序,避免每次使用密钥都输入密码短语。

启动 ssh-agent 并添加密钥

eval "$(ssh-agent -s)"      # 启动代理
ssh-add ~/.ssh/id_ed25519   # 添加私钥(会提示输入密码短语)

之后在同一会话中连接远程主机时,将自动使用已添加的密钥。

💡 注(eval 是干嘛的)ssh-agent -s 会输出几行"设置环境变量"的命令,但只是打印出来不会执行。eval "$(...)" 的作用是"把括号里命令的输出当成命令再执行一遍",从而真正把环境变量设好,让后续的 ssh-addssh 能找到这个代理。照抄即可,不用深究。

💡 注(会话):这里说的"会话"指一个终端窗口开着期间。关掉终端,代理就结束了,下次还得重新启动–所以才有下面的"永久配置"。

永久配置(macOS/Linux)

可将上述命令添加到 shell 配置文件(如 .bashrc.zshrc)中。

💡 注(shell 配置文件).bashrc / .zshrc 是终端每次启动时自动执行的脚本。把启动代理的命令写进去,就不用每次手动运行了。macOS 默认用 zsh(对应 .zshrc),多数 Linux 用 bash(对应 .bashrc)。


8. SSH 端口转发(隧道)

💡 注(端口转发 / 隧道–重要概念):端口转发(也叫"隧道")就是把"本来要发到 A 端口的流量,通过 SSH 加密管道转交给 B"。打个比方:SSH 是一条加密的地下管道,你把本来要走地上(不安全)的流量改走这条地下管道,既安全又能"绕路"到达原本到不了的地方。下面三种是不同方向的转发。

SSH 端口转发允许将本地端口流量通过 SSH 加密隧道转发到远程主机,或反向转发。

8.1 本地转发(将远程端口映射到本地)

访问远程主机上的服务(如数据库)就像访问本地服务一样。

ssh -L 本地端口:目标主机:目标端口 用户@跳板机

例如,通过跳板机访问内部网络的 MySQL(3306):

ssh -L 3306:internal-db:3306 user@jumpbox

然后在本地用 127.0.0.1:3306 连接即可。

💡 注(跳板机 / 堡垒机):内部网络里的数据库通常不对外开放,只能从一台"中间机器"访问,这台中间机器就叫跳板机(jumpbox)或堡垒机。你先 SSH 到跳板机,再通过它转到内部数据库。本地转发就是让"本地端口"的流量经跳板机送到数据库。

8.2 远程转发(将本地端口暴露到远程)

让远程主机可以访问我们本地的服务。

ssh -R 远程端口:本地主机:本地端口 用户@远程主机

例如,让远程主机能访问本地运行的 web 服务(8080):

ssh -R 8080:localhost:3000 user@remote

在远程主机上访问 localhost:8080 即可。

💡 注(-L vs -R 怎么记)-L(Local)= 在本地开端口,把远程服务拉到本地;-R(Remote)= 在远程开端口,把本地服务推到远程。两者方向相反。

8.3 动态转发(SOCKS 代理)

创建一个 SOCKS 代理,通过 SSH 服务器转发所有流量。

ssh -D 本地端口 用户@远程主机

例如,在本地创建 SOCKS5 代理端口 1080:

ssh -D 1080 user@remote

然后在浏览器或系统设置中配置 SOCKS 代理为 127.0.0.1:1080,即可通过远程主机上网。

💡 注(SOCKS 代理):SOCKS 是一种通用的代理协议。开了动态转发后,你的浏览器把所有流量交给本地 1080 端口,SSH 把这些流量加密送到远程主机,再由远程主机替你访问互联网–相当于"借远程主机的网络上网"。常用于在不信任的网络里安全上网,或访问只有远程主机那边才能访问的资源。


9. 安全最佳实践

  • 禁用 root 密码登录:在 /etc/ssh/sshd_config 中设置 PermitRootLogin prohibit-password(仅允许密钥登录)。
  • 使用密钥认证,禁用密码:设置 PasswordAuthentication no
  • 更改默认端口:降低被自动扫描的概率(但并非真正安全)。
  • 限制用户访问:使用 AllowUsersDenyUsers 指令。
  • 使用防火墙:如 ufw 限制 SSH 端口访问来源 IP。
  • 定期更新 OpenSSH:确保修复已知漏洞。

💡 /etc/ssh/sshd_config 是 SSH 服务器端的主配置文件,改完要让配置生效需重启 sshd 服务(如 sudo systemctl restart sshd)。改之前建议备份原文件–改错了可能把自己锁在外面连不上服务器。


10. 故障排查

常见问题及解决

  • 连接超时:检查远程主机是否可达(ping),防火墙是否开放端口。
  • 认证失败:检查用户名、密码/密钥是否正确;查看服务器日志 /var/log/auth.log
  • 主机密钥变更:如果重装系统后连接,会出现"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!",需移除旧的 known_hosts 条目:
    ssh-keygen -R 主机名
    
  • 权限错误:确保本地 ~/.ssh 和私钥文件权限正确(私钥应为 600)。

💡 注(主机密钥变更警告):这行警告意思是"这台服务器的身份证和上次记的不一样了"。常见原因:服务器重装系统、IP 对应的机器换了。但也可能是真的被冒充了。确认安全后用 ssh-keygen -R 主机名 删掉旧记录,重新连接即可。


11. 总结

SSH 是远程管理和安全通信的核心工具。掌握 SSH 的基本用法、密钥认证、配置管理和端口转发,能极大提高工作效率和系统安全性。建议日常工作中尽量使用密钥认证,并熟悉客户端配置文件以简化操作。


本文档适用于个人知识库构建,涵盖了 SSH 的主要概念和实践用法。如有更深入的需求,可参考 OpenSSH 官方文档或 man ssh

💡 注(man 命令)man ssh 就是打开 ssh 命令的内置说明书(manual),按方向键滚动,按 q 退出。Linux/macOS 下几乎所有命令都有 man 手册。