使用mod_proxy_html完善Apache反向代理

在使用和配置过程中,还是遇到了一些波折,这里分享、记录一下。

1. 模块mod_proxy_html可以做些什么

使用Apache内置的mod_proxy的Proxypass可以帮助我们实现基本的反向代理功能。但是,代理返回的结果页面包含的链接并不会被重写,所以如果被代理的Server返回的是绝对地址,用户则无法正确访问这些链接。例如:

我们有反向代理服务器http://myproxy.taobao.org/,而内网有需要代理的服务器http://internalserver.taobao.org/,通过基本的反向代理指令Proxypass

ProxyPass ^/proxy_internal/(.*)$ http://internalserver.taobao.org/$1

可以完成基本的反向代理任务,但是如果internalserver.taobao.org返回的HTML代码中有如下链接,则客户端则无法正常链接到目标页面了:

<a href=”/test/index.html”>Sample Link</a>

因为,客户端点击该链接时会定向到http://myproxy.taobao.org/test/index.html,而资源实际是在http://internalserver.taobao.org/test/index.html上。

Apache自带的mod_proxy无法解决这个问题,开源的第三方模块mod_proxy_html为此而生。经过代理服务器的HTML可以通过该模块做一次替换,从而变成可以正常访问的URL(上例中会把/oninternal/index.html替换成/proxy_internal/test/index.html)。

2. 编译安装mod_proxy_html模块

我是在RHEL5.4上安装的,并不容易。理想的安装步骤(为了支持多字符集需要同时安装mod_xml2enc):

1. 检查是否安装了libxml2。

2. 下载mod_proxy_html源码:地址;下载mod_xml2enc的源码:地址mod_xml2enc

3. 编译mod_proxy_html和mod_xml2enc:

sudo /usr/sbin/apxs -c -I/usr/include/libxml2 -I. -I /usr/lib -i mod_proxy_html.c
sudo /usr/sbin/apxs -c -I/usr/include/libxml2 -I. -i mod_xml2enc.c
chmod 755 /usr/lib64/httpd/modules/mod_proxy_html.so

如果你这么顺利就编译好了模块,那你很幸运。

编译中的问题

$ /usr/sbin/apxs -c -I/usr/include/libxml2 -I. -I /usr/lib -i mod_proxy_html.c
“my” variable $libdir masks earlier declaration in same scope at /usr/sbin/apxs line 36.
/apr-1/build/libtool –silent –mode=compile gcc -prefer-pic -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/httpd -I/usr/include/apr-1 -I/usr/include/apr-1 -I/usr/include/libxml2 -I. -I/usr/lib -c -o mod_proxy_html.lo mod_proxy_html.c && touch mod_proxy_html.slo
sh: /apr-1/build/libtool: No such file or directory
apxs:Error: Command failed with rc=8323072

仔细看是:/apr-1/build/libtool: No such file or directory。对libtool和apr-1不很熟悉,看出是因为没有正确找到libtool的路径导致的,所以修改了一下脚本apxs,强制指定libtool的位置,虽然这不是“优雅的”解决办法:

$locate libtool #找到你的libtool
……
$vi /usr/sbin/apxs

my $libtool = `$apr_config –apr-libtool`;
chomp($libtool);
$libtool = “/usr/lib64/apr-1/build/libtool”;

It works! 如果有个有更好的办法,或者知道根本原因的,请告诉我,谢过先。

3. 配置该模块

强烈建议参考mod_proxy_html源码中的proxy_html.conf,这是一个示例配置文件,非常有指导意义。我这里的配置如下:

1. 加载必要的模块:

LoadFile /usr/lib64/libxml2.so
LoadModule xml2enc_module modules/mod_xml2enc.so
LoadModule proxy_html_module modules/mod_proxy_html.so

2. 指定需要修改的链接标签:

SetOutputFilter proxy-html
ProxyHTMLExtended On
ProxyHTMLLinks a href
ProxyHTMLLinks area href
ProxyHTMLLinks link href
ProxyHTMLLinks img src longdesc usemap
ProxyHTMLLinks object classid codebase data usemap
ProxyHTMLLinks q cite
ProxyHTMLLinks blockquote cite
ProxyHTMLLinks ins cite
ProxyHTMLLinks del cite
ProxyHTMLLinks form action
ProxyHTMLLinks input src usemap
ProxyHTMLLinks head profile
ProxyHTMLLinks base href
ProxyHTMLLinks script src for
ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
onmouseover onmousemove onmouseout onkeypress \
onkeydown onkeyup onfocus onblur onload \
onunload onsubmit onreset onselect onchange

3. 指定的URL替换规则:

ProxyPassMatch ^/proxy_dir/(.*)$ http://yourdomain/$1 <LocationMatch "/proxy_dir/"> ProxyPassReverse / ProxyHTMLURLMap / /proxy_dir/ ProxyHTMLURLMap http://some_(reg_exp)_url_(is_supported)you_wanna_replace/ /proxy_dir/$1/$2/ R RequestHeader unset Accept-Encoding </LocationMatch>

OK,That’s all.

广告:我们寻找靠谱的人 | 感谢作者

参考:

1. mod_proxy_html主页

2. Running a Reverse Proxy in Apache

2 responses to “使用mod_proxy_html完善Apache反向代理”

  1. df

    这样做太繁琐,而且我设置另一段proxyrequests off代码,竟然无效。还是先安装/加载模块,添加下述几行到apache2.conf(httpd.conf)
    LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
    LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
    LoadModule proxy_connect_module /usr/lib/apache2/modules/mod_proxy_connect.so
    LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
    LoadModule proxy_ftp_module /usr/lib/apache2/modules/mod_proxy_ftp.so

    然后在新建的虚拟主机目录下建立.htaccess文件:
    RewriteEngine On
    RewriteBase /
    RewriteRule ^(.*)$ http://some-blocked-site.com/$1 [P]

    然后在默认的虚拟主机的配置文件里,

    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all

    然后重启apache即可。

    而且可添加新的虚拟主机,以便反向代理其他被封的网站。

  2. 遇到了一个问题,在编译mod_proxy_html 时出错 libxml/HTMLparser.h: No such file or directory ,libxml存在问题,但是不知道该怎么解决了. libxml2 是yum安装上的.

Leave a Reply

Your email address will not be published. Required fields are marked *