突发奇想,用 Nginx 代理一个网站,把网站的一些关键字替换掉,蛮有意思的。

如下图:

百度百科

一、编译安装 Nginx

一般 Nginx 中不包含 subs_filter 文本替换的模块,需要自己手动编译安装,步骤如下。

克隆 subs_filter 仓库:

git clone http://github.com/yaoweibin/ngx_http_substitutions_filter_module.git

正常下载 Nginx 源码包解压,并安装相关编译环境:

# 解压安装包
tar -zxvf nginx-1.22.1.tar.gz
# 安装编译环境
yum -y install gcc gcc-c++  pcre pcre-devel openssl openssl-devel zlib zlib-devel

预编译 Nginx,需要携带上 --with-http_sub_module 参数,并通过 --add-module 指定刚刚拉取的 subs_filter 仓库地址。

本文中仓库地址为:/root/install/ngx_http_substitutions_filter_module/

所以需要携带上关键参数:--with-http_sub_module --add-module=/root/install/ngx_http_substitutions_filter_module/

完整预编译命令如下:

./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_sub_module --with-http_v2_module --add-module=/root/install/ngx_http_substitutions_filter_module/

正常步骤安装 Nginx

# 编译并安装
make && make install
 
# 检查是否编译正确,如果返回值是 0,就是执行成功;0 以外的值,就是失败。
echo $?

# 软连接二进制文件到命令目录
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx

二、配置实现

sub_filter 命令用于指定替换的文本:sub_filter $目标文本 $替换文本;

sub_filter_once 命令指定替换文本的次数,默认为 on,仅替换一次,修改为 off 可进行全文替换。

需要注意源站是否有进行 gzip 压缩,sub_filter 仅能对未压缩的网页进行替换。

server
{
    listen 80;
    listen 443 ssl http2;
    server_name vm.nineya.com;
    index index.php index.html index.htm default.php default.htm default.html;

    ...省略一堆关于https的配置...
  
    location / {
        # 需要进行字符替换的源站点
        proxy_pass http://baike.baidu.com;
        # 指定源站不要进行压缩
        proxy_set_header Accept-Encoding '';
        sub_filter_once off;
        sub_filter 马云 玖涯;
    }
 
}

三、字符替换不生效

按上面的 conf 配置,实际上是无法生效的,因为 Accept-Encoding 配置对于 baike.baidu.com 并没有生效,百度百科依旧反回了经过 gzip 压缩的内容。

该问题可通过两次代理解决,先用一次代理去除源站的 gzip 压缩,然后再用第二次代理进行文本替换。

配置参考如下:

server
{
    listen 80;
    listen 443 ssl http2;
    server_name vm.nineya.com;
    index index.php index.html index.htm default.php default.htm default.html;

    ...省略一堆关于https的配置...

    # 代理去除源站的gzip压缩
    location /test {
        gzip off;
        proxy_pass https://baike.baidu.com/;
        proxy_set_header HOST 'baike.baidu.com';
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }
  
    # 给外部调用,进行文本替换
    location / {
        proxy_pass https://vm.nineya.com/test;
        proxy_set_header Accept-Encoding '';
        sub_filter_once off;
        sub_filter 马云 玖涯;
    }
}