
浅谈 SSH原理、认证与四种常见用法SSH 是一种“安全地远程控制另一台电脑”的方式。SSH 全称是Secure Shell安全外壳协议。最常见的场景是你的电脑在家里或办公室而服务器在机房、云服务器上你通过 SSH 登录到那台服务器然后像坐在服务器前一样执行命令。通信加密、确认服务器身份、确认登录者身份远程登录通过 SSH 做 Git 身份认证SSH 隧道 / 端口转发。远程传文件排名SSH 使用场景重要性常见用途1远程登录服务器⭐⭐⭐⭐⭐登录 Linux 服务器、云主机、开发机、生产环境2通过 SSH 做 Git 身份认证⭐⭐⭐⭐⭐GitHub / GitLab 拉取、推送私有仓库3SSH 隧道 / 端口转发⭐⭐⭐⭐访问内网数据库、Redis、内部服务、跳板机环境4远程传文件⭐⭐⭐使用 scp、sftp 在本地和服务器之间传文件远程登录服务器项目示例值说明本机 IP192.168.1.20你自己的电脑在局域网里的 IP服务器 IP203.0.113.10远程 Linux 服务器的 IP服务器用户名devuser你登录服务器使用的账号服务器密码DemoPass123!仅作为示例真实环境不要使用这种简单密码SSH 端口22SSH 默认端口服务器 IP 可以是公网 IP也可以是私网 IP。前提是你的电脑和服务器之间存在可达的网络路径并且服务器的 SSH 端口允许访问。【本机 / 你的电脑】 IP192.168.1.20 用户你当前登录本机的用户 │ │ │ 发起 SSH 连接 │ ssh devuser203.0.113.10 │ ▼ 【本机网络 / 路由器】 │ │ │ 经过互联网 │ ▼ 【远程服务器】 公网 IP203.0.113.10 SSH 端口22 服务器用户名devuser 服务器密码DemoPass123! │ │ │ 服务器要求身份认证 ▼ 输入密码 DemoPass123! │ │ │ 认证成功 ▼ 【进入远程服务器 Shell】 当前身份devuser 当前机器203.0.113.10 │ ├── pwd ├── ls ├── cd ├── ps └── 其他 Linux 命令远程登录连接案例关键命令# 语法 ssh 用户名服务器IP # 具体样例 ssh devuser203.0.113.10 # 如果不是22接口 ssh -p 具体端口 用户名服务器IP # 具体样例 这里假设是 ssh -p 31022 devuser203.0.113.10ssh → 使用 SSH -p 31022 → 指定 SSH 端口为 31022 【通常为22】 devuser → 服务器用户名 203.0.113.10 → 服务器 IP整体关系就是你的电脑 IP: 192.168.1.20 │ │ SSH 加密连接 │ │ ssh devuser203.0.113.10 ▼ 远程 Linux 服务器 IP: 203.0.113.10 用户名: devuser 密码: DemoPass123! SSH端口: 22你在自己的电脑终端里执行ssh devuser203.0.113.10第一次连接时可能会看到类似The authenticity of host 203.0.113.10 cant be established. Are you sure you want to continue connecting (yes/no/[fingerprint])?你确认服务器身份后输入yes然后服务器会要求密码devuser203.0.113.10s password:这时候你输入DemoPass123!注意一个很重要的点输入密码时终端通常不会显示任何字符连******都不会显示这是正常的。登录成功之后可能看到devuserserver:~$这意味着原来 你↓ 本机终端 ↓ 192.168.1.20 现在 你 ↓ 本机终端 ↓ SSH ↓ 203.0.113.10 ↓ 远程服务器 Shell此时你执行pwd看到/home/devuser执行ls看到的是project logs backup这些文件和目录不是你本机192.168.1.20上的而是服务器203.0.113.10上的。所以整个过程可以记成本机 192.168.1.20 ssh devuser203.0.113.10 │ ▼ SSH建立加密连接 │ ▼ 输入服务器密码 DemoPass123! │ ▼ 身份认证成功 │ ▼ 远程服务器 203.0.113.10 当前身份 devuser 你现在输入的 Linux 命令 主要都在这台远程服务器上执行注意点还有一个容易混淆的地方本机 IP 通常不需要写进ssh命令。你不需要写ssh 192.168.1.20 devuser203.0.113.10只需要ssh devuser203.0.113.10因为 SSH 客户端本来就是从你当前这台电脑发起连接的。所以这个案例里真正最核心的三个信息其实是服务器地址203.0.113.10 用户名devuser 密码DemoPass123!然后ssh devuser203.0.113.10输入密码就完成一次最基础的SSH 密码登录。通过 SSH 做 Git 身份认证你在访问远程 Git 仓库时不输入账号密码而是用 SSH Key 证明“你是谁”。GitHub 是最常见的场景但不只是 GitHubGitLab、Bitbucket、公司内部 Git 服务器也都常这样做。【本机 / 你的电脑】 │ │ 1. 生成 SSH Key │ │ ssh-keygen -t ed25519 -C your_emailexample.com ▼ 【本机生成一对密钥】 │ ├── 私钥 │ ~/.ssh/id_ed25519 │ 只保存在本机 │ 不要泄露 │ └── 公钥 ~/.ssh/id_ed25519.pub │ │ 2. 复制公钥内容 ▼ 【GitHub 账号】 Settings │ ▼ SSH and GPG keys │ │ 3. 添加你的公钥 ▼ 【GitHub 保存公钥】 │ │ │ 4. 测试 SSH 认证 │ │ ssh -T gitgithub.com ▼ 【SSH 建立连接】 │ │ 本机使用私钥证明身份 │ │ GitHub 使用保存的公钥验证 ▼ 【身份验证成功】 │ │ GitHub 确认 │ “这个 SSH Key 属于哪个 GitHub 账号” ▼ 【通过 SSH 操作 Git 仓库】 │ ├── git clone gitgithub.com:user/project.git │ ├── git pull │ └── git push │ ▼ 【GitHub 检查仓库权限】 │ ├── 有权限 → 允许操作 │ └── 没权限 → 拒绝操作Github SSH KEY 配置示例私钥在你电脑上公钥在 GitHub 上当你用 SSH 操作 Git 仓库时GitHub 通过这对密钥确认“你是谁”。最典型的流程是这样的你的电脑 │ │ 本地保存 SSH 私钥 │ ▼ GitHub │ │ 保存你的 SSH 公钥 │ ▼ 当你 git clone / pull / push 时 GitHub 验证 “你是否真的拥有对应的私钥” │ ▼ 验证成功 │ ▼ 允许访问仓库比如你平时可能看到两种 GitHub 仓库地址HTTPSgit clone https://github.com/user/project.gitSSHgit clone gitgithub.com:user/project.git后面这种gitgithub.com:user/project.git就是通过SSH来认证。整个配置通常分 4 步。在本机生成 SSH Key例如现在比较常用ssh-keygen -t ed25519 -C your_emailexample.com生成以后通常会得到~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub其中id_ed25519 ↓ 私钥 只保存在你自己电脑上 绝对不要给别人 id_ed25519.pub ↓ 公钥 可以给 GitHub把公钥添加到 GitHub你查看公钥cat ~/.ssh/id_ed25519.pub会看到类似ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...... your_emailexample.com然后把这一整行复制到 GitHub 的 SSH Keys 设置中。Github配置SSH个人头像 -- Settings -- SSH And GPG Keys -- New SSH key然后进行添加title和key这样就形成你的电脑 ──────────────────────────── 私钥 ~/.ssh/id_ed25519 GitHub ──────────────────────────── 公钥 ssh-ed25519 AAAA......测试 SSH 身份认证通常可以执行ssh -T gitgithub.com第一次连接可能会问你是否信任 GitHub 的主机指纹。认证成功以后GitHub 会告诉你认证成功。注意这里gitgithub.com这个git一般不是你的 GitHub 用户名。它是 GitHub SSH 服务使用的固定 SSH 用户。GitHub 最终是通过你的SSH Key来判断这个 key 属于哪个 GitHub 账号使用 SSH 地址操作仓库之后git clone gitgithub.com:user/project.git或者git pullgit pushGit 就会在底层通过 SSH 建立连接。可以把一次git push粗略理解成你执行 git push │ ▼ Git 发现远程地址是 gitgithub.com:user/project.git │ ▼ 启动 SSH │ ▼ 连接 github.com │ ▼ SSH 使用你的私钥 │ ▼ GitHub 使用你上传的公钥进行验证 │ ▼ 验证成功 │ ▼ GitHub 确认你的账号 │ ▼ 检查你是否有这个仓库的 push 权限 │ ▼ 允许 push这里有一个特别容易混淆的概念SSH 身份认证 ≠ Git 提交身份。比如你设置git config --global user.name Tom git config --global user.email tomexample.com这是告诉 Git“这次 commit 的作者是谁。”而 SSH Key 是告诉 GitHub“现在连接 GitHub 的这个人是谁以及他有没有访问仓库的权限。”所以两者完全不同东西作用git config user.nameCommit 作者名字git config user.emailCommit 作者邮箱SSH Key登录 / 认证 GitHub 身份GitHub 仓库权限决定你能不能 clone / pull / push你可以把 GitHub SSH 认证浓缩成一句话本机保存私钥GitHub 保存公钥当你通过 SSH 操作 Git 仓库时GitHub 验证你是否拥有对应私钥验证成功后再判断你有没有仓库权限。SSH 隧道 / 端口转发SSH 隧道 / 端口转发Port Forwarding。它和“远程登录服务器”不一样。远程登录的目标是让我进入远程服务器的 Shell。而 SSH 隧道的目标更像是借助 SSH 这条安全连接把原本访问不到的某个端口“转到”我本机来访问。SSH 连接负责建立“隧道”隧道出口所在的那一侧还必须能访问最终目标。-L在本机开一个端口转到远程。-R在远程 SSH 服务器上开一个端口转回本机。本文重点介绍-L和-R两种常见转发方式-N、-f是辅助参数。类型第一条件另外还需要-L 本地端口转发本机能 SSH 连接服务器SSH 服务器要能访问最终目标服务-R 远程端口转发本机能 SSH 连接服务器本机要能访问最终目标服务参数作用常见程度-L本地端口转发⭐⭐⭐⭐⭐-R远程端口转发⭐⭐⭐⭐⭐-N只建立隧道不打开远程 Shell⭐⭐⭐⭐⭐-f建立连接后放到后台运行⭐⭐⭐⭐-g允许其他机器访问本地转发端口⭐⭐-L / -R 决定“怎么转发” -N 决定“只做隧道不登录进去”-L 本地端口转发 ← 最常用 -R 远程端口转发# 本地端口转发 【正向隧道 / 正向 SSH 隧道】 ssh -L 13306:10.0.0.20:3306 devuser203.0.113.10 ssh -N -L 13306:10.0.0.20:3306 devuser203.0.113.10 # 远程端口转发 【反向隧道 / Reverse SSH Tunnel】 ssh -R 18080:127.0.0.1:3000 devuser203.0.113.10 ssh -N -R 18080:127.0.0.1:3000 devuser203.0.113.10-f, -gssh -f -N -L 13306:10.0.0.20:3306 devuser203.0.113.10 -f → 后台 -N → 不开 Shell -L → 本地端口转发-L本地端口转发在你的本机打开一个端口把访问这个本地端口的流量通过 SSH 隧道转发到远程目标服务。-L 本机端口 → SSH 隧道 → 远程目标端口配置成功之后: 本地端口只是一个“入口”真正访问的是 SSH 隧道另一端配置的目标地址和目标端口。语法ssh -L 本地端口:目标主机:目标端口 用户名SSH服务器 # 用户名SSH服务器 【zho】具体样例ssh -L 13306:10.0.0.20:3306 devuser203.0.113.10解决了什么问题 【为什么要跳板机】本机访问不到某个远程服务但 SSH 服务器能访问所以借 SSH 隧道过去。# 本机: 127.0.0.1[192.168.1.20] ----X-X---- 10.0.0.20:3306 无法直接访问 # 跳板机 本机: 127.0.0.1[192.168.1.20] 可以通过SSH访问 devuser203.0.113.10 devuser203.0.113.10 又可以直接访问 10.0.0.20:3306 # 那么就可以通过 SSH 本地端口转发 ssh -L 13306:10.0.0.20:3306 devuser203.0.113.10 # 配置只有 访问 127.0.0.1:13306 等价与 10.0.0.20:3306 # 是不是这样# 1. 本机无法直接访问目标 MySQL 你的电脑 IP192.168.1.20 本机 ────── X ────── 10.0.0.20:3306 无法直接访问 # 2. 但是本机可以 SSH 登录跳板机 你的电脑 192.168.1.20 │ │ SSH ▼ devuser203.0.113.10 │ │ 可以访问 ▼ 10.0.0.20:3306 # 3. 所以建立 SSH 本地端口转发 ssh -L 13306:10.0.0.20:3306 devuser203.0.113.10 # 4. 建立成功以后 你的电脑访问 127.0.0.1:13306 │ │ SSH 隧道 ▼ 203.0.113.10 │ ▼ 10.0.0.20:3306场景例子访问内网数据库MySQL 3306、PostgreSQL 5432访问内网 RedisRedis 6379访问内部 Web 服务比如 10.0.0.30:8080访问管理后台服务只允许内网访问访问 Elasticsearch 等中间件如 9200通过跳板机访问受限资源本机不能直连但跳板机可以具体样例比如一个非常典型的后端场景你的电脑 │ │ SSH 隧道 ▼ 跳板机 / Linux 服务器 │ │ 内网访问 ▼ MySQL 10.0.0.20:3306假设 MySQL 不对公网开放你本机不能直接10.0.0.20:3306但是你能 SSH 登录一台服务器203.0.113.10那么你可以ssh -L 13306:10.0.0.20:3306 devuser203.0.113.10然后你本机访问127.0.0.1:13306实际上流量会走本机 127.0.0.1:13306 ↓ SSH 加密隧道 ↓ 203.0.113.10 ↓ 10.0.0.20:3306所以你可以先把它记成一句话SSH 隧道 借一台可以 SSH 连接的服务器当作安全通道去访问其他网络里的服务。在程序员日常工作中最常见的是访问MySQL / PostgreSQLRedisElasticsearch公司内网 Web 服务只允许内网访问的管理后台Kubernetes / 开发环境里的服务而 SSH 端口转发主要有三种-L 本地端口转发 ← 最常用 -R 远程端口转发如果按重要性学习可以先掌握-L本地端口转发它是开发和运维工作中最常见的一种。-R远程端口转发-R表示Remote Port Forwarding远程端口转发。它会在远程 SSH 服务器上打开一个端口并把收到的连接通过 SSH 隧道转发到本机服务。假设本机运行着一个正在开发的 Web 应用本机开发服务127.0.0.1:3000 远程测试服务器203.0.113.10可以在本机执行ssh-N-R18080:127.0.0.1:3000 devuser203.0.113.10解决了什么问题-R的核心价值是让远程测试环境通过加密连接访问本机开发服务。连接建立后在远程服务器上访问curlhttp://127.0.0.1:18080远程服务器 127.0.0.1:18080 │ │ SSH 远程端口转发 ▼ 本机 127.0.0.1:3000该方式适合调试 Webhook、远程回调和测试环境中的本机应用。仅应在自己拥有或明确授权的环境中使用端口转发。-N辅助/行为控制参数。-N不是一种“端口转发类型”它表示只建立 SSH 连接不执行远程命令也不进入远程 Shell。比如普通 SSHssh devuser203.0.113.10通常会登录进去看到远程终端devuserserver:~$但如果你只是想建立隧道不想进入服务器可以这样ssh -N -L 13306:10.0.0.20:3306 devuser203.0.113.10意思是-N ↓ 不要打开远程 Shell -L ... ↓ 只建立本地端口转发所以它常和这些一起用ssh -N -L ... ssh -N -R ...例如ssh -N -R 18080:127.0.0.1:3000 devuser203.0.113.10表示只建立远程端口转发不登录到远程终端。你可以直接记-L / -R 怎么转发 -N 不要远程 Shell只保留隧道所以-N在“纯隧道用途”里很常见。远程传文件 SCP可以。SSH 远程传文件本质上就是利用 SSH 的加密连接在本机和远程服务器之间安全地复制文件。最常见有两个工具工具作用scp直接复制文件/目录简单常用sftp类似 FTP 的交互式文件传输但走 SSH最常见的是scp。本地到远程 【SCP】比如把本机文件传到远程服务器scp test.txt devuser203.0.113.10:/home/devuser/意思是本机 test.txt ↓ SSH 加密传输 ↓ 远程服务器 203.0.113.10 ↓ /home/devuser/远程到本地 【SCP】反过来把远程文件下载到本机scp devuser203.0.113.10:/home/devuser/test.txt ./如果传整个目录scp -r project/ devuser203.0.113.10:/home/devuser/其中-r recursive 递归复制整个目录如果 SSH 不是默认22端口比如31022scp要用大写-Pscp -P 31022 test.txt devuser203.0.113.10:/home/devuser/注意这里和ssh不一样ssh 指定端口-p scp 指定端口-P所以这一块你先记一句就够了scp** 通过 SSH 在本机和远程服务器之间复制文件。**最核心的两个方向本机 → 远程服务器 scp 本地文件 userserver:远程路径 远程服务器 → 本机 scp userserver:远程文件 本地路径个人声明博客为个人学习笔记如有错误请指正修改。