Monday, July 7, 2014

Nginx dynamic reverse proxy

About four years ago, i was knew Nginx when try to fight with slowloris attack on my Apache server. Since that day I was fell in love with Nginx and it never cease to amaze me about what it can do. I now i decice to collect about some part of my use case and solution with Nginx to share.

Our team have one line of internet and one public IP which have to handle many kind of web application behind it some of web application very simple and doesn't care about virtual domain, URL rewirte, authentication resource optimization. So it really need a front web-server who fill the gap  and make the manage process more easy and secured. That where Nginx coming and give me a greate favour. Here is what Nginx currently do in my server:

  • Forward request base on domain and url to the right web application behind 
  • Support https, SPDY to make web application faster and more secure.
  • Caching and optimizing the response of web application's static resource.
  • Authentication and authorization base on domain and URL.
  • Rewrite the URL and add more information to request to help the web application understand more about user. 
  • Limited request rate and bandwidth, deny request base on IP and country to protect web application from abuse by bad visitor.
The Case 1:
We have a IP range in our local network which reserve for 4 virtual machine which run our demo product and can be managed directly by developer when they need to show case to our customer. 

Problem is every time they want allow outside access to their demo product i have to add new record to Nginx or router to forward the request to demo server and now i go tired with that task. I want nginx to extract the forward destination by reading the domain information and forward request to that. For example, when user request Nginx will forward lookup local DNS for computer name acceptance01 and forward to that computer on port 8080 with file index.php. If request failed some how Nginx will handle the bad situation by display a nice error message.

Here is some quick and dirty config from my /etc/nginx/sites-available/
server {
    listen   80;
    server_name  *;

    # Point this to you DNS server which client get DHCP from
    # for example: a virtual machine with host name "abc" request DHCP with your router
    # the DNS name will remember the IP address of "abc" in memory that why we can use
    # hostname with style of

    set $realservername "";
    set $realport "80";

    if ($http_host ~ ^([a-z0-9\-]*)\.(vm\.example\.com)$) {
        set $realservername $1;

    if ($http_host ~ ^([a-z0-9\-]*)\.(\d*)\.(vm\.example\.com)$) {
        set $realservername $1;
        set $realport $2;

    location / {
        # Block client if client not from my country
        # if ($geoip_country_code !~ (VN|^$) ) {
        #    return 403;
        # }

        # uncomment this if you want to limit the name list of server name
        # if ($realservername !~ (name1|name2|name3) ) {
        #    return 403;
        # }

        proxy_connect_timeout 10s;
        proxy_read_timeout 20m;
        proxy_send_timeout 20m;
        proxy_pass  http://$realservername:$realport;

        # needed to forward user's IP address to rails
        proxy_set_header  X-Real-IP  $remote_addr;

        # needed for HTTPS
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_max_temp_file_size 0;

You will also need a wildcard DNS for * point to your server. I using Cloudflare free service which support wildcard DNS. Check with your DNS provider to make sure it support.

Thursday, February 27, 2014

Access free network with tiny DNS packet

Wondering when you're on the airport or Internet cafe with non-free wireless provider, they always redirect you to a page and force you to sign-up and buy their package for wireless access. WOW so disappointed!!!

Luckily on some network like that they are still allow DNS service to have some free to run. So I decide to search some solution about transfer data over tiny over DNS query.

Let Google with "DNS tunneling" and I  choiced the most common solution depend on the limited of the network provider.
  • First is using OpenVPN and configurate it listen on DNS service (UDP port 53) and connect VPN over that. The problem is some secured ISP force us to use their DNS system - they redirect all packet that connect to DNS service to thier server instead of allow it pass the Internet gateway - however this method provide more robust solution for all OS and device ( Ubuntu, Android, Windows ... ) and better performance.
  • The second solution is iodine, a portable-small-tiny and easy to configure DNS tunnel server. However Idoine speed quite limited, but in case of emergency it will help. I found myself that iodine more easy for me than OpenVPN and it can pass almost filter of ISP than OpenVPN tooooo. If you need tunnel for Android device use the Magic tunnel - the folk of Idoin.
OpenVPN: Big Long howto
      Iodine: Quick install guide , Magic tunnel