edoceo

How To: Protecting Sites and APIs using Nginx Reverse Proxy w/Filter

Nginx can be easily configured to protect your sites and APIs from unauthorized access.

Nginx For Security

Nginx is a high quality web-server and capable of handling many thousands of connections.

Configure Reverse Proxy

In this example we'll assume that Nginx is protecting Apache and that both are running on the same host. In reality, there would be multiple hosts. If however you're on a single VPS (eg Linode) this might be a method to protect your sites on this single host.

Firstly install nginx.

This configuration defines and Nginx proxy with one back-end server

http {
    limit_req_zone  $binary_remote_addr  zone=one:10m   rate=1r/s;

    proxy_http_version 1.1;
    proxy_intercept_errors on

    perl_modules perl/lib;
    perl_require contego.pm;

    server {

        listen      $public.ip:80;
        server_name edoceo.com
        root /var/www/proxy
        index index.html

        # Rate Limit Requests
        limit_req  zone=one burst=8

        perl  proxy_filter::filter;
        perl_set $do_proxy praesidio::proxy_pass;

        # Everything to the Proxy
        location / {
    
            if ($do_proxy = 1) {
                proxy_pass http://spif.co;
                break;
            }

            proxy_pass  http://127.0.0.1:80;
            # proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect   off;
            proxy_buffering  off;
            proxy_set_header Host            $host;
            proxy_set_header X-Real-IP       $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

Proxy Filter Script

This is a pretty lightweight script. It attempts to filter out a bundle of known bogus input.

See contego.pm

package contego;

use warnings;
use strict;
use Data::Dumper;
use nginx;

$| = 1;

my $log;

sub filter {

    open($log, '>>', '/tmp/proxy-pass.log');
    print $log "Request: " . $r->uri . "\n";

    my $r = shift;
    if ( ($r->request_method ne "GET") || ($r->request_method ne "POST") ) {
        return DECLINED;
    }
    if ($r->request_method eq "GET") {
        $r->discard_request_body();
    }
    if ($r->has_request_body(\&post)) {
        return OK;
    }

    return OK;
}
 
1;
__END__

Loading Comments from Disqus...