vault backup: 2026-05-17 22:27:07
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
---
|
||||
tags: [计算机网络, SSH, SFTP, SCP]
|
||||
create time: 2026-05-18 03:20
|
||||
---
|
||||
|
||||
# SSH 远程安全登录
|
||||
|
||||
## 概述
|
||||
|
||||
SSH(Secure Shell)是替代 Telnet、rlogin 等明文协议的加密外壳工具。它不仅仅用于远程登录——SSH 的隧道转发能力使其成为网络安全的瑞士军刀。
|
||||
|
||||
## SSH 架构三层模型
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ Application Layer │ ← SSH-CONNECT, SSH-USERAUTH, SSH-CONNECTION
|
||||
│ • scp / sftp │ 每个子协议独立协商版本
|
||||
│ • port forwarding │
|
||||
│ • X11 forwarding │
|
||||
├─────────────────────────────────┤
|
||||
│ Transport Layer │ ← Host-key auth + encryption + integrity
|
||||
│ • Server host-key authentication│ 一旦建立隧道,所有上层协议自动加密
|
||||
│ • Server/pubkey exchange │
|
||||
│ • Symmetric encryption │ 默认 AES-128-GCM or ChaCha20-Poly1305
|
||||
│ • HMAC integrity │
|
||||
├─────────────────────────────────┤
|
||||
│ User Authentication Layer │ ← 多种认证方式
|
||||
│ • password │ SSH-CONN USER_AUTH_REQUEST
|
||||
│ • public key │
|
||||
│ • keyboard-interactive │ MFA/TOTP
|
||||
│ • GSSAPI (Kerberos) │
|
||||
│ • OS Login / Certificate │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
## SSH 密钥交换过程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client
|
||||
participant S as Server
|
||||
|
||||
Note over C,S: Phase 1: Key Exchange (Diffie-Hellman)
|
||||
C->>S: KEXINIT (supported ciphers, DH groups, MACs, compressions)
|
||||
S-->>C: KEXINIT (negotiated algorithms)
|
||||
|
||||
Note over C,S: 服务器选择双方都支持的最强算法
|
||||
S->>C: Server Key Exchange (DH params)
|
||||
S->>C: Server Host Key (RSA/ED25519) + signature
|
||||
|
||||
Note over C: Verify host key fingerprint!
|
||||
C->>S: Client Key Exchange (DH response)
|
||||
|
||||
Note over C,S: Both compute shared secret → derive session keys
|
||||
|
||||
Note over C,S: Phase 2: User Authentication
|
||||
C->>S: SSH_USERAUTH_REQUEST "root" "password"
|
||||
S-->>C: SSH_USERAUTH_SUCCESS ✅
|
||||
|
||||
Note over C,S: Phase 3: Channel Open
|
||||
C->>S: SSH_CHANNEL_OPEN "session"
|
||||
S-->>C: SSH_CHANNEL_OPEN_CONFIRMATION
|
||||
```
|
||||
|
||||
### SSH 支持的公钥算法
|
||||
|
||||
| 算法 | 密钥大小 | 安全性等级 | 备注 |
|
||||
|------|---------|-----------|------|
|
||||
| **ed25519** | 32 bytes | ~128 bits | ✅ **推荐**,EdDSA 椭圆曲线,速度快 |
|
||||
| rsa | 4096 bits | ~128 bits | 通用兼容,但体积大 |
|
||||
| ecdsa | 384 bits | ~128 bits | NIST 曲线,争议因 DualECDRBG |
|
||||
| dsa | 1024 bits | ~80 bits | ❌ **已弃用**,OpenSSH 7.0+ 禁用 |
|
||||
| ssh-rsa (SHA-1) | variable | 弱 | ❌ OpenSSH 8.8+ 默认禁用 |
|
||||
|
||||
```bash
|
||||
# 生成 ed25519 密钥
|
||||
$ ssh-keygen -t ed25519 -C "alice@example.com"
|
||||
# 或带注释和自定义路径
|
||||
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "work@company.com"
|
||||
|
||||
# 复制公钥到远程服务器
|
||||
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote-server
|
||||
|
||||
# 手动添加
|
||||
$ cat ~/.ssh/id_ed25519.pub | ssh user@remote 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'
|
||||
```
|
||||
|
||||
## SSH 端口转发(Tunneling)
|
||||
|
||||
### 本地端口转发(Local Forwarding)⭐
|
||||
|
||||
```bash
|
||||
# 通过 jump server 访问内网数据库
|
||||
ssh -L 3307:db.internal:3306 user@jump.example.com
|
||||
|
||||
# 等效命令: ssh -L <local_port>:<dest_host>:<dest_port> <jump_host>
|
||||
# 本地 localhost:3307 → SSH 隧道 → jump.example.com → db.internal:3306
|
||||
```
|
||||
|
||||
```
|
||||
Client Jump Server DB Server
|
||||
──────── ─────────── ─────────
|
||||
localhost:3307 ──→ [SSH Tunnel] ──→ db.internal:3306
|
||||
↑ ↑
|
||||
MySQL CLI SSH 加密通道 🔒
|
||||
```
|
||||
|
||||
### 远程端口转发(Remote Forwarding)
|
||||
|
||||
```bash
|
||||
# 让外网访问我本地服务(反向穿透 NAT)
|
||||
ssh -R 8080:localhost:3000 user@public-server
|
||||
|
||||
# 我的 Mac:3000 ← SSH -R ← public-server:8080
|
||||
# 任何人访问 public-server:8080 都能到我的本地服务!
|
||||
```
|
||||
|
||||
### 动态端口转发(SOCKS Proxy)
|
||||
|
||||
```bash
|
||||
# 创建 SOCKS5 代理
|
||||
ssh -D 1080 user@bastion
|
||||
|
||||
# 浏览器设置 SOCKS proxy: 127.0.0.1:1080
|
||||
# → 所有流量经过 bastion 转发
|
||||
```
|
||||
|
||||
## SSH 配置文件
|
||||
|
||||
```bash
|
||||
# ~/.ssh/config
|
||||
Host github.com
|
||||
HostName github.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_ed25519_github
|
||||
IdentitiesOnly yes
|
||||
|
||||
Host bastion
|
||||
HostName 203.0.113.5
|
||||
User deploy
|
||||
IdentityFile ~/.ssh/id_ed25519_bastion
|
||||
Port 2222
|
||||
|
||||
Host internal-*
|
||||
ProxyJump bastion
|
||||
User admin
|
||||
IdentityFile ~/.ssh/id_ed25519_internal
|
||||
ServerAliveInterval 60
|
||||
ServerAliveCountMax 3
|
||||
|
||||
# 使用: ssh internal-webapp1 (自动经 bastion 跳转)
|
||||
```
|
||||
|
||||
### 关键参数说明
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| `ProxyJump` | 通过堡垒机跳转 |
|
||||
| `ServerAliveInterval` | 客户端发送心跳间隔(秒),防防火墙超时 |
|
||||
| `ServerAliveCountMax` | 最多连续无响应次数后断开 |
|
||||
| `IdentitiesOnly` | 仅使用指定的 identity file,不尝试其他密钥 |
|
||||
| `StrictHostKeyChecking` | `ask`(默认) / `no`(不检查) / `accept-new`(首次接受) |
|
||||
|
||||
## Go 中的 SSH
|
||||
|
||||
```go
|
||||
import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
"os"
|
||||
)
|
||||
|
||||
// 读取私钥文件
|
||||
key, err := os.ReadFile("~/.ssh/id_ed25519")
|
||||
if err != nil { panic(err) }
|
||||
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
if err != nil { panic(err) }
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: "admin",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 生产环境用 ssh.FixedHostKey()
|
||||
}
|
||||
|
||||
client, err := ssh.Dial("tcp", "server.example.com:22", config)
|
||||
if err != nil { panic(err) }
|
||||
|
||||
// 执行远程命令
|
||||
session, _ := client.NewSession()
|
||||
defer session.Close()
|
||||
output, _ := session.CombinedOutput("uname -a; uptime")
|
||||
fmt.Println(string(output))
|
||||
|
||||
// SFTP client
|
||||
sftpClient, _ := sftp.NewClient(client)
|
||||
defer sftpClient.Close()
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/HTTPS与TLS握手]] — SSH 也使用非对称加密 + 对称加密混合模式
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — SSH 端口转发可穿透 NAT
|
||||
- [[hhs/NETWORK/MAC地址与广播域]] — SSH 在局域网内的常见部署场景
|
||||
Reference in New Issue
Block a user