AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 34552
In Process
ahanson
ahanson
Asked: 2009-07-02 08:01:45 +0800 CST2009-07-02 08:01:45 +0800 CST 2009-07-02 08:01:45 +0800 CST

是否有基于名称的虚拟主机 SSH 反向代理?

  • 772

我已经非常喜欢在我们的开发环境中使用 HTTP 反向代理,并且发现基于 DNS 的虚拟主机反向代理非常有用。在防火墙上只打开一个端口(和标准端口)使管理变得更加容易。

我想找到类似的东西来做 SSH 连接,但运气不太好。我不想简单地使用 SSH 隧道,因为这需要打开标准以外的端口范围。有什么可以做到这一点吗?

HAProxy 可以做到这一点吗?

ssh reverse-proxy
  • 7 7 个回答
  • 30172 Views

7 个回答

  • Voted
  1. Zoredache
    2009-07-02T08:17:09+08:002009-07-02T08:17:09+08:00

    鉴于协议的工作方式,我不相信基于名称的 SSH 是可能的。

    这里有一些替代方案。

    • 您可以做的是将响应端口 22 的主机设置为网关。然后可以配置ssh服务器根据key向里面转发请求。带有密钥的SSH网关示例

    • 您可以调整您的客户端以将该主机用作代理。也就是说,它会通过 ssh 连接到网关主机,然后使用该主机与内部主机建立连接。带有客户端配置的SSH 代理。

    • 您还可以在边缘设置一个简单的 http 代理。然后使用它来允许传入连接。通过HTTP 代理的SSH 。

    显然,以上所有内容,确保正确配置和锁定网关非常重要。

    • 26
  2. kasperd
    2014-07-09T06:54:39+08:002014-07-09T06:54:39+08:00

    在过去的 16 个月里,我一直在寻找解决这个问题的方法。但是每次我看,似乎不可能使用相关 RFC 中指定并由主要实现实现的 SSH 协议来做到这一点。

    但是,如果您愿意使用稍作修改的 SSH 客户端,并且愿意以设计时不完全预期的方式使用协议,那么就有可能实现。更多关于这下面。

    为什么不可能

    客户端不会将主机名作为 SSH 协议的一部分发送。

    它可能会将主机名作为 DNS 查找的一部分发送,但这可能会被缓存,并且从客户端通过解析器到权威服务器的路径可能不会穿过代理,即使这样做了,也没有将特定 DNS 查找与特定的 SSH 客户端。

    您也无法对 SSH 协议本身做任何花哨的事情。您必须在没有看到客户端的 SSH 版本横幅的情况下选择服务器。您必须先向客户端发送横幅,然后它才会向代理发送任何内容。来自服务器的横幅可能会有所不同,您无法猜测,哪一个是正确的。

    即使此横幅未加密发送,您也无法对其进行修改。该横幅的每一点都将在连接设置期间进行验证,因此您可能会导致连接失败。

    对我来说,结论很清楚,必须在客户端进行一些更改才能使这种连接正常工作。

    大多数变通方法都是将 SSH 流量封装在不同的协议中。还可以想象 SSH 协议本身的附加内容,其中客户端发送的版本横幅包含主机名。这可以与现有服务器保持兼容,因为部分横幅当前被指定为自由格式标识字段,并且虽然客户端通常在发送自己的版本横幅之前等待来自服务器的版本横幅,但协议确实允许客户端发送他们的横幅第一的。一些最新版本的 ssh 客户端(例如 Ubuntu 14.04 上的客户端)会在不等待服务器横幅的情况下发送横幅。

    我不知道有任何客户端已采取措施在此横幅中包含服务器的主机名。我已经向OpenSSH 邮件列表发送了一个补丁来添加这样的功能。但它被拒绝了,因为它不想向任何窥探 SSH 流量的人透露主机名。由于秘密主机名从根本上与基于名称的代理的操作不兼容,因此不要指望很快就会看到 SSH 协议的官方 SNI 扩展。

    真正的解决方案

    最适合我的解决方案实际上是使用 IPv6。

    使用 IPv6,我可以为每个服务器分配一个单独的 IP 地址,因此网关可以使用目标 IP 地址来找出将数据包发送到哪个服务器。SSH 客户端有时可能在网络上运行,其中获取 IPv6 地址的唯一方法是使用 Teredo。众所周知,Teredo 不可靠,但仅当连接的本机 IPv6 端使用公共 Teredo 中继时。可以简单地在网关上放置一个 Teredo 中继,您将在其中运行代理。Miredo 可以在不到五分钟的时间内安装和配置为继电器。

    一种解决方法

    您可以使用跳转主机/堡垒主机。此方法适用于您不希望将单个服务器的 SSH 端口直接暴露给公共 Internet 的情况。它确实具有减少 SSH 所需的面向外部的 IP 地址数量的额外好处,这就是它在这种情况下可用的原因。它是一种旨在出于安全原因添加另一层保护的解决方案这一事实并不能阻止您在不需要增加的安全性时使用它。

    ssh -o ProxyCommand='ssh -W %h:%p user1@bastion' user2@target
    

    如果真正的解决方案 (IPv6) 超出您的能力范围,那么很难破解以使其工作

    我将要描述的 hack 只能用作绝对的最后手段。在您考虑使用此 hack 之前,我强烈建议为您希望通过 SSH 从外部访问的每台服务器获取一个 IPv6 地址。使用 IPv6 作为访问 SSH 服务器的主要方法,并且仅当您需要从纯 IPv4 网络运行 SSH 客户端时才使用此 hack,而您对部署 IPv6 没有任何影响。

    这个想法是客户端和服务器之间的流量需要是完全有效的 SSH 流量。但是代理只需要对数据包流有足够的了解就可以识别主机名。由于 SSH 没有定义发送主机名的方法,因此您可以考虑其他提供这种可能性的协议。

    HTTP 和 HTTPS 都允许客户端在服务器发送任何数据之前发送主机名。现在的问题是,是否有可能构造一个字节流,它同时作为 SSH 流量和 HTTP 和 HTTPS 都有效。HTTPs 它几乎是一个非入门者,但 HTTP 是可能的(对于 HTTP 的足够自由的定义)。

    SSH-2.0-OpenSSH_6.6.1 / HTTP/1.1
    $: 
    Host: example.com
    

    对您来说,这看起来像 SSH 还是 HTTP?它是 SSH 并且完全符合 RFC(除了一些二进制字符被 SF 渲染弄乱了一点)。

    SSH 版本字符串包含一个注释字段,上面的值为/ HTTP/1.1。换行后 SSH 有一些二进制数据包数据。第一个数据包是MSG_SSH_IGNORE客户端发送的消息,被服务器忽略。要忽略的有效负载是:

    : 
    Host: example.com
    

    如果 HTTP 代理在其接受的内容上足够自由,那么相同的字节序列将被解释为调用的 HTTP 方法SSH-2.0-OpenSSH_6.6.1,而忽略消息开头的二进制数据将被解释为 HTTP 标头名称。

    代理既不理解 HTTP 方法也不理解第一个标头。但它可以理解Host标头,这是它找到后端所需的全部内容。

    为了让它工作,代理的设计原则是它只需要理解足够的 HTTP 来找到后端,一旦找到后端,代理将简单地传递原始字节流并离开真正的终止由后端完成的 HTTP 连接。

    对 HTTP 代理做这么多假设听起来有点牵强。但是,如果您愿意安装一个旨在支持 SSH 的新软件,那么对 HTTP 代理的要求听起来还不错。

    在我自己的情况下,我发现这种方法可以在已经安装的代理上工作,而无需更改代码、配置或其他方式。这是针对仅使用 HTTP 而没有考虑 SSH 编写的代理。

    概念证明客户端和代理。(免责声明代理是我运营的服务。一旦确认任何其他代理支持此使用,请随时更换链接。)

    这个黑客的注意事项

    • 不要使用它。最好使用真正的解决方案,即 IPv6。
    • 如果代理试图理解 HTTP 流量,它肯定会中断。
    • 依赖修改后的 SSH 客户端并不好。
    • 25
  3. Király István
    2017-06-24T04:52:01+08:002017-06-24T04:52:01+08:00

    街区里来了一个新孩子。SSH piper 将根据预定义的用户名路由您的连接,该用户名应映射到内部主机。这是反向代理环境下的最佳解决方案。

    SSH 吹笛者在 github

    我的第一个测试证实,SSH 和 SFTP 都可以工作。

    • 4
  4. Mark
    2009-07-02T08:25:27+08:002009-07-02T08:25:27+08:00

    我不相信这是可能的,至少按照你描述的方式,尽管我很想被证明是错误的。客户端似乎没有发送它希望连接的主机名(至少是明确的)。SSH 连接的第一步似乎是设置加密。

    此外,您还会遇到主机密钥验证问题。SSH 客户端将根据 IP 地址和主机名验证密钥。您将拥有多个具有不同密钥的主机名,但您连接的 IP 相同。

    一个可能的解决方案是拥有一个“堡垒”主机,客户端可以通过 ssh 进入该机器,获得一个正常的(或如果需要的话受到限制)shell,然后可以从那里通过 ssh 进入内部主机。

    • 3
  5. Kafeine
    2011-06-24T00:19:32+08:002011-06-24T00:19:32+08:00

    我想知道是否无法修改具有代理模式的 Honeytrap(低交互蜜罐)来实现这一目标。

    这个蜜罐能够将任何协议转发到另一台计算机。添加基于名称的虚拟主机系统(由 Apache 实现)可以使其成为任何协议的完美反向代理,不是吗?

    我没有实现这一目标的技能,但也许这可能是一个伟大的项目。

    • 2
  6. Jure1873
    2009-07-02T14:48:13+08:002009-07-02T14:48:13+08:00

    由于 ssh 的工作方式,我认为这是不可能的。与 https 类似,您必须为不同的主机提供不同的(外部)IP,因为网关不知道您要连接到哪里,因为 ssh 中的所有内容都已加密

    • 1
  7. John_K
    2022-08-25T09:11:59+08:002022-08-25T09:11:59+08:00

    您可以在服务器端使用 HAProxy,在客户端使用 ssh + openssl 通过 HTTPS 进行 SSH。此方法使用 HTTPS SNI 来识别目标服务器。

    客户端命令示例:

    ssh -o ProxyCommand="openssl s_client -quiet -connect <proxy IP>:2222 -servername server1" dummyName1

    dummyName1在上面的命令中纯粹用作占位符,因为 ssh 需要主机名,但 openssl 在这里完成所有连接工作

    基本 HAProxy 配置:

    frontend fe_ssh
       bind *:2222 ssl crt /etc/haproxy/certs/ssl.pem
       mode tcp
       log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] "
       tcp-request content set-var(sess.dst) ssl_fc_sni
       use_backend %[ssl_fc_sni]
    
    backend server1
       mode tcp
       server s1 <backend ip 1>:22 check
    
    backend server2
       mode tcp
       server s2 <backend ip 2>:22 check
    
    backend server3
       mode tcp
       server s2 <backend ip 3>:22 check
    

    更多细节和安全改进可以在源代码中找到

    • 0

相关问题

  • Mac OS X:如何在无头机器上运行 GUI 应用程序

  • Windows SSH 客户端

  • 在 Windows Server 2003 上通过 SSH 启动和停止 Mongrel 服务

  • 隧道 Xbox 网络流量 [关闭]

  • 为什么使用authorized_keys通过ssh自动登录不起作用?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    从 IP 地址解析主机名

    • 8 个回答
  • Marko Smith

    如何按大小对 du -h 输出进行排序

    • 30 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    Windows 中执行反向 DNS 查找的命令行实用程序是什么?

    • 14 个回答
  • Marko Smith

    如何检查 Windows 机器上的端口是否被阻塞?

    • 4 个回答
  • Marko Smith

    我应该打开哪个端口以允许远程桌面?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    MikeN 在 Nginx 中,如何在维护子域的同时将所有 http 请求重写为 https? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 bash中的双方括号和单方括号有什么区别? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    kch 如何更改我的私钥密码? 2009-08-06 21:37:57 +0800 CST
  • Martin Hope
    Kyle Brandt IPv4 子网如何工作? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve