libraries
and internal_data
.
server {
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm index.php;
access_log /var/www/logs/example.com.access.log;
location / {
try_files $uri $uri/ /index.php?$uri&$args;
}
location ~ /(internal_data|library) {
internal;
}
location ~ \.php$ {
fastcgi_pass unix:/tmp/php.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
For a XenForo installation in a sub directory xenforo
, the configuration should be like this:
server {
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm index.php;
access_log /var/www/logs/example.com.access.log;
location /xenforo/ {
try_files $uri $uri/ /xenforo/index.php?$uri&$args;
}
location ~ /xenforo/(internal_data|library) {
internal;
}
location ~ \.php$ {
fastcgi_pass unix:/tmp/php.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
]]>This configuration file :
- Redirects www sub domain to the bare domain along with any parked domains.
- Prevents external access to files and directories like config.php, avatar upload directory, etc.
- Sets proper Expires header for images.
server {
listen [::]:80;
server_name www.domain.com parkeddomain.com *.parkeddomain.com;
rewrite ^ http://domain.com$request_uri? permanent;
}
server {
listen [::]:80;
server_name domain.com;
root /var/www/domain.com;
index index.php index.html index.htm;
access_log /var/logs/domain.com.access.log;
location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|store) {
deny all;
return 403;
}
location ~* \.(gif|jpe?g|png|css)$ {
expires 30d;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/tmp/php.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
]]>autoindex
is set to off
.These are some among many cases where a 403 Forbidden response is intentionally returned. But here we will talk about the causes of 403 responses that are unintentional/not desired which generally occur as a result of misconfiguration on the server side.
This is the most common cause of this error. By permissions, I do not only mean the permissions for the file that is being accessed. In order to serve a file, Nginx needs to have read permissions for the file as well as execute permissions for every hierarchial parent directory of the file to chdir to it. For example, to access the file located at -
/usr/share/myfiles/image.jpg
Nginx needs to have read permissions for the file as well as execute permissions for /
, /usr
, /usr/share
and /usr/share/myfiles
. If you use the standard 755 for directories and 644 for files (umask: 022), you should not run into this problem.
To check for ownership and permissions on a path, we can use the namei
utility like this -
$ namei -l /var/www/vhosts/example.com
f: /var/www/vhosts/example.com
drwxr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x www-data www-data www
drwxr-xr-x www-data www-data vhosts
drwxr-xr-x clara clara example.com
Sometimes, the index directive does not contain the desired directory index. For example, for a standard setup with PHP, the index directive should be -
index index.html index.htm index.php;
According to this example, when a directory is acessed directly, Nginx will try to serve index.html, then index.htm and index.php after that. If none of them are found, Nginx will return a 403 header. If index.php were not defined in the root directive, Nginx would have returned 403 without checking for the existence of index.php.
Similarly, for a Python setup, index.py should be defined as a directory index.
These are the most common causes of undesired 403 responses. Feel free to leave a comment if you are still getting 403s.
]]>CloudFlare is an innovative service, providing webmasters with a CDN (Content Delivery Network) and many other things. Among these other things, it provides an IP geolocation service using which we can use to redirect/block visitors from specific countries.
We need to first enable ‘IP Geolocation’ in the CloudFlare settings for this to work -
We also need to make sure that the A record for the domain/sub domain is being proxied though the CloudFlare proxy. So, enable CloudFlare for the relevant A record from the DNS settings if it hasn’t been set accordingly.
If everything is done properly, the HTTP_CF_IPCOUNTRY environment variable should contain the country code for the visitor. To test it, we can write a small script in Perl.
1 2 |
|
Run the script and it should show you your country code. A list of country codes can be found here.
Now, we need to take care of the Nginx configuration. We need to map the environment variable to a variable of our own, so that the value of our variable changes depending on whether we want to allow visitors from the country or not.
We need to put the following code inside the http block but outside the server
block for your website. It can be put in /etc/nginx/nginx.conf
inside the
HTTP block or in your vhosts file, outside of the server block.
map $http_cf_ipcountry $allow {
default yes;
CN no;
MX no;
NO no;
}
This sets $allow
to yes or no, depending on the country of the visitor.
Here, we are setting the variable to no if the visitor is from China, Mexico,
or Norway. We can also set the default to no, and allow countries one by one
if we need to allow only a few countries and block all others. Now that the
variable is set, we need to instruct Nginx to serve a 403 page to the visitors
from the blocked countries. Add this anywhere inside the server block :
if ($allow = no) {
return 403;
}
This will make Nginx return a 403 Forbidden HTTP status code. A custom 403 error page can also be defined to make the error page more helpful.
If you are not using CloudFlare, you can still block visitors by country using the GeoIP module.
]]>Download it : http://nginx.org/en/download.html
The changes include :
Change: now double quotes are encoded in an “echo” SSI-command output. Thanks to Zaur Abasmirzoev.
Feature: the “image_filter_sharpen” directive.
Bugfix: a segmentation fault might occur in a worker process if SNI was used; the bug had appeared in 1.0.9.
Bugfix: SIGWINCH signal did not work after first binary upgrade; the bug had appeared in 1.0.9.
Bugfix: the “If-Modified-Since”, “If-Range”, etc. client request header lines might be passed to backend while caching; or not passed without caching if caching was enabled in another part of the configuration.
Bugfix: in the “scgi_param” directive, if complex parameters were used.
Bugfix: “add_header” and “expires” directives did not work if a request was proxied and response status code was 206.
Bugfix: in the “expires @time” directive.
Bugfix: in the ngx_http_flv_module. Thanks to Piotr Sikora.
Bugfix: in the ngx_http_mp4_module.
Bugfix: nginx could not be built on FreeBSD 10.
Bugfix: nginx could not be built on AIX.
Download it : http://nginx.org/en/download.html
The changes include :
Bugfix: a segmentation fault might occur in a worker process if resolver got a big DNS response. Thanks to Ben Hawkes.
Bugfix: in cache key calculation if internal MD5 implementation was used; the bug had appeared in 1.0.4.
Bugfix: the module ngx_http_mp4_module sent incorrect “Content-Length” response header line if the “start” argument was used. Thanks to Piotr Sikora.
Download it : http://nginx.org/en/download.html
The changes include :
Change: now the 0x7F-0x1F characters are escaped as \xXX in an access_log.
Change: now SIGWINCH signal works only in daemon mode.
Feature: “proxy/fastcgi/scgi/uwsgi_ignore_headers” directives support the following additional values: X-Accel-Limit-Rate, X-Accel-Buffering, X-Accel-Charset.
Feature: decrease of memory consumption if SSL is used.
Feature: accept filters are now supported on NetBSD.
Feature: the “uwsgi_buffering” and “scgi_buffering” directives. Thanks to Peter Smit.
Bugfix: a segmentation fault occurred on start or while reconfiguration if the “ssl” directive was used at http level and there was no “ssl_certificate” defined.
Bugfix: some UTF-8 characters were processed incorrectly. Thanks to Alexey Kuts.
Bugfix: the ngx_http_rewrite_module directives specified at “server” level were executed twice if no matching locations were defined.
Bugfix: a socket leak might occurred if “aio sendfile” was used.
Bugfix: connections with fast clients might be closed after send_timeout if file AIO was used.
Bugfix: in the ngx_http_autoindex_module.
Bugfix: the module ngx_http_mp4_module did not support seeking on 32-bit platforms.
Bugfix: non-cacheable responses might be cached if “proxy_cache_bypass” directive was used. Thanks to John Ferlito.
Bugfix: cached responses with an empty body were returned incorrectly; the bug had appeared in 0.8.31.
Bugfix: 201 responses of the ngx_http_dav_module were incorrect; the bug had appeared in 0.8.32.
Bugfix: in the “return” directive.
Bugfix: the “ssl_verify_client”, “ssl_verify_depth”, and “ssl_prefer_server_ciphers” directives might work incorrectly if SNI was used.
Download it : http://nginx.org/en/download.html
The changes include :
Download it : http://nginx.org/en/download.html
The changes include :
Change: now if total size of all ranges is greater than source response size, then nginx disables ranges and returns just the source response.
Feature: the “max_ranges” directive.
Feature: the module ngx_http_mp4_module.
Feature: the “worker_aio_requests” directive.
Bugfix: if nginx was built –with-file-aio it could not be run on Linux kernel which did not support AIO.
Bugfix: in Linux AIO error processing. Thanks to Hagai Avrahami.
Bugfix: in Linux AIO combined with open_file_cache.
Bugfix: open_file_cache did not update file info on retest if file was not atomically changed.
Bugfix: reduced memory consumption for long-lived requests.
Bugfix: in the “proxy/fastcgi/scgi/uwsgi_ignore_client_abort” directives.
Bugfix: nginx could not be built on MacOSX 10.7.
Bugfix: in the “proxy/fastcgi/scgi/uwsgi_ignore_client_abort” directives.
Bugfix: request body might be processed incorrectly if client used pipelining.
Bugfix: in the “request_body_in_single_buf” directive.
Bugfix: in “proxy_set_body” and “proxy_pass_request_body” directives if SSL connection to backend was used.
Bugfix: nginx hogged CPU if all servers in an upstream were marked as “down”.
Bugfix: a segmentation fault might occur during reconfiguration if ssl_session_cache was defined but not used in previous configuration.
Bugfix: a segmentation fault might occur in a worker process if many backup servers were used in an upstream.
Download it : http://nginx.org/en/download.html
The changes include :
Feature: cache loader run time decrease.
Feature: loading time decrease of configuration with large number of HTTPS sites.
Feature: now nginx supports ECDHE key exchange ciphers. Thanks to Adrian Kotelba.
Feature: the “lingering_close” directive.
Feature: now shared zones and caches use POSIX semaphores on Solaris. Thanks to Den Ivanov.
Bugfix: nginx could not be built on Linux 3.0.
Bugfix: a segmentation fault might occur in a worker process if “fastcgi/scgi/uwsgi_param” directives were used with values starting with “HTTP_”; the bug had appeared in 0.8.40.
Bugfix: in closing connection for pipelined requests.
Bugfix: nginx did not disable gzipping if client sent “gzip;q=0” in “Accept-Encoding” request header line.
Bugfix: in timeout in unbuffered proxied mode.
Bugfix: memory leaks when a “proxy_pass” directive contains variables and proxies to an HTTPS backend.
Bugfix: in parameter validaiton of a “proxy_pass” directive with variables. Thanks to Lanshun Zhou.
Bugfix: SSL did not work on QNX.
Bugfix: SSL modules could not be built by gcc 4.6 without –with-debug option.
location ~ \.(jpe?g|png|gif)$ {
valid_referers none blocked mysite.com *.mysite.com;
if ($invalid_referer) {
return 403;
}
}
Use the pipe (“|”) to separate file extensions you want to hotlink protect.
The valid_referers
directive contains the list of site for whom hotlinking
is allowed. Here is an explanation of the parameters for the valid_referers
directive :
You can also tweak the location directive for blocking files from a specific directory. Like this :
location /images/ {
valid_referers none blocked mysite.com *.mysite.com;
if ($invalid_referer) {
return 403;
}
}
This will hotlink protect every file in any images directory.
]]>server_tokens
directive in your Nginx configuration. The server_tokens directive can be used either in the http, server or location block.
Just set server_tokens
to off
(it is set to on
by default) to hide your Nginx version in all externally visible places.
server_tokens off;
Just like using Apache’s ServerSignature and ServerTokens directive, your Nginx version should now be hidden in the server signature and the default error pages. To check the server headers, use the HTTP Header Checker utility from Webconfs.com.
]]>Example outputs :
$ nginx -v
nginx version: nginx/0.8.54
$ nginx -V
nginx version: nginx/0.8.54
TLS SNI support enabled
configure arguments: --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl --with-mail --with-mail_ssl_module --add-module=/build/buildd/nginx-0.8.54/debian/modules/nginx-upstream-fair
]]>Download it : http://nginx.org/en/download.html
The changes include :
Install these packages :
apt-get install nginx php5-cgi
We’ll now replace Nginx’s package maintainer’s vhosts file with our own.
mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.old
vi /etc/nginx/sites-available/default
Put this in the file :
server {
listen [::]:80;
server_name example.com; # Replace this with your own
root /var/www/example.com;
index index.html index.htm index.php;
access_log /var/www/logs/example.com.access.log;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/tmp/php.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Now, there are some tutorials on the internet which wrongly configure Nginx and introduce an arbitrary code execution bug. Note that Nginx passes a request to the php-cgi daemon if the REQUEST_URI
has a trailing .php
. It does not check whether the file exists or not. Suppose a request is made for /images/dog.jpg/test.php
. Nginx will match the trailing .php
and pass the request to php-cgi. Now, if test.php does not exist and cgi.fix_pathinfo
is set to 1, php-cgi will try to execute /images/dog.jpg
with /test.php
as pathinfo. This is especially dangerous if you have a public upload directory. In our configuration, this will not happen even if cgi.fix_pathinfo
is set to 1. The try_files $uri =404;
line checks for the existence of the .php file and returns a 404 response header if it does not exist. Alternatively, cgi.fix_pathinfo
can be set to 0, but is is not required as our configuration takes care of it.
Now we’ll use a Debian init script to control the php-cgi daemon which will be running on port 9000.
vi /etc/init.d/php-fcgi
Add this in the file :
#!/bin/bash
### BEGIN INIT INFO
# Provides: php-cgi
# Required-Start: networking
# Required-Stop: networking
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start the PHP FastCGI daemon.
### END INIT INFO
BIND=/tmp/php.socket
USER=www-data
PHP_FCGI_CHILDREN=2
PHP_FCGI_MAX_REQUESTS=5000
PHP_CGI=/usr/bin/php-cgi
PHP_CGI_NAME=`basename $PHP_CGI`
PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND"
RETVAL=0
start() {
echo -n "Starting PHP FastCGI: "
start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS
RETVAL=$?
echo "$PHP_CGI_NAME."
}
stop() {
echo -n "Stopping PHP FastCGI: "
killall -q -w -u $USER $PHP_CGI
RETVAL=$?
echo "$PHP_CGI_NAME."
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage: php-fcgi {start|stop|restart}"
exit 1
;;
esac
exit $RETVAL
This can also be done in one line if you have shell access on your server :
wget http://nginxlibrary.com/downloads/php-fcgi/php-fcgi -O /etc/init.d/php-fcgi
Give the file executable permissions and make it start during booting :
chmod +x /etc/init.d/php-fcgi && insserv php-fcgi
Finally, start the fastcgi daemon :
invoke-rc.d php-fcgi start
To check that it is working properly, create this file :
vi /var/www/example.com/info.php
Put this in it :
<?php phpinfo(); ?>
Now go to http://example.com/info.php
and you’ll get the PHP information
page showing information about the loaded modules.
Now, there are a couple of options you can change in the PHP-FastCGI init
script, namely, PHP_FCGI_CHILDREN
and PHP_FCGI_MAX_REQUESTS
.
PHP_FCGI_CHILDREN
specifies the number of child processes the php-cgi master
process will spawn. Usually, two, or, even one is sufficient for a medium-
traffic site. PHP_FCGI_MAX_REQUESTS
specifies the number of requests each
child process will serve before being terminated and respawned.
Let us first add the testing/unstable repositories to the software sources list.
vi /etc/apt/sources.list
Add these lines at the end of the file :
deb http://ftp.debian.org/debian/ testing main contrib non-free
deb-src http://ftp.debian.org/debian/ testing main contrib non-free
Replace testing
with unstable
if you want to add the unstable repositories
instead of testing.
Now we need to pin the nginx package in testing/unstable to a higher priority so that it gets selected. Actually, in Debian, nginx is a meta-package that selects the nginx-full package. So, if you want to use nginx-light or nginx-extras, use them instead of just “nginx”.
vi /etc/apt/preferences
Add these lines :
Package: nginx
Pin: release a=testing
Pin-Priority: 900
As explained before, you can use nginx-light or nginx-extra instead of nginx here. You can also use unstable instead of testing.
Now, run :
apt-get update
Check whether the newer version of nginx is selected for install by running :
apt-cache policy nginx
Finally, install/upgrade nginx by running :
apt-get install nginx
or
apt-get upgrade nginx
You’ll have a relatively newer version of Nginx installed after finishing this.
]]>Download it : http://nginx.org/en/download.html
The changes include :
Download it : http://nginx.org/en/download.html
The changes include :
Feature: the “auth_basic_user_file” directive supports “$apr1”, “{PLAIN}”, and “{SSHA}” password encryption methods. Thanks to Maxim Dounin.
Feature: the “geoip_org” directive and $geoip_org variable. Thanks to Alexander Uskov, Arnaud Granal, and Denis F. Latypoff.
Feature: ngx_http_geo_module and ngx_http_geoip_module support IPv4 addresses mapped to IPv6 addresses.
Bugfix: a segmentation fault occurred in a worker process during testing IPv4 address mapped to IPv6 address, if access or deny rules were defined only for IPv6; the bug had appeared in 0.8.22.
Bugfix: a cached reponse may be broken if proxy/fastcgi/scgi/ uwsgi_cache_bypass and proxy/fastcgi/scgi/uwsgi_no_cache directive values were different; the bug had appeared in 0.8.46.
Here’s how the .htaccess file looks like :
Order Allow,Deny
Deny from All
Order Allow,Deny
Deny from All
And here’s what you need to add to your Nginx configuration file in order to duplicate that behaviour :
location ~ /config.php|/common.php {
deny all;
}
This will deny access to all instances of config/common.php located in the document root, regardless of where they are located.
]]>Download it : http://nginx.org/en/download.html
The changes include :