Nginx Hacking Tips

By Angsuman Chakraborty, Gaea News Network
Saturday, July 12, 2008

Nginx LogoNginx is a high performance web server and mail proxy server written by Igor Sysoev and a good replacement for Apache HTTPD, the market leader. Nginx is rapidly increasing its market share with major websites joining it like wordpress.com. In the June 2008 Netcraft survey LiteSpeed lost more than 600 thousand sites during this survey, while nginx gained more than a million sites; more than doubling in numbers. The WordPress blogging system recently converted all of its load balancers to nginx, using the upstream hash module to serve 8-9 thousand requests per second. We too have decided to move some of our websites to Nginx. Here are few essential tips and general guidelines for configuring Nginx. This is not a substitute for reading the documentation (rtfm). However when you are stuck even after reading and re-reading the nginx documentation then read below. You will understand the value of the tips below only then :)

We will focus on general configuration tips as well as for virtual hosting.

Note: In virtual hosting you use the same IP address for multiple websites. Each website will most likely have separate .htaccess (assuming you were initially hosted on Apache HTTPD web server) files, separate root directory etc. For example in one website you have wordpress, while on the other you may have MODx and who knows maybe phpBB on the third. All these different .htaccess directives needs to go in the nginx configuration file(s).

Nginx has a major limitation in rewrite rules in that you cannot impose multiple conditions for a rewrite rule. Apache HTTPD on the other hand provides a good solution using multiple RewriteCond directives.

Nginx on the other hand allows if statement. You can have rewrite rules within if blocks. However the if block themselves are limited. You do not have and or or to add multiple conditions to a single if block. Also you cannot nest if blocks. There are no else statement either. However you can use regular expressions so the following is possible:

if ($request_method !~ ^(GET|HEAD)$ ) {
    return 501;
}

However you cannot check two variables at a time. Specially in virtual hosting scenario such limitations can often be perceived as showstoppers. However I found that with little extra thinking you can come up with innovative solutions to serve your special needs. For example a very common .htaccess rule for many PHP based web software including wordpress is:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

It says that if the requested filename is not present and is also not a directory then invoke index.php instead.

However while the RewriteCond is the same for most PHP based software the RewriteRule isn’t. For example a portion of the rewrite rules for phpBB is:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^[a-z0-9_-]+/?(p([0-9]+)\.html)?$ /viewforum.php?start=$2 [QSA,L,NC]

Ignore the third RewriteCond for now. It also checks for symbolic links. As you can see the rewrite rule is different. Suppose you need to host both WordPress and phpBB websites on a single IP address (single server). As the first two rules are common you can do write the following rule which will apply to both the server:

# If it is a file, directory or symbolic link
if (-e $request_filename) {
    break;
}

This does the same thing as the previous RewriteCond does and is applicable to all the websites on the server (assuming you placed it within the server).

Now you can have separate rewrite rules for your individual server. For example you can use this rule for your WordPress blog:

# rewrite rules for blog.example.com
if ($host ~* ^blog\.example\.com$) {
    rewrite  ^(.*)$  /index.php?q=$1  last;
    break;
}

The break is to ensure that no further rules are processed after all the previous statements in the if condition has been executed.

The last ensures that no further rewrite rules are executed when the rewrite rule matches.

I have written three articles recently with emphasis on virtual hosting:

  1. How to run phpBB on Nginx with / without Virtual Hosting
  2. Nginx: how to fix directory resolution issue as well as internal re-directs in virtual hosting
  3. How to configure Nginx for virtual hosting

Let’s add few more tips to complete the chapter, shall we?

How to prevent files beginning with . (like .htaccess) from being viewed in Nginx?

Add this within your server block near the top:

location ~ /\. {
    deny  all;
}

This will reject all external requests for files with names beginning with . (dot).

How to re-direct www url’s to non-www variants?

For example here is how you can re-direct all requests like http://www.example.com/yourpage to http://example.com/yourpage:

if ($host ~* ^www\.(.*)) {
    set $host_without_www $1;
    rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/yourpage', not 'www.example.net/yourpage'
}

Note: This example is from their website

How to convert Apache HTTPD rewrite rules to Nginx rewrite rules?

I have discussed some nuances above and in the articles. The single biggest tip I can give is that in Apache HTTPD the regular expression in RewriteRule is matched with the Request URI without a / at the beginning, while in Nginx it matches with a request uri with a slash at the beginning. So for example a Apache HTTPD rewrite rule such as this:

RewriteRule ^[a-z0-9_-]*-f([0-9]+)/?(p([0-9]+)\.html)?$ /viewforum.php?f=$1&start=$3 [QSA,L,NC]

becomes this in nginx:

rewrite ^/[a-z0-9_-]*-f([0-9]+)/?(p([0-9]+)\.html)?$ /viewforum.php?f=$1&start=$3 last;

Simple, isn’t it?

Note: The RewriteCond’s needs to be implemented using if directives as explained above.

How to stop logging image / static files?
How to specify an expiry date for image / static files?

# serve static files directly
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html)$ {
    access_log        off;
    expires           30d;
}

Feel free to discuss about this article in our forum.

PS. In case you are wondering hacking isn’t about breaking a software or using it for malicious purposes (cracking is). Hacking is about knowing a subject in intimate details. Unfortunately the print-media journalists often confuse between hacking and cracking and has given hacking a bad name.

PPS. What I haven’t explored yet is the performance difference between nginx and Apache HTTPD. I will update on that later.

Discussion
May 2, 2010: 9:45 am

thanks admin you power blog


J Cortina
July 8, 2009: 5:23 pm

Re your first P.S. - Let’s do without the revisionist history, shall we? The term ‘hacking’ has been used to describe malicious and/or exploitative acts for over 45 years (since the early ‘6os at least!). See the Nov 20, 1963 ‘The Tech’ (MIT Student Newspaper) for a story about the phone system there being ‘hacked’. Anyone who claims it was nothing but popular media misinformation to ‘redefine’ the term simply does not know what they’re talking about concerning the meaning and history of the term they are claiming some expertise for.


sandeep sehwag
February 25, 2009: 10:34 am

Hello sir, Gd Afternoon

I have spice mobile model no. s-7. i want the software of magic bluetooth for this. how i can download this.

November 28, 2008: 9:29 pm

In the section about serving static files if you have a url like this
http://mysite.com/users/bjs where bjs is the user’s login name it will fall into the ’static file’ trap.

This appears to fix the problem:

location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires 30d;
}

Basically force the preceeding char to be an actual ‘.’ rather than ANY character.

This one recently bit me, so I thought I would share!

- Peter

YOUR VIEW POINT
NAME : (REQUIRED)
MAIL : (REQUIRED)
will not be displayed
WEBSITE : (OPTIONAL)
YOUR
COMMENT :