SSH 是一种网络协议。OpenSSH 是 SSH 最常见的开源实现。
OpenSSH 通常包含:
ssh 远程登录客户端
sshd SSH 服务端
scp 文件复制
sftp 文件传输
ssh-keygen 生成 SSH 密钥
ssh-agent 管理私钥
ssh-add 向 ssh-agent 添加密钥
SSH Server
Linux
Refer to OpenSSH Server | Ubuntu
- 安装ssh服务端
sudo apt install openssh-server
sudo ps -e |grep ssh # 显示sshd即安装成功
- SSH Service
# 启动 ssh 服务
sudo systemctl start ssh
# 重启 ssh 服务
sudo systemctl restart ssh
SSH Server Config
配置文件位于
/etc/ssh/sshd_config,比较常见的修改是端口和关闭密码登录:- 端口:
Port xxxx - 关闭密码登录:将配置文件中的
#PasswordAuthentication yes取消注释并修改为PasswordAuthentication no。请先将客户机的公钥上传到服务器上再关闭密码登录。
修改完成后重启服务。
- 端口:
macOS
要我说前几年 macOS 是没有什么 ssh 远程访问的需求的(毕竟连 Mac OS X Server 都停止支持了),但随着 Agent 时代(2026)的来临, 软硬件设计和性价比都相当优秀的 Mac Mini 爆火,Mac 作为小型服务器的时代又回来了。
Windows
参考 Official: Get started with OpenSSH for Windows
SSH Client
主流操作系统一般会自带 SSH client,大多是 OpenSSH 实现。
SSH 命令
# 连接服务器
ssh <user>@<ip_address>
# 通过特定端口连接服务器
ssh <user>@<ip_address> -p 6222
完整手册见 https://man7.org/linux/man-pages/man1/ssh.1.html
更复杂的操作不建议使用命令方式实现,请直接使用 SSH 配置文件。
SSH 配置文件
强烈建议使用 ssh 配置文件管理多服务器地址以及命令行选项。用户特定配置位于 ~/.ssh/config。
使用配置文件之后不再需要记每个服务器的地址,不再需要每次输入长长的命令,便利性、复用性和可维护性都大大增强。
一个简单的 config 示例:
Host server1
HostName 10.17.111.111
User example_user
Host server2
HostName 10.17.111.112
User example_user
Port 2222
ServerAliveInterval 60
RemoteForward 7890 localhost:7890
Host server3
HostName 10.17.111.113
User example_user
Port 2222
ServerAliveInterval 60
RemoteForward 7890 localhost:7890
LocalForward 5173 localhost:5173
LocalForward 8051 localhost:8051
ProxyCommand nc -X 5 -x localhost:11080 %h %p
完整配置清单参考 https://man7.org/linux/man-pages/man5/ssh_config.5.html
Example1: server1
最简单的配置,使用默认端口 22
完成配置后可以直接通过别名连接
ssh server1
等价于
ssh example_user@10.17.111.111
Example2: server2
在 server 1 的基础上:
- 指定端口为 2222
- 添加服务器保活
- 添加远程端口转发(隧道),将服务器的 7890 端口转发至客户机的 7890 端口
然后在服务器的 ~/.bashrc(如果你使用 zsh 那就是 ~/.zshrc)中添加如下内容:
# for codex or other node env
export NODE_USE_ENV_PROXY=1
IP_ADDRESS="127.0.0.1"
PROXY_PORT="7890"
export http_proxy="http://${IP_ADDRESS}:${PROXY_PORT}"
export https_proxy="http://${IP_ADDRESS}:${PROXY_PORT}"
export no_proxy="localhost,127.0.0.1,::1"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export NO_PROXY="$no_proxy"
新建终端或者运行 source ~/.bashrc 后服务器终端的流量会被转发至客户机的 7890 端口(或者是别的你设置的端口)。Docker 使用代理需要额外修改一些配置文件,请自行查阅。
此时在客户机上运行代理软件,并且设置代理端口是 7890,那么服务器也会通过该代理上网。
如果你有多台需要代理上网的服务器,通过本方式就不再需要为每台服务器单独配置代理。服务器通过代理上网后不再需要配置各种镜像源,也可以直接运行 Codex 等 Coding Agent。
Example3: server3
在 server2 的基础上:
- 添加了本地端口转发,将服务器的两个端口转发至客户机
- 添加
ProxyCommand,让 SSH 通过监听 11080 端口的 SOCKS5 代理连接远程服务器
server3 在我这里的使用场景是 人在校外,连接校内服务器进行工作:
- 本地运行学校提供的 VPN,服务端口为 11080,用于在公网连接校内的服务器,
- 本地运行网络代理,服务端口为 7890,用于本机和服务器 正常 上网
- 设置端口转发以便我可以在本地访问服务器的一些服务(比如 api、webui)
SSH Keygen
本地没有密钥也可以通过密码的方式连接服务器,但还是建议生成 SSH 密钥,可以用于更安全的服务器登陆、通过 SSH 连接 Git 等功能。
检查本地是否已经存在密钥
ls ~/.ssh
若不存在则生成密钥
ssh-keygen -t ed25519 -a 256 -C "user@email"
-t指定密钥类型,这里使用 ed22519,安全性比 rsa 更高-a设置保护私钥的密钥派生函数(KDF)迭代轮数为256- -C 设置注释文字,比如邮箱;不参与身份验证
复制本地公钥到服务器
ssh-copy-id <user>@<ip_address>
(可选)手动复制本地公钥到服务器
cat ~/.ssh/id_ed25519.pub | ssh <user>@<ip_address> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
(Windows)复制本地公钥到服务器
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh <user>@<ip_address> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
复制完成后本机登陆该服务器不再需要输入用户密码。
SCP
scp 基于 SSH 传输文件,参数和 cp 基本一致,只是路径可以写成 主机:路径 的形式。
# 上传文件到服务器
scp ./app.tar.gz <user>@<ip_address>:~/apps/
# 上传目录
scp -r ./dist <user>@<ip_address>:~/apps/
# 下载服务器上的文件到当前目录
scp <user>@<ip_address>:~/logs/app.log ./
# 下载服务器上的目录
scp -r <user>@<ip_address>:~/logs ./backup/
# 两台服务器之间直接传输,数据经过本机中转
scp <user>@<ip_address_1>:~/app.tar.gz <user>@<ip_address_2>:~/
配置好 ~/.ssh/config 之后直接用别名
scp ./app.tar.gz server1:~/apps/
scp -r server3:~/logs ./
scp 的端口参数是大写 -P,和 ssh 的小写 -p 不同:
scp -P 2222 ./app.tar.gz <user>@<ip_address>:~/
scp 没有断点续传和增量同步,大文件或反复同步的目录建议改用 rsync:rsync -avz --progress ./dist server1:~/apps/。
SFTP
相比于 scp 一次跑一条命令,sftp 则是交互式会话
sftp <user>@<ip_address>
sftp server1 # 使用 ~/.ssh/config 中的别名
sftp -P 2222 <user>@<ip_address>
进入会话后是熟悉的类 shell 操作,带 l 前缀的命令作用于本地:
| 命令 | 作用 |
|---|---|
pwd / lpwd | 查看服务器 / 本地当前目录 |
ls / lls | 列出服务器 / 本地文件 |
cd / lcd | 切换服务器 / 本地目录 |
get <文件> / put <文件> | 下载 / 上传文件 |
get -r <目录> / put -r <目录> | 递归传输目录 |
mkdir / rmdir / rm | 在服务器上建目录、删目录、删文件 |
chmod / df | 修改权限 / 查看磁盘空间 |
!<命令> | 在本地执行命令,比如 !ls |
exit 或 bye | 退出会话 |
常见的几步操作:
# 下载服务器 logs 目录到本地 ~/Downloads 目录
lcd ~/Downloads
get -r logs
# 上传本地 dist 目录到服务器的 ~/apps 目录
put -r ./dist ~/apps
批量传输可以写成脚本,非交互式执行,创建 commands.txt,填入内容:
lcd ~/Downloads
get -r logs
put -r ./dist ~/apps
然后执行:
sftp -b commands.txt server1