Apache mod_substitute 对反向代理主机的 HTTP 请求

Dan*_*cio 6 mod-rewrite reverse-proxy apache-2.2

我有以下设置:

  • LAN 上的打印机 #1
  • LAN 上的 #2 打印机
  • 面向 Internet 的 Debian Apache 2.2 Web 服务器server-external-ip,我想将其用作两台打印机的 IPP 网关

可以通过以下 IPP URL 访问这两个打印机(从 LAN 和从 Apache 服务器):

  • http://printer-1-local-ip/printer
  • http://printer-2-local-ip/printer

(打印机并未物理连接到 Web 服务器。)

我希望可以通过以下 URL 从 Internet 访问它们:

  1. http://server-external-ip/prn1
  2. http://server-external-ip/prn2

IPP 专门通过 HTTP 请求到打印机地址工作(即整个打印过程通过http://printer-X-local-ip/printer URL 上的POST 请求发生),所以我只需要重定向(即反向代理与 Apache) URL 1 和 2 以上。

Apache 正在提供其他内容,因此我无法用自定义程序(例如,netcat 或 netsed)替换它。此外,我无法在不同的端口上运行自定义程序,因为打印机客户端只能在端口 80 上访问服务器。

然后我尝试了以下 Apache 配置:

RewriteRule ^/prn1$ http://printer-1-local-ip:80/printer [P]
ProxyPassReverse /prn1 http://printer-1-local-ip
Run Code Online (Sandbox Code Playgroud)

将 Windows 客户端连接到http://server-external-ip/prn1 URL,反向代理工作。但是 IPP 协议也将完整的设备 URL 发送到打印机(在 POST 数据中)。

这意味着打印机会收到对http://server-external-ip/prn1打印机的显式 IPP 请求,而不是其正确地址 ( http://printer-1-local-ip/printer )。所以它拒绝连接。

我将此条目添加到 Windows 客户端的 HOST 文件中:

server-external-ip    printer-dns-name
Run Code Online (Sandbox Code Playgroud)

但它仍然不起作用,因为打印机收到了对http://printer-dns-name/ prn1的 IPP 请求,该请求仍然具有错误的服务名称(即prn1而不是打印机)。

我无法将反向代理 url 从http://server-external-ip/prn1 更改http://server-external-ip/打印机,因为我必须提供对两台打印机的访问权限(并且我无法更改打印机服务打印机配置中的名称)。

我想要做的是将 IPP 数据通过 HTTP POST 发送到打印机,以将http://server-external-ip/prnX 替换http://printer-X-local-ip/printer(没有校验和在 IPP 协议和我捕获的数据包中,这应该可以工作)。

问题是我可以在谷歌上搜索的所有 Apache 模块都无法帮助您处理发送到反向代理打印机的HTTP请求正文mod_rewrite仅适用于标头,mod_substitute适用于响应正文,mod_headers适用于请求和响应标头,mod_replace适用于除请求正文以外的所有内容等。

随着mod_substitute我试着用下面的:

<Location /> 
    AddOutputFilterByType SUBSTITUTE application/ipp
    Substitute "s|server-external-ip/prn1|printer-1-local-ip/printer|"
</Location>
Run Code Online (Sandbox Code Playgroud)

但是,正如预期的那样,它在响应主体上完美运行,但不适用于代理请求(我检查了代理到另一台服务器)。另请注意,IPP 请求属于application/ipp MIME 类型,因此过滤不会(显着)影响正常流量。

关于如何解决这个烂摊子的任何想法?我觉得应该有一个简单的解决方案,而且我没有以正确的方式看待事情。这就是为什么我要问这个永远很棒的社区(我在这里还没有帖子,但我是一个长期的粉丝)。

我想继续使用这种“重定向方法”,因此只有在不存在直接解决方案的情况下,变通方法才有用。是的,我可以为此目的修改 Apache 模块,但我真的不喜欢...... :-)

与此同时,我会尝试一些网络魔法...... :-)

Kri*_*ien 3

为什么不执行以下操作:为外部打印机定义两个 DNS 名称,例如

printer-1-external.mydomain.com CNAME external-server.mydomain.com
printer-2-external.mydomain.com CNAME external-server.mydomain.com
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用与内部使用的名称相同的名称。让内部 DNS 将打印机名称直接解析为打印机,将外部 DNS 解析为您的外部 IP...

在您的服务器上添加两个基于名称的虚拟主机:

<VirtualHost *:80>
    ServerName printer-1-external.mydomain.com
    ProxyPass / http://printer-1-local-ip/
</VirtualHost>
<VirtualHost *:80>
    ServerName printer-2-external.mydomain.com
    ProxyPass / http://printer-2-local-ip/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

这样,您对http://printer-2-external.mydomain.com/printer的 IPP 请求将在其发布参数中包含正确的服务名称。