Nginx is a lightweight, high-performance web server/reverse proxy and email proxy (IMAP/POP3) that runs on UNIX, GNU/Linux, BSD variants, MAC
OS X, Solaris, and Microsoft
on Windows. According to Netcraft survey data, 6% of domain names on the Internet use Nginx
Web server. Nginx is one of the servers that solve the C10K problem. Unlike traditional servers, Nginx does not rely on threads to process requests. Instead, it uses a more scalable event-driven (asynchronous) architecture. Nginx is used on many high traffic websites such as WordPress, Hulu, Github and SourceForge.
The main purpose of this article is to introduce how to improve the security of Nginx web server running on Linux or UNIX-like operating system.
Nginx default configuration file and default port
◆ /usr/local/nginx/conf/ –
Nginx server configuration directory, /usr/local/nginx/conf/nginx.conf is the main configuration file
◆ /usr/local/nginx/html/ – default document location
◆ /usr/local/nginx/logs/ – default log file location
◆ Nginx HTTP default port: TCP 80
◆ Nginx HTTPS default port: TCP 443
You can use the following command to test whether the configuration of Nginx is correct:
# /usr/local/nginx/sbin/nginx -t
Example output:
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
configuration file /usr/local/nginx/conf/nginx.conf test is successful
To make the modified configuration take effect, execute the following command:
# /usr/local/nginx/sbin/nginx -s reload
To stop the server, run:
# /usr/local/nginx/sbin/nginx -s stop
1. Enable SELinux
SELinux (Security-Enhanced Linux) is a Linux kernel function that provides a mechanism to support access control security policies and provides great security protection capabilities. It can prevent most system root-level attacks. Please refer to “How to install on CentOS/Red
Enable SELinux on the Hat system” (http://www.cyberciti.biz/faq/rhel-fedora-redhat-selinux-protection/).
Run the getsebool -a command to view SELinux settings:
getsebool -a | lessgetsebool -a | grep offgetsebool -a | grep
o
Then use the setsebool command to enable the required configuration items. Note: After enabling SELinux, the system overhead will usually increase by 2-8% on RHEL or CentOS.
2. Provide minimum permissions through mount parameters
Create a separate partition for your /html/php files, for example, create a /dev/sda5 partition to mount on /ngnix, make sure /ngnix is mounted with noexec, nodev and noseuid permissions. Here is an example of my mount:
LABEL=/nginx
/nginx
ext3 defaults,nosuid,noexec,nodev 1 2
Note that you need to create a new partition using fdisk and the mkfs.ext3 command.
3. Reinforce through /etc/sysctl.conf
The Linux kernel and network settings can be controlled and configured via /etc/sysctl.conf.
Also, please refer to:
# Avoid amplification attacks
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable malicious icmp error message protection
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Enable SYN flood attack protection
net.ipv4.tcp_synCOOKIEs = 1
# Enable and log spoofing, source routing and redirecting packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians=1
# Process passively routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Enable reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Make sure no one can modify the routing table
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects=0
# Do not act as a router
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Enable execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# IPv6 settings
net.ipv6.conf.default.router_solicitatiOns= 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autocOnf= 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
# Optimize the port used by LB
# Increase system file descriptor limit
fs.file-max = 65535
# Allow more PIDs (less rollover issues); may break some programs 32768
kernel.pid_max = 65536
# Increase the system IP port limit
net.ipv4.ip_local_port_range = 2000 65000
# Increase TCP max buffer size<brMaximum size of POST data
post_max_size = 8M
# Whether to allow HTTP file upload
file_uploads = Off
# The maximum file size allowed to be uploaded
upload_max_filesize = 2M
# Do not expose PHP error messages to external users
display_errors = Off
# Enable Safe Mode
safe_mode = On
# Only allow access to executables in the quarantined directory
safe_mode_exec_dir = php-required-executables-path
# Restrict external access to PHP resources
safe_mode_allowed_env_vars = PHP_
# Limit disclosure of PHP information
expose_php = Off
# log all errors
log_errors = On
# Do not register globals for input data
register_globals = Off
# Minimize allowed php post size
post_max_size = 1K
# Make sure PHP redirects correctly
cgi.force_redirect = 0
# Do not upload unless necessary
file_uploads = Off
# Enable SQL safe mode
sql.safe_mode = On
# Avoid opening remote files
allow_url_fopen = Off
Also, please refer to “PHP Security: Limit resources used by scripts” (http://www.cyberciti.biz/faq/php-resources-limits/), “PHP.INI: Disable exec, shell_exec, system, popen and other Functions Improve Security” (http://www.cyberciti.biz/faq/linux-unix-apache-lighttpd-phpini-disable-functions/).
17. Run Nginx in Chroot Jail (container) as much as possible
Chroot Nginx
Jail minimizes the risk of being attacked, it isolates the web server to a dedicated area of the file system, note you cannot setup Nginx using the traditional chroot method, but you can use FreeBSD
jails, Xen or OpenVZ virtualization, which also use the concept of containers.
18. Limit the connection of each IP at the firewall level
The web server has to keep an eye on connections and there is a connection per second limit, both pf and iptables can jam the end user before they can access the Nginx server.
Linux iptables: Nginx connections stuck every second
The following example shows that if an IP attempts to connect to port 80 more than 15 times in 60 seconds, iptables will drop incoming connections from it:
/sbin/iptables -A INPUT -p tcp –dport 80 -i eth0 -m state
–state NEW -m recent –set
/sbin/iptables -A INPUT -p tcp –dport 80 -i eth0 -m state –state
NEW -m recent –update –seconds 60 –hitcount 15 -j DROP
service iptables save
BSD PF: Nginx connections stuck every second
Edit /etc/pf.conf and make the following updates. The following command limits the maximum number of connections from each source to 100, and 15/5 specifies the limit on the number of connections within a certain time span. Here, the maximum number of connections within 5 seconds is
15. If someone violates this rule, he will be added to the abusive_ips table, and he will not be able to connect in the future. Finally refresh all states.
ebserver_ip=”202.54.1.1″
table persist
block in quick from
pass in on $ext_if proto tcp to $webserver_ip port www flags S/SA
keep state (max-src-conn 100, max-src-conn-rate 15/5,
overload flush)
Please adjust all values according to your needs and communication traffic (browser may open multiple connections).
In addition, please refer to “PF Firewall Script Example” (http://bash.cyberciti.biz/firewall/pf-firewall-script/), “iptables Firewall Script Example” (http://bash.cyberciti.biz/firewall/ linux-iptables-firewall-shell-script-for-standalone-server/).
19. Configure the operating system to protect the web server
In addition to enabling SELinux, you must also set the correct permissions for the /nginx directory. The system user name for running Nginx is nginx, but the files in DocumentRoot (/nginx or /usr/local/nginx/html) should not be
Belongs to this user and he cannot modify it either. Use the following command to find files with incorrect permissions:
# find /nginx -user nginx
# find /usr/local/nginx/html -user nginx
Please make sure to change the owner of the file to root or other users. A typical permission setting is as follows:
# ls -l /usr/local/nginx/html/
Example output:
-rw-r–r– 1 root root 925 Jan 3 00:50 error4xx.html
-rw-r–r– 1 root root 52 Jan 3 10:00 error5xx.html
-rw-r–r– 1 root root 134 Jan 3 00:52 index.html
Also, you must delete unnecessary backup files created by vi or other text editors:
# find /nginx -name ‘.?*’ -not -name .ht* -or -name ‘*~’ -or
-name ‘*.bak*’ -or -name ‘*.old*’
# find /usr/local/nginx/html/ -name ‘.?*’ -not -name .ht* -or -name
‘*~’ -or -name ‘*.bak*’ -or -name ‘*.old*’
Pass the -delete parameter to the find command and it will automatically delete these files.
20. Limit outbound Nginx connections
Attackers may use tools such as wget to download files on your web server, and use iptables to block outbound connections from Nginx users. The ipt_owner module can match the characteristics of various package creators, and only those in the OUTPUT chain are valid. Here, the vivek user is allowed to use port 80 to connect to external resources (especially useful for RHN access or fetching CentOS updates through repositories).
/sbin/iptables -A OUTPUT -o eth0 -m owner –uid-owner vivek -p
tcp –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
Add the above rule to your iptables base shell script to not allow nginx web server users to connect to external resources.
Bonus Tip: Watching Logs and Auditing
Check the log file, you can find some whereabouts and attack methods of the attacker.
# grep “/login.php??” /usr/local/nginx/logs/access_log
# grep “…etc/passwd” /usr/local/nginx/logs/access_log
# egrep -i “denied|error|warn” /usr/local/nginx/logs/error_log
The Auditd service provides the system audit function, starts SELinux events, authentication events, file modification, account modification and other audit services, as usual, first close all services, and then open the “Linux server hardening” .biz/tips/linux-security.html).
Summary
With these settings, your Nginx server can provide external services, but you should further check additional resources according to application security needs. For example, WordPress or other third-party programs have their own security requirements.
r -name ‘*~’ -or
-name ‘*.bak*’ -or -name ‘*.old*’
# find /usr/local/nginx/html/ -name ‘.?*’ -not -name .ht* -or -name
‘*~’ -or -name ‘*.bak*’ -or -name ‘*.old*’
Pass the -delete parameter to the find command and it will automatically delete these files.
20. Limit outbound Nginx connections
Attackers may use tools such as wget to download files on your web server, and use iptables to block outbound connections from Nginx users. The ipt_owner module can match the characteristics of various package creators, and only those in the OUTPUT chain are valid. Here, the vivek user is allowed to use port 80 to connect to external resources (especially useful for RHN access or fetching CentOS updates through repositories).
/sbin/iptables -A OUTPUT -o eth0 -m owner –uid-owner vivek -p
tcp –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
Add the above rule to your iptables base shell script to not allow nginx web server users to connect to external resources.
Bonus Tip: Watching Logs and Auditing
Check the log file, you can find some whereabouts and attack methods of the attacker.
# grep “/login.php??” /usr/local/nginx/logs/access_log
# grep “…etc/passwd” /usr/local/nginx/logs/access_log
# egrep -i “denied|error|warn” /usr/local/nginx/logs/error_log
The Auditd service provides the system audit function, starts SELinux events, authentication events, file modification, account modification and other audit services, as usual, first close all services, and then open the “Linux server hardening” .biz/tips/linux-security.html).
Summary
With these settings, your Nginx server can provide external services, but you should further check additional resources according to application security needs. For example, WordPress or other third-party programs have their own security requirements.