我正在尝试对路由器上的子网进行 SNI 代理,同时保留源 IP。
背景:我有一个路由器执行 DNAT 来为许多应用程序端口进行端口转发,并且它连接到具有不同后端的子网(实际上使用 VPN)。对于没有 HTTP Host 或 TLS SNI 之类的可以根据请求路由到不同 IP 的协议,我只需使用带有 TCP 端口过滤器的 DNAT,它们就可以正常工作。
对于 TLS,我使用SNI代理基于 TLS SNI 将传入连接多路复用到不同的服务器。它运行良好,但 SINProxy 从路由器本身发送 TLS 数据包,丢弃源地址。这会破坏一些依赖源 IP 的后端服务。
因此,我想知道 netfilter 是否可以使用 TLS SNI(可选使用外部模块)过滤流量并使用 DNAT 路由它们(而不是仅仅丢弃)。如果这不可能,还有其他选择吗?
顺便说一句,我不想在我的路由器上部署完整的 HTTP(或任何 L5 服务器),因为:
- 我必须解密流量并将其代理到后端。这是一笔巨大的开销。
- 由于管理的复杂性,我不想在路由器上部署 TLS 证书。
非常感谢您提前提供的任何有用的回复。
答案1
理论上,使用-j NFQUEUE
让用户空间更改第一个数据包并进行 NAT,您可以想象做这样的事情。实际上您不能,因为您需要收到带有 SNI 扩展的完整 ClientHello 消息才能猜测新的目标地址,并且由于第一个 TCP 数据包将为空,或者使用 UDP,DTLS 无论如何都需要几轮,因此现在对由 conntrack 管理的流进行 NAT 已经太晚了。
您需要一个代理。但代理可以透明,或者您可以使用 PROXY 协议和支持该协议的后端应用程序(尽管它们必须支持同时使用 PROXY 协议和 TLS)。
例如haproxy
在网关上运行可以做以下事情:这是提出PROXY 协议,它也可以使用Linux代理服务器透明代理的目标(对于源和目标都是透明的)。
下面是我找到的 github gist 的链接,其中提供了两种选择:利用 HAProxy 将请求透明地路由到按主机名标识的 Web 服务。以下是有关透明代理配置的几行,将在 Linux 内核中使用代理服务器文档(也是同一要点):
HAProxy 服务器配置如下所示。它适用于 TCP 和 HTTP 模式。
server app1-tls 192.0.2.10:3001 source * usesrc client weight 0
答案2
因此,我想知道 netfilter 是否可以使用 TLS SNI(可选使用外部模块)过滤流量
这是不可能的。NAT 必须从连接的第一个数据包开始,即启动 TCP 握手的 TCP SYN。但 SNI 仅存在于 TLS 握手的 ClientHello 中,该消息仅在 TCP 握手完成后发送。换句话说:NAT 所需的信息在需要时尚未可用。
如果这不可能的话,还有其他选择吗?
haproxy 可以终止 TCP 连接,然后根据 ClientHello 中的 SNI 转发数据 - 而无需在代理处终止 TLS。然后,它可以使用 PROXY 协议(基本上是转发连接开头的标头)转发 TCP 连接内的客户端的原始源 IP。如果上游服务器本身不理解 PROXY 协议,则可以使用类似代理服务器对来自 haproxy 的连接进行 SNAT 以便它显示原始源 IP。