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

我有以下设置:

  • 局域网上的打印机#1
  • 打印机#2在LAN上
  • 互联网面临的server-external-ip Debian的Apache 2.2 Web服务器,我想用作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请求来工作(即,整个打印过程通过POST请求在http:// printer-X-local-ip /打印机 URL处发生),所以我只需要redirect(即反向代理与Apache)上面的URL 1和2。

Apache正在服务其他内容,所以我不能用自定义程序(例如netcat或netsed)来replace它。 另外,由于打印机客户端只能够在端口80处到达服务器,因此我无法在其他端口上运行自定义程序。

然后我尝试了下面的Apacheconfiguration:

 RewriteRule ^/prn1$ http://printer-1-local-ip:80/printer [P] ProxyPassReverse /prn1 http://printer-1-local-ip 

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

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

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

 server-external-ip printer-dns-name 

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

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

我想要做的是将IPP数据HTTP POST-ed打印到打印机,用http:// printer-X-local-ip / printerreplacehttp:// server-external-ip / prnX (没有校验和在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> 

但是,正如预期的那样,它完美地处理响应主体,而不是代理请求(我检查代理到另一台服务器)。 另请注意,IPP请求属于application / ipp MIMEtypes,因此过滤不会(显着)影响正常stream量。

任何想法如何解决这个烂摊子? 我觉得应该有一个简单的解决scheme,我不看正确的方式。 这就是为什么我问这个总是令人敬畏的社区(我在这里没有post,但我是一个长期的粉丝)。

我想继续使用这种“redirect方法”,所以只有在没有直接解决scheme的情况下,解决方法才有用。 是的,我可以修改一个Apache模块的目的,但我真的不喜欢它… 🙂

在此期间,我会尝试一些networking魔术… 🙂

为什么不这样做:定义两个DNS名称为您的外部打印机,例如。

 printer-1-external.mydomain.com CNAME external-server.mydomain.com printer-2-external.mydomain.com CNAME external-server.mydomain.com 

你甚至可以使用内部使用的相同名称。 让内部DNS直接将打印机名称parsing到打印机,并将外部DNSparsing到您的外部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> 

这样您的IPP请求http://printer-2-external.mydomain.com/printer将在其后的参数中具有正确的服务名称&#x3002;

对不起,我不能添加评论,但是,如果你还没有,请检查以查看是否:

 ProxyPreserveHost On 

在您的conf文件中设置。

重写的方法对于上下文根是好的,但是对于主机名的问题,听起来像你想要检查ProxyPreserveHost。

http://httpd.apache.org/docs/2.2/vhosts/examples.html