远程操作:ssh、scp
ssh:安全远程登录
ssh(Secure Shell)是加密的远程登录协议,替代了不安全的 telnet,是管理远程服务器的标准方式。
基础连接
# 基本连接(默认端口 22)
ssh user@hostname
ssh user@192.168.1.100
# 指定端口(-p port)
ssh -p 2222 user@hostname
# 使用私钥登录(-i identity)
ssh -i ~/.ssh/id_rsa user@hostname
# 执行远程命令(不登录交互式 Shell)
ssh user@hostname "ls -la"
ssh user@hostname "sudo apt update"
# 本地端口转发(-L local:remote)
ssh -L 8080:localhost:80 user@hostname
# 访问本机 8080 端口 = 访问远程服务器的 80 端口
# 远程端口转发(-R)
ssh -R 9090:localhost:3000 user@hostname
# 远程服务器访问 9090 端口 = 访问本机的 3000 端口
# 动态端口转发(SOCKS 代理,-D)
ssh -D 1080 user@hostname
# 配置浏览器使用 SOCKS5 代理 localhost:1080
SSH 密钥认证
密码登录不安全且繁琐,SSH 密钥认证是标准做法。
# 生成密钥对(-t type,-b bits)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 或更现代的算法
ssh-keygen -t ed25519 -C "your_email@example.com"
# 生成过程
# Enter file in which to save the key: (~/.ssh/id_rsa)
# Enter passphrase: (可选,建议设置)
# 生成:私钥 ~/.ssh/id_rsa,公钥 ~/.ssh/id_rsa.pub
# 复制公钥到远程服务器(自动配置 authorized_keys)
ssh-copy-id user@hostname
# 手动复制公钥
cat ~/.ssh/id_rsa.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
# 配置 SSH 客户端(~/.ssh/config)
cat >> ~/.ssh/config
Host myserver
HostName 192.168.1.100
User admin
Port 2222
IdentityFile ~/.ssh/id_rsa
ServerAliveInterval 60
# Ctrl+D
# 使用别名连接
ssh myserver
SSH 配置优化
# ~/.ssh/config 常用配置
Host *
ServerAliveInterval 60 # 每 60 秒发送心跳包
ServerAliveCountMax 3 # 最多 3 次无响应断开
StrictHostKeyChecking no # 首次连接不提示确认(仅内网)
UserKnownHostsFile /dev/null # 不记录 known_hosts(仅测试环境)
Host prod
HostName 203.0.113.10
User deploy
Port 22
IdentityFile ~/.ssh/prod_key
ForwardAgent yes # 转发本地 SSH agent
scp:安全文件复制
scp(Secure Copy)基于 SSH 协议在本地和远程之间复制文件。
# 本地 → 远程
scp file.txt user@hostname:/path/to/dest/
scp file.txt user@hostname:/path/to/dest/newname.txt
# 远程 → 本地
scp user@hostname:/path/to/file.txt ./
# 指定端口(-P port,注意大写 P)
scp -P 2222 file.txt user@hostname:/path/
# 使用私钥(-i identity)
scp -i ~/.ssh/id_rsa file.txt user@hostname:/path/
# 复制目录(-r recursive)
scp -r local_dir/ user@hostname:/path/to/dest/
# 复制多个文件
scp file1.txt file2.txt user@hostname:/path/
# 保留文件属性(-p preserve)
scp -p file.txt user@hostname:/path/
# 显示进度(-v verbose)
scp -v file.txt user@hostname:/path/
scp vs rsync
| 特性 | scp | rsync |
|---|---|---|
| 增量传输 | 否(全量复制) | 是(只传差异部分) |
| 断点续传 | 否 | 是 |
| 删除目标多余文件 | 否 | 是(--delete) |
| 速度 | 慢(大文件) | 快(增量) |
| 适用场景 | 简单复制 | 同步、备份 |
# rsync 替代 scp(推荐用于大文件/目录)
rsync -avz local_dir/ user@hostname:/path/to/dest/
# -a = 归档模式(保留属性)
# -v = 详细
# -z = 压缩传输
# rsync 增量同步(只传修改过的文件)
rsync -avz --delete local_dir/ user@hostname:/path/to/dest/
# --delete = 删除目标端多余的文件
SSH 端口转发详解
本地端口转发(-L)
把本地端口映射到远程服务器的某个端口,常用于访问远程内网服务。
# 场景:远程服务器运行了 MySQL(端口 3306),但只监听 localhost
# 你想用本地的 MySQL 客户端连接
ssh -L 3307:localhost:3306 user@remote-server
# 本地 3307 → 远程 localhost:3306
# 现在可以在本地连接
mysql -h localhost -P 3307 -u root -p
远程端口转发(-R)
把远程服务器的端口映射到本地的某个端口,常用于让外网访问内网服务。
# 场景:你在内网开发机运行了 Web 服务(端口 3000)
# 想让外网通过远程服务器访问
ssh -R 8080:localhost:3000 user@remote-server
# 远程 8080 → 本地 localhost:3000
# 外网用户访问 remote-server:8080 = 访问你的本地 3000
动态端口转发(-D)
创建 SOCKS 代理,把所有流量通过 SSH 隧道转发。
# 创建 SOCKS5 代理
ssh -D 1080 user@remote-server
# 配置浏览器/系统使用 SOCKS5 代理 localhost:1080
# 所有流量通过远程服务器转发
本篇小结
ssh user@host:远程登录,-p指定端口,-i指定私钥ssh-keygen:生成密钥对,ssh-copy-id:复制公钥到远程服务器~/.ssh/config:配置主机别名、端口、私钥,简化连接scp:基于 SSH 的文件复制,-r递归目录,-P指定端口rsync -avz:增量同步,比 scp 更高效,支持断点续传- 本地转发
-L:访问远程内网服务;远程转发-R:让外网访问本地服务;动态转发-D:SOCKS 代理
动手实践
SSH 密钥配置:
# 生成密钥(如果还没有) ssh-keygen -t ed25519 -C "your_email@example.com" # 查看公钥 cat ~/.ssh/id_ed25519.pub # 配置别名(如果有远程服务器) cat >> ~/.ssh/config Host test HostName 192.168.1.100 User testuser Port 22 # Ctrl+Dscp 文件传输:
# 本地 → 远程(如果有远程服务器) # scp file.txt test:/tmp/ # 远程 → 本地 # scp test:/etc/passwd ./ # 本地练习(复制到 /tmp) scp /etc/passwd /tmp/passwd.bak端口转发实验(如果有两台机器):
# 终端 1:建立隧道 # ssh -L 8080:localhost:80 test # 终端 2:通过隧道访问 # curl http://localhost:8080rsync 同步练习:
mkdir -p source/{a,b,c} touch source/{a,b,c}/file.txt rsync -avz source/ dest/ ls -R dest/ # 修改 source 后再次同步 touch source/newfile.txt rsync -avz source/ dest/SSH 配置优化:
cat >> ~/.ssh/config Host * ServerAliveInterval 60 ServerAliveCountMax 3 # Ctrl+D思考:为什么 SSH 密钥认证比密码认证更安全?如果私钥文件
~/.ssh/id_rsa被泄露,攻击者能直接登录你的服务器吗?如何保护私钥?