我可以使用 ssh 密钥来验证 HTTP 请求吗?

Jas*_*ker 5 authentication ssh rsa oauth

我正在编写一个需要与网络服务交互的命令行工具,我希望能够使用用户的 ssh 密钥对其进行身份验证。我想知道我是否可以做这样的事情:

  1. 用户/auth/login使用用户的用户 ID向 url(例如)发出请求。
  2. 服务器知道用户的 ssh 公钥,并使用该密钥加密会话 ID。
  3. 用户使用他们的私钥解密服务器的响应,并在每个后续请求中提供该会话 ID。

我想我的主要问题是:我是否刚刚重新发明了一个众所周知的安全机制?这听起来有点像 oauth,但我不确定它是否或如何映射到任何现有的 oauth 工作流程中。

Tom*_*art 0

SSH 和 HTTP 显然是不同的协议。您将需要对不同服务(使用共享会话存储)发出多个请求。穷人的解决方案可以利用ssh隧道。在命令行工具中,您将启动一个进程来保持与服务器的连接

          /---- a local port (entry to the tunnel)
         /
ssh -L 8080:localhost:8081 remote.server.com
               \         \-------------------- remote port (publicly not accessible)
                \
                 \--- address resolve at the other end of tunnel (on server)
Run Code Online (Sandbox Code Playgroud)

一旦隧道建立并且用户通过他的公共 ssh 密钥进行身份验证。CLI 工具可以向本地 http 端口发出请求,8080该请求将通过安全隧道路由到服务器。该请求将被加密,但服务器不知道有关用户及其 ssh 密钥的任何信息。我们要么必须保持隧道打开,要么为每个 HTTP 服务器请求建立新的连接(例如 VPN)。

为了正确实现这一点,您必须实现/修改 ssh 服务器。这基本上就是您想要的,通过 ssh 进行 HTTP 身份验证的 POC源代码(此处)

该代码使用了一个不错的项目charmbracelet/wish,它实现了 ssh 服务器。

            /--- port 8080 - HTTP sever
./auths.sh -
            \--- port 4202 - SSH server
Run Code Online (Sandbox Code Playgroud)
  1. 用户访问https://auths.sh,服务器生成随机 UUID 并告诉用户运行命令ssh auths.sh 28c21335-6ba1-4d3a-8835-e737811297d5
  2. 使用给定的UUID执行ssh命令,服务器将用户的公钥写入文件/tmp/28c21335-6ba1-4d3a-8835-e737811297d5
  3. 浏览器经过身份验证(UUID 存储在 cookie 中SESSION_ID),HTTP 服务器知道用户的公共 ssh 密钥。

使用该wish包,您可以轻松实现自定义身份验证:

s, err := wish.NewServer(
        wish.WithAddress(fmt.Sprintf("%s:%d", host, port)),
        wish.WithHostKeyPEM(pem),
        wish.WithPublicKeyAuth(func(ctx ssh.Context, key ssh.PublicKey) bool { 
        // <- validate public key against e.g. authorized_keys
            return true 
        }),
        wish.WithMiddleware(
            sshHandler,
            logging.Middleware(),
        ),
Run Code Online (Sandbox Code Playgroud)

您可以修改代码并添加会话加密和解密。