借助ssh实现web服务的安全验证

背景

  • 公有云服务器 http 服务 80端口,想做到安全访问
  • 无须HTTPS + 客户端证书
  • 方便、快捷、安全

SSH 隧道 + 本地代理

使用 SSH 隧道将 HTTP 服务"隐藏"在 SSH 之后:

bash 复制代码
# 客户端建立隧道(将本地 8080 转发到服务器的 80 端口)
ssh -L 8080:localhost:80 user@your-server -i ~/.ssh/id_ed25519

# 然后访问本地端口(需先通过 SSH 认证)
curl http://localhost:8080
  • 适用场景:临时授权访问,不适合公开服务。

因为 SSH 隧道(端口转发)的流量是通过 SSH 协议(默认 22 端口) 传输的,与目标服务(如 HTTP 的 80 端口)无关。

其他方式

✅ 方案一:使用客户端证书(TLS Mutual Authentication)

这是最接近 SSH 公钥认证的做法。

✦ 原理(TLS 双向认证):

  • 客户端持有私钥 + 客户端证书
  • 服务端信任某个 CA(或特定证书)
  • 在 TLS 握手阶段,客户端用私钥签名一个随机值,服务端验证客户端证书和签名
  • 验证通过后,允许访问

✦ 实现步骤(以 Nginx 为例):

1. 创建自签 CA:
bash 复制代码
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt
2. 为客户端生成证书:
bash 复制代码
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256
3. 配置 Nginx 启用客户端认证:
nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /path/to/server.crt;
    ssl_certificate_key /path/to/server.key;

    ssl_client_certificate /path/to/ca.crt;   # 信任的CA
    ssl_verify_client on;

    location / {
        root /var/www/html;
    }
}
4. 客户端访问时使用浏览器导入证书:
  • Chrome / Firefox 支持在"证书管理"中导入 .crt.key 文件
  • 或用 curl 测试:
bash 复制代码
curl -v --cert client.crt --key client.key https://example.com/

✅ 方案二:基于 JWT(非对称签名)模拟公钥认证

如果 TLS 客户端证书太重,你可以用 JWT 模拟"公钥签名验证"机制。

✦ 原理:

  • 客户端持有私钥,每次请求前用私钥签名一个 payload,生成 JWT
  • 服务端用已知公钥验证签名,确认身份

✦ 实现逻辑(伪代码):

客户端(Python 示例):
python 复制代码
import jwt
from datetime import datetime, timedelta

private_key = open("client.key").read()

payload = {
    "sub": "client1",
    "exp": datetime.utcnow() + timedelta(minutes=5)
}

token = jwt.encode(payload, private_key, algorithm="RS256")
# 在 header 中发送
headers = {"Authorization": f"Bearer {token}"}
服务端验证(Python Flask 示例):
python 复制代码
from flask import request
import jwt

public_key = open("client.pub").read()

token = request.headers.get("Authorization").split()[1]

try:
    payload = jwt.decode(token, public_key, algorithms=["RS256"])
    print("Client ID:", payload["sub"])
except jwt.ExpiredSignatureError:
    return "Token expired", 401
except jwt.InvalidTokenError:
    return "Invalid token", 403

这种方式适合你已有 Web 架构,且不想涉及证书分发的问题。


✅ 方案三:基于公钥的 HTTP 签名(Http Signature)

这是类似于 AWS、GitHub Webhook 的请求签名机制。

✦ 原理:

  • 请求者用私钥签名 HTTP 请求(方法、时间戳、body 等)
  • 服务端使用公钥验证签名是否匹配

✦ 适用场景:

  • REST API 鉴权
  • 高安全需求的 webhook 回调
  • 可接入现有 Web 服务中间件

✦ 示例实现:

参考规范:


🧠 总结对比

方案 是否基于公钥 浏览器支持 安全性 部署复杂度
TLS 客户端证书 ✅ 是 ★★★★★
JWT + 私钥签名 ✅ 是 ❌(仅后端) ★★★★
HTTP 请求签名(HttpSig) ✅ 是 ★★★★
HTTP Basic / Cookie / 密码 ❌ 否 ★★
相关推荐
Otaku love travel2 小时前
实施运维文档
运维·windows·python
basketball6162 小时前
Linux C 管道文件操作
linux·运维·c语言
浩浩测试一下3 小时前
Windows 与 Linux 内核安全及 Metasploit/LinEnum 在渗透测试中的综合应用
linux·运维·windows·web安全·网络安全·系统安全·安全架构
将心ONE3 小时前
使用 lstrip() 和 rstrip() 方法
运维·服务器
G_whang4 小时前
centos7 安装jenkins
运维·jenkins
Two_brushes.5 小时前
【linux网络】深入理解 TCP/UDP:从基础端口号到可靠传输机制全解析
linux·运维·服务器
FJW0208145 小时前
【Linux】系统引导修复
linux·运维·服务器
✧北辰٩(ˊωˋ*)و南冥✧5 小时前
nginx 负载均衡配置(加解决重复登录问题)
运维·nginx·负载均衡
前端世界5 小时前
鸿蒙系统安全机制全解:安全启动 + 沙箱 + 动态权限实战落地指南
android·安全·harmonyos