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

  1. 安装ssh服务端
sudo apt install openssh-server
sudo ps -e |grep ssh # 显示sshd即安装成功
  1. SSH Service
# 启动 ssh 服务
sudo systemctl start ssh
# 重启 ssh 服务
sudo systemctl restart ssh
  1. SSH Server Config

    配置文件位于 /etc/ssh/sshd_config,比较常见的修改是端口和关闭密码登录:

    • 端口:Port xxxx
    • 关闭密码登录:将配置文件中的#PasswordAuthentication yes取消注释并修改为PasswordAuthentication no。请先将客户机的公钥上传到服务器上再关闭密码登录。

    修改完成后重启服务。

macOS

参考 允许远程电脑访问你的 Mac

要我说前几年 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