Nginx reverse proxy with code injection

Using nginx as a reverse proxy is very easy to do and there are many guides on the internet on this topic. However there’s not a lot of content regarding modifying proxied data on-the-fly. Here’s how to do it

There are many reasons why you’d want to modify page content on your reverse proxy/load balancer. Maybe you want to insert your analytics script or even do some templating.

We’ll be using the ngx_http_sub_module nginx module (link to official documentation), which should be available by default in most builds. If you are compiling nginx on your own, you have to manually enable it by adding --with-http_sub_module to your compile arguments, as it’s not a default option. You can check if your installation includes this module by running nginx -V

 

Enough preface, let’s get to the code:

location / {
    proxy_set_header Accept-Encoding "";
    proxy_pass http://backend;
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header Connection "Keep-Alive";
    proxy_set_header Proxy-Connection "Keep-Alive";
    sub_filter '</head>' '<script src="https://example.com/injected.js"></script></head>';
    sub_filter_once on;
}

This location block will accept requests and pass them to an upstream called backend. It will then search for string </head> in the responses and if it finds a match, it will replace it with the string <script src="https://example.com/injected.js"></script></head>

sub_filter_once on basically means that if the filter finds multiple occurrences of </head> in our response, it will replace just the first one. For replacement of all occurrences just set the value to off

By default sub_filter modifies just content with text/html mime-type. This is important to ensure it doesn’t try to perform substitution on files such as images or executables. For adding multiple mime-types use the sub_filter_types directive.

1 thought on “Nginx reverse proxy with code injection”

Leave a Reply...