Showing posts with label NGINX. Show all posts
Showing posts with label NGINX. Show all posts

Friday, April 15, 2016

Nginx php-fpm security.limit_extension issue

Just found something weird while tweaking the configurations in Nginx PHP-FPM. URL via https suddenly went offline and the server log shows something as follows:
[error] 18292#0: *1 FastCGI sent in stderr: "Access to the script '/usr/share/nginx/html' has been denied (see security.limit_extensions)", client: x.x.x.x, server: localhost, request: "GET /index.php HTTP/1.1", host: "xxx.net"

Although people suggest to turn off security.limit_extensions by setting it to nothing, it really raise me a bit of security concern.

It ends up there's one line in the config file /etc/nginx/sites-enabled/default which causes the error:
#
#
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
Comment it out is okay while the .php page loads fine if it's changed to something else:

# Fix for missing params and blank php page display problems
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO          $fastcgi_path_info;
#fastcgi_param PATH_TRANSLATED    $document_root$fastcgi_path_info;
fastcgi_param PATH_TRANSLATED    $document_root$fastcgi_script_name;
Reloading nginx server again and things are loaded up properly!









Monday, April 11, 2016

Nginx PHP-FPM display blank page for .PHP file on Ubuntu

Setting up new Nginx instance wasn't a funny thing as stated on most blogposts while it display blank page during startup. This is annoying when people set things up from scratches.

First thing first:

Check whether PHP-FPM is running:
$ ps -aux | grep php-fpm --color


$
$ ps -aux | grep php-fpm --color
root      1898  0.0  1.8 209928 18992 ?        Ss   11:48   0:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)                      
www-data  1900  0.0  0.6 210060  6660 ?        S    11:48   0:00 php-fpm: pool www                                                            
www-data  1901  0.0  0.5 210060  6088 ?        S    11:48   0:00 php-fpm: pool www   


Also, you may notice that running processes may be owned by someone else, like nginx, apache or whatsoever. Make sure user/group setting in php-fpm config file is referring to the same user/group as set in Nginx config file, like www-data/www-data.

Default location of php-fpm 7.0 config file:

/etc/php/7.0/fpm/pool.d/www.conf

Default location of Nginx config file:
/etc/nginx/sites-available/default

Back to the question about why nginx displays a balnk page instead? Let's take a look at the Nginx config file:

...
...
server {
        ...
        location ~ \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_cache  microcache;
                fastcgi_cache_key $scheme$host$request_uri$request_method;
                fastcgi_cache_valid 200 301 302 30s;
                fastcgi_cache_use_stale updating error timeout invalid_header http_500;
                fastcgi_pass_header Set-Cookie;
                fastcgi_pass_header Cookie;
                fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                fastcgi_index index.php;
                include fastcgi_params;
                # Fix for missing params and blank php page display problems
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

        }
}


The line "include fastcgi_params" actually refers to the file /etc/nginx/fastcgi_params which has various fastcgi_param variables initialized when calling. Unfortunately, two important variables went missing leading to an unknown blank page when startup.

They are SCRITP_FILENAME and PATH_TRANSLATED. Add them back to Nginx config file and PHP things execute again!

Ref: https://www.narga.net/avoid-nginx-wordpress-blank-page/







Friday, June 7, 2013

Convert .p12 bundle to server certificate and key files for Nginx

SSL certificate is a must for nowadays e-commerce site whereas newly emerged web server like Nginx has gained so much attention due to its performance when dealing with heavy traffic to the web site. Why do those people choose Nginx?

Nginx's unique architecture makes it easy to handle large number of concurrent connections at one time with low CPU and memory consumption, compared with IIS and Apache.

Nginx has also taken the place as the front-end proxy server for traditional web servers like IIS and Apache.

Now, back to the topic we are facing today.

Assuming you have received .p12 file from your trust provider, you might need to know more about what a .p12 file is.

According to wiki, PKCS #12 defines an archive file format for storing many cryptography objects as a single file. It is commonly used to bundle a private key with its X.509 certificate or to bundle all the members of a chain of trust.

This means a .p12/.pfx file contains everything we need to provide SSL services, like server certificates, CA root certificate, intermediate chain certificates and server private key.

Unlike .pem file, .p12/.pfx file is in binary form so we cannot copy and paste those blocks for use in a human readable format. It needs a conversion tool like openssl to extract necessary files for the web server like Nginx.

Nginx is also sensitive to the order of server certificate and other CA root and chain certificates in a bundle .pem file so it may not start up properly with a .pem file which has been tempered with no proper knowledge.

Here're the two commands to generate necessary certificate bundle and server key files from a .p12/.pfx bundle file which is supposed to be directly imported into IIS web erver.

#
#
#Generate certificates bundle file
> openssl pkcs12 -nokeys -in server-cert-key-bundle.p12 -out server-ca-cert-bundle.pem
#
#
#Generate server key file
> openssl pkcs12 -nocerts -nodes -in server-cert-key-bundle.p12 -out server.key
#
#

whereas you might be asked to input the password which was included in .p12 file during the creation.

In Niginx.conf, we can include these two files for SSL connection:
#
#
server {
        listen   443 default ssl;
        server_name  localhost ...;

        ssl                  on;
        ssl_certificate      /some_where/ssl_cert/server-ca-cert-bundle.pem;
        ssl_certificate_key  /some_where/ssl_cert/server.key;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;
    
#...  
#


After that, Nginx should start up properly with HTTPS protocol ready for the web site.







Monday, February 25, 2013

Auto start Nginx on Linux reboot

After compiling Nginx from the source on older release of Ubuntu server, there are some steps to be performed in order to let Nginx service start automatically after a system reboot.

A startup script can be obtained here:
https://github.com/JasonGiedymin/nginx-init-ubuntu/blob/master/nginx

This script will be saved to /etc/init.d/nginx

However, there are additional changes on this script file in order to make it running properly.

For the existing version of Nginx v1.2.7, a couple of changes are required for pointing to the correct path of related files as follows:




# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf
# pidfile:     /usr/local/nginx/logs/nginx.pid
# Provides:    nginx


PATH=/usr/local/nginx/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/nginx/sbin/nginx

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"




Once the changes are saved successfully, it'll be ready to add Nginx to the list of startup service on the server.

First, change the file permission as follows:

sudo chmod +x /etc/init.d/nginx


Second, use the following command to update the default run level of the startup script:

sudo /usr/sbin/update-rc.d -f nginx defaults 



After these, Nginx service will be started by itself during next system reboot.

You can also perform various tasks manually via the following command syntax:

sudo /etc/init.d/nginx (start|stop|reload|status)






Wednesday, November 21, 2012

Tuning and optimization of NGINX for 2 Million HTTP concurrent connections

As heard from the news about the crash of Click Frenzy website, they were going to deal with 1 million  connections. But it turned out to be more than 2 million connections.

While talking about a reliable IT infrastructure to support this level of user group at peak hours, does anyone mention about NGINX acting as the front-end server to deal with that?

An article from Taobao.com mentioned about an experiment using NGINX to simulate a condition of 2 million concurrent connections to a single server. I was surprised that people out there shared it on Twitter even it wasn't posted in plain English. Here's the translation:


Tuning and optimization of NGINX for 2 Million concurrent connections

For the server performance, one of the vital indicators is the maximum number of queries per second, i.e., qps. There are exceptions for certain types of applications that we do care more about the maximum number of concurrent connections rather than qps, although we still consider qps as one of the system performance indicators. The comet server for Twitter belongs to this kind of species. Other examples like online chat room and instant messaging applications are also similar in nature. For the introduction of Comet-typed applications, please refer to the previous posts. For this kind of system, there would be a lot of messages produced and delivered to the clients. Those client connections are on hold even during the idle time. When a huge number of clients connect to the system, a long queue of concurrent connections would be made and held by the system.

First of all, we need to analyse the resources consumptions for this kind of service. These mainly involve CPU usage, network bandwidth and memory. To optimize the system, we need to find the whereabouts of the bottleneck. Among those concurrent connections, part of them may not be sending data at all time and be considered as idle connections occasionally. These connections at idle state don’t actually exhaust the CPU or network resources, but barely occupy some spaces in memory.

Based on the assumptions above, the system can support a much higher number of concurrent connections desired, with adequate amount of system memory. Could this happen in the real world? If yes, this could also be a challenge to the CPU core for supporting such a huge client group.

To start an experiment for the theory above, we need to have a running server and a huge number of clients as well. Also, server program and client program are required to finish the tasks.

Here’s the scenario:
  • Each client initiates a connection and sends out a request to the server.
  • The connection is on hold at the server side with no actual response.
  • This state is maintained until a maximum number of concurrent connections are reached, i.e., 2 million concurrent connections.


1. Preparation of Server-side
As per the assumption above, we need to have a server with large amount of memory for the deployment of Comet application by using NGINX. Here’s the specification of the server:

  • Summary: Dell R710, 2 x Xeon E5520 2.27GHz, 23.5GB / 24GB 1333MHz
  • System: Dell PowerEdge R710 (Dell 0VWN1R)
  • Processors: 2 x Xeon E5520 2.27GHz 5860MHz FSB (16 cores)
  • Memory: 23.5GB / 24GB 1333MHz == 6 x 4GB, 12 x empty
  • Disk-Control: megaraid_sas0: Dell/LSILogic PERC 6/i, Package 6.2.0-0013, FW 1.22.02-0612,
  • Network: eth0 (bnx2):Broadcom NetXtreme II BCM5709 Gigabit Ethernet,1000Mb/s
  • OS: RHEL Server 5.4 (Tikanga), Linux 2.6.18-164.el5 x86_64, 64-bit


The program at the server-side is so simple. An NGINX based comet module can be written to achieve the purposes of accepting user request and putting the connection on hold with no response. Apart from this, Status module in NGINX can be used to monitor the maximum number of concurrent connection at real time.

Let’s tweak some system parameters on the server, within the file /etc/sysctl.conf:

net.core.somaxconn = 2048
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 4096 16777216
net.ipv4.tcp_wmem = 4096 4096 16777216
net.ipv4.tcp_mem = 786432 2097152 3145728
net.ipv4.tcp_max_syn_backlog = 16384
net.core.netdev_max_backlog = 20000
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_orphans = 131072

Then, issue the following command to make the new settings effective:
/sbin/sysctl -p


Here are a couple of things to notice:

Net.ipv4.tcp_rmem: this is used to allocate the size of READ buffer. The first one is for the minimum value, the second one is for the default value and the third one is for maximum value. To keep the memory consumption to minimum for each socket, the minimum value is set to 4096.

Net.ipv4.tcp_wmem: this is used to allocate the size of WRITE buffer. Both READ and WRITE buffer can actually affect the memory consumption of the socket within the core system.

Net.ipv4.tcp_mem is used to allocate the memory size for TCP, in terms of pages, not words. When the memory size exceeds the second parameter as defined, TCP will enter the pressure mode. At this time, TCP will try to stabilize its memory usage. In case, the memory size is reduced less than the first parameter, TCP will leave the pressure mode. However, if the memory size exceeds the third parameter, TCP will refuse to allocate extra socket for the other connections. At this moment, a whole list of log entries like “TCP: too many of orphaned sockets” will be shown by using dmesg command at the server-side.

Also, the parameters for net.ipv4.tcp_max_orphans should be set to allow a maximum number of sockets being held by no process. This should be considered carefully especially when we need to create a huge number of connections.

Apart from this, the server needs to open a certain amount of files descriptors, i.e., 2 million. There is a problem when setting a large size for file descriptors. But, no worry. Let’s talk about this later.

2. Preparation of client side
In this scenario we need to initiate a large amount of client connections. However, the number of local ports on the computer is limited. With the port range between 0 and 65535, there is a reserved range between 0 and 1023. In other words, only 64511 ports within the port range between 1024 and 65534 can be allocated. To achieve 2 million concurrent connections, 34 client computers will be required.
Of course, we can use Virtual IP to realize this number of clients. For each Virtual IP, around 64500 ports can used for binding whereas 34 Virtual IP can get things done. Fortunately, we have the company resources to carry out this experiment by using physical machines.

The default parameters set for the auto allocation of the ports is limited, i.e., from 32768 to 61000, so we need to modify the parameter on the client computer, within the file /etc/sysctl.conf:

net.ipv4.ip_local_port_range = 1024 65535

Followed by a line of commands like this to make it effective:
/sbin/sysctl -p

A program at the client side is writtern based on libevent module which continuously initiate new requests for connection.

3. Adjustment of File Descriptors
Due to a large number of socket required by Client-side and Server-side, we need to adjust the maximum value of File Descriptor.

At Client-side, we need to create more than 60,000 sockets, it’s fine to set the parameter to 100,000.

Within the file /etc/security/limits.conf, please add these two lines:
admin soft nofile 100000
admin hard nofile 100000

At Server-side, we need more than 2,000,000 sockets. That would be a problem if we set it to something like, “nofile 2000000”. In this case, the server will no longer be able to be accessed. After several attempts, it is discovered that the maximum value can only set to 1 million. After checking the source code of the kernel v2.6.25, there is a global defined value for this as 1024*1024, i.e., almost 1 million. Anyway, Linux kernel version 2.6.25 or later can be tweaked through the settings in /proc/sys/fs/nr_open. So, I can’t wait to upgrade the kernel to 2.6.32.

For the blog post about “ulimit”, please visit:

After the kernel upgrade, we can optimize it by the following command:
sudo bash -c 'echo 2000000 > /proc/sys/fs/nr_open'

Now, we can modile the nofile parameters again within the file /etc/security/limits.conf:

admin soft nofile 2000000
admin hard nofile 2000000

4. Final test
Throughout the test, “dmesg” console shows continuing messages about the newly optimized parameters for allocating server ports according to the settings in /sbin/sysctl. At the end, we have finished a test for 2 million concurrent connections.

To minimize the memory consumption for NGINX, the default value of “request_pool_size” is changed from 4k to 1k. Also, the default values of net.ipv4_wmem and net.ipv4.tcp_rmem have been changed to 4k.

At the time of 2 million connections, the following data has been collected via NGINX: 








At the same time, the condition of the system cache:




5. Conclusion
Normally, parameters like “request_pool_size” need to be adjusted during the real time. The default sizes of “net.ipv4.tcp_rmem” and “net.ipv4.tcp_wmem” should also be changed as well.