Nginx Reverse Proxy on Asus Merlin

A reverse proxy is what you need when you want to make your home things with Web GUIs, like web cameras, media servers, web servers, etc available on the internet.

I´ve got a Asus RT-N66U router with Asuswrt-Merlin firmware installed which means I can install lots of additional stuff using OPTWARE with ipkg command, like nginx.

So, here´s the step by step guide.

1. I want nginx to listen to the standard http and https ports and since the administration web interface listens on the http port, I need to move the admin web interface to a different port.
In the Web-GUI: Administration / System – Change Authentication Method to https and enter port 8443, Save.

2. SSH to your asus router and login with the admin account.

3. Install nginx package

ipkg install nginx

4. Add startup scripts for allowing http/https in firewall and for starting nginx.

admin@RT-N66U-6370:/# vi /jffs/scripts/firewall-start

#!/bin/sh
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -j ACCEPT

admin@RT-N66U-6370:/# vi /jffs/scripts/services-start

#!/bin/sh
/opt/etc/init.d/S80nginx start

5. Chmod the scripts making them executable.

chmod 755 /jffs/scripts/*

6. Create self-signed SSL certificate with openssl (google it if unsure, lots of howtos out there). Copy to /opt/etc/nginx/ directory with name cert.pem and cert.key . (If you don´t need https skip this part and comment out the servers listening on 443 in nginx.conf below)

7. Edit nginx config file, below is an example config file.

admin@RT-N66U-6370:/# vi /opt/etc/nginx/nginx.conf

user nobody nobody ;
worker_processes  1;
 
events {
    worker_connections  1024;
}
 
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    server_names_hash_bucket_size  64;
 
    sendfile        on;
    #tcp_nopush     on;
 
    #keepalive_timeout  0;
    keepalive_timeout  65;
 
    #gzip  on;
 
    #HTTP default website
    server {
        listen 80;
        server_name  localhost;
 
        location / {
            root   html;
            index  index.html index.htm;
        }
 
        error_page  404              /404.html;
 
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
 
    #HTTP reverse proxies
    server {
        listen 80;
        server_name  www.mydomain.com;
        location / {
            # A backend apache server
            proxy_pass http://192.168.1.4;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
 
    server {
        listen 80;
        server_name  myplex.mydomain.com;
        if ($request_uri !~ "^/web/.*")
        {
          return 301 http://$host/web/index.html;
        }
        location / {
            # Plex Web
            proxy_pass http://192.168.1.9:32400;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
 
    server {
        listen 80;
        server_name  webcam.mydomain.com;
        location / {
            # My webcam
            proxy_pass http://192.168.1.30;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
 
    server {
        listen 80;
        server_name  torrents.mydomain.com;
        location / {
            # Transmission Web interface.
            proxy_pass http://192.168.1.8:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }
 
    # HTTP to HTTPS redirects
    server {
        listen 80;
        # Force SSL for Owncloud
        server_name  owncloud.mydomain.com;
        return 301 https://$host;
    }
 
    # HTTPS default website
    server {
        listen       443;
        server_name  localhost;
        ssl                  on;
        ssl_certificate      cert.pem;
        ssl_certificate_key  cert.key;
        ssl_session_timeout  5m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
 
    # HTTPS reverse proxies
    server {
        listen       443;
        server_name  owncloud.mydomain.com;
        ssl                  on;
        ssl_certificate      cert.pem;
        ssl_certificate_key  cert.key;
        ssl_session_timeout  5m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;
        location / {
            # Owncloud
            proxy_pass http://192.168.1.7;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    }

8. Start nginx

/opt/etc/init.d/S80nginx start

9. If you want to show the correct Remote IP adress of clients connecting in logs on backend webservers, you need to change so the backends uses the X-Forwarded-For HTTP header instead, otherwise it will look like your asus router is the client.

Apache example:
Add a row in httpd.conf:
LogFormat “\”%{X-Forwarded-For}i\” %l %u %t \”%r\” %>s %b \”%{Referer}i\” \”%{User-Agent}i\”” combined_revproxy
And in your vhost:
CustomLog /path/to/your/logfile combined_revproxy

OR: You can install apache module mod_extract_forwarded which will change the REMOTE_ADDR to display the correct Remote IP adress.
RHEL/CentOS: Make sure you have EPEL yum repository, yum install mod_extract_forwarded , edit /etc/httpd/conf.d/mod_extract_forwarded.conf , add MEFaccept all.

PS: Don´t forget to backup your jffs partition before upgrading firmware – in my experience it´s often wiped when you upgrade.
A backup is most easily done by SSH to your router and running tar cvf /tmp/mnt/sda1/backup/jffs-backup.tar /jffs

15 thoughts on “Nginx Reverse Proxy on Asus Merlin

  1. Marc Elser

    Hi,

    When I try to start nginx it always complains that it cannot bind to port 80 on iP 0.0.0.0 because ASUS Web UI is occupying this. I tried to overcome this by only using “HTTPS” login, but it proved to be very unreliably, router got stuck all the time (Chrome + Firefox) when trying to use the Web Interface . Any solution on this?

    Thanks and best regards
    Marc

    Reply
    1. goran Post author

      Hi, Im running the same config, web ui on port 8443 or something like that and I never had any issues.

      Im afraid I dont have any suggestions at the moment…maybe ask a question on the Asuswrt Merlin website?

      Reply
  2. Ingmar

    Hi Goran,

    I’m trying to deploy Nginx reverse proxy setup as described in your article.
    Router is Asus RT-AC66U with most recent version of WRT Merlin firmware.
    For some reason the reverse proxy only works on the internal side and not on the WAN side so I’m not able to access internal websites from the internet.
    Although I’ve also deploy the iptable rules as described the router does not accept traffic on port 80.

    Do you have any idea what is going wrong on my side?

    Thanks!

    Reply
  3. Ingmar

    Already solved the issue… Because of a typo the iptables rules were not loaded correctly.
    Thanks for providing the wiki, it really helped configuring nginx.

    Reply
  4. R

    Fantastic article. What is the correct code to access the ASUSWRT admin page from domain.com/router/?

    Reply
  5. Jon Brown

    Thank you for sharing this. I was wondering if this very things was possible instead for forwarding 80/443 to another server to proxy.

    Currently I run stock firmware on an AC87U which forward HTTP(S) traffic to a Linux NUC that runs Nginx. It doesn’t see significant public traffic, just me accessing my file server and home server.

    Longer term have you had any major issues running the reverse proxy on your router? I haven’t had the need to switch this one to Merlin, but if it’s as easy as it looks and not a PITA to maintain long term I’d do it.

    Reply
    1. goran Post author

      Hi,
      It works like a charm running nginx on my asus router, very stable, never had any issues with it.

      Reply
  6. Chris

    Hi.

    Thank you for the great tutorial. Even for someone like me with very limited linux knowledge I managed to get an nginx server up and running on Asus AC68U with Merlin FW.

    One question if possible: how to update nginx ? it reports version 1.0.14 which is quite old from I could find.

    thank you

    Reply
    1. goran Post author

      Hi,
      I think you are in the hands of optware/entware packaging …if they dont release a newer version you will probably need to compile your own version…never tried that though 🙂

      Reply
  7. Asri

    Hi,
    What’s the requirement for the sites in nginx config file to work over WAN?

    do i just need to set an A record for the domain to my WAN IP?
    No issues loading the sites in my local network using plex.mydomain.com

    but i can’t seem to get it working over WAN.

    Already set up DDNS using namecheap freedns on my router and seems to register with no issues.

    Reply
    1. goran Post author

      Yes, you will need to create DNS records that points on the CNAME of your dynamic dns address.
      And then add those DNS records in nginx.

      Or if you dont have your own domain name I believe most of the dynamic dns providers have wildcard dns settings like *.myhostname.no-ip.org and then you can just create a bunch of sites in nginx.conf like:
      http://www.myhostname.no-ip.org
      webcam.myhostname.no-ip.org
      owncloud.myhostname.no-ip.org
      …and all will resolve to your WAN IP.

      Reply
  8. RuthChief

    I have checked your website and i’ve found some duplicate content, that’s why you don’t rank high
    in google’s search results, but there is a tool that can help you to create 100% unique articles, search for:
    boorfe’s tips unlimited content

    Reply
  9. BestBelle

    I have noticed you don’t monetize your blog, don’t waste your traffic, you can earn additional cash every month because you’ve got hi quality content.
    If you want to know how to make extra $$$, search for:
    Ercannou’s essential adsense alternative

    Reply

Leave a Reply

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