Professional Documents
Culture Documents
Nginx Secure
Nginx Secure
Nginx is a lightweight, high performance web server/reverse proxy and e-mail (IMAP/POP3) [1] proxy. It runs on UNIX, GNU/Linux, BSD variants, Mac OS X, Solaris, and Microsoft Windows. According to Netcraft, 6% of all domains on the Internet use nginx webserver. Nginx is one of a handful of servers written to address the C10K problem. Unlike traditional servers, Nginx doesn't rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture. Nginx powers several high traffic web sites, such as WordPress, Hulu, Github, and SourceForge. This page collects hints how to improve the security of nginx web servers running on Linux or UNIX like operating systems.
Do Boolean Lockdown
Run the getsebool -a command and lockdown system: getsebool -a | less getsebool -a | grep off getsebool -a | grep o To secure the machine, look at settings which are set to 'on' and change to 'off' if they do not apply to your setup with the help of setsebool command. Set correct SE Linux booleans to maintain functionality and protection. Please note
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 1 of 13
Note you need to create a new partition using fdisk and mkfs.ext3 [3] commands.
# Avoid a smurf attack net.ipv4.icmp_echo_ignore_broadcasts = 1 # Turn on protection for bad icmp error messages net.ipv4.icmp_ignore_bogus_error_responses = 1 # Turn on syncookies for SYN flood attack protection net.ipv4.tcp_syncookies = 1 # Turn on and log spoofed, source routed, and redirect packets net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 # No source routed packets here net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Turn on reverse path filtering net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Make sure no one can alter the routing tables 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 # Don't act as a router net.ipv4.ip_forward = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Turn on execshild kernel.exec-shield = 1 kernel.randomize_va_space = 1 # Tuen IPv6 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 # Optimization for port usefor LBs # Increase system file descriptor limit fs.file-max = 65535 # Allow for more PIDs (to reduce rollover problems); may break some programs 32768 kernel.pid_max = 65536
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 2 of 13
# Increase system IP port limits net.ipv4.ip_local_port_range = 2000 65000 # Increase TCP max buffer size setable using setsockopt() net.ipv4.tcp_rmem = 4096 87380 8388608 net.ipv4.tcp_wmem = 4096 87380 8388608 # Increase Linux auto tuning TCP buffer limits # min, default, and max number of bytes to use # set max to at least 4MB, or higher if you use very high BDP paths # Tcp Windows etc net.core.rmem_max = 8388608 net.core.wmem_max = 8388608 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_window_scaling = 1
See also: Linux Tuning The VM [5] (memory) Subsystem Linux Tune Network Stack [6] (Buffers Size) To Increase Networking Performance
static char ngx_http_server_string[] = "Server: nginx" CRLF; static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
static char ngx_http_server_string[] = "Server: Ninja Web Server" CRLF; static char ngx_http_server_full_string[] = "Server: Ninja Web Server" CRLF;
Save and close the file. Now, you can compile the server. Add the following in nginx.conf to turn off nginx version number displayed on all auto generated error pages: server_tokens off
mod_security provides an application level firewall for Apache. Install mod_security for all backend [7] Apache web servers. This will stop many injection attacks.
#### IPS ###### # Get server public ip SERVER_IP=$(ifconfig eth0 | grep 'inet addr:' | awk -F'inet addr:' '{ print $2}' | awk '{ print $1}' LB1_IP="204.54.1.1" LB2_IP="204.54.1.2" # Do some smart logic so that we can use damm script on LB2 too OTHER_LB="" SERVER_IP="" [[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB="$LB2_IP" || OTHER_LB="$LB1_IP" [[ "$OTHER_LB" == "$LB2_IP" ]] && OPP_LB="$LB1_IP" || OPP_LB="$LB2_IP" ### IPs ### PUB_SSH_ONLY="122.xx.yy.zz/29" #### FILES ##### BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 4 of 13
SPOOFIP="127.0.0.0/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 0.0.0.0/8 240.0.0.0/4 25 BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v "^#|^$" ${BLOCKED_IP_TDB}) ### Interfaces ### PUB_IF="eth0" # public interface LO_IF="lo" # loopback VPN_IF="eth1" # vpn / private net ### start firewall ### echo "Setting LB1 $(hostname) Firewall..." # DROP and close everything $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP # Unlimited lo access $IPT -A INPUT -i ${LO_IF} -j ACCEPT $IPT -A OUTPUT -o ${LO_IF} -j ACCEPT # Unlimited vpn / pnet access $IPT -A INPUT -i ${VPN_IF} -j ACCEPT $IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT # Drop sync $IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP # Drop Fragments $IPT -A INPUT -i ${PUB_IF} -f -j DROP $IPT $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP
# Drop NULL packets $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# Drop XMAS $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # Drop FIN packet scans $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
# Log and get rid of broadcast / multicast and invalid $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j LOG --log-prefix " Broadcast " $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j DROP $IPT $IPT $IPT $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j LOG --log-prefix " Multicast " -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j DROP -A INPUT -i ${PUB_IF} -m state --state INVALID -j LOG --log-prefix " Invalid " -A INPUT -i ${PUB_IF} -m state --state INVALID -j DROP
# Log and block spoofed ips $IPT -N spooflist for ipblock in $SPOOFIP do $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG --log-prefix " SPOOF List Block " $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP done $IPT -I INPUT -j spooflist $IPT -I OUTPUT -j spooflist $IPT -I FORWARD -j spooflist
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 5 of 13
# Allow ssh only from selected public ips for ip in ${PUB_SSH_ONLY} do $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} --destination-port 22 -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} --sport 22 -j ACCEPT done
# allow incoming ICMP ping pong stuff $IPT -A INPUT -i ${PUB_IF} -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -m $IPT -A OUTPUT -o ${PUB_IF} -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACC
# allow incoming HTTP port 80 $IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLIS $IPT -A OUTPUT -o ${PUB_IF} -p tcp --sport 80 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED # allow outgoing ntp $IPT -A OUTPUT -o ${PUB_IF} -p udp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p udp --sport 123 -m state --state ESTABLISHED -j ACCEPT # allow outgoing smtp $IPT -A OUTPUT -o ${PUB_IF} -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT ### add your other rules here #### ####################### # drop and log everything else $IPT -A INPUT -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " DEFAULT DROP " $IPT -A INPUT -j DROP exit 0
## Start: Size Limits & Buffer Overflows ## client_body_buffer_size 1K; client_header_buffer_size 1k ; client_max_body_size 1k ; large_client_header_buffers 2 1k ; ## END: Size Limits & Buffer Overflows ##
Where, 1. client_body_buffer_size 1k - (default is 8k or 16k) The directive specifies the client request body buffer size. 2. client_header_buffer_size 1k - Directive sets the headerbuffer size for the request header from client. For the overwhelming majority of requests a buffer size of 1K is sufficient. Increase this if you have a custom header or a large cookie sent from the client (e.g., wap client). 3. client_max_body_size 1k - Directive assigns the maximum accepted body size of client request, indicated by the line Content-Length in the header of request. If size is greater the given one, then the client gets the error "Request Entity Too Large" (413). Increase this when you are getting file uploads via the POST method. 4. large_client_header_buffers 2 1k - Directive assigns the maximum number and size of buffers for large headers to read from client request. By default the size of one buffer is equal to the size of page, depending on platform this either 4K or 8K, if at the end of working request connection converts to state keep-alive, then these buffers are freed. 2x1k will accept 2kB data URI. This will also help combat bad bots and DoS attacks. You also need to control timeouts to improve server performance and cut clients. Edit it as follows:
Page 6 of 13
1. client_body_timeout 10; - Directive sets the read timeout for the request body from client. The timeout is set only if a body is not get in one readstep. If after this time the client send nothing, nginx returns error "Request time out" (408). The default is 60. 2. client_header_timeout 10; - Directive assigns timeout with reading of the title of the request of client. The timeout is set only if a header is not get in one readstep. If after this time the client send nothing, nginx returns error "Request time out" (408). 3. keepalive_timeout 5 5; - The first parameter assigns the timeout for keep-alive connections with the client. The server will close connections after this time. The optional second parameter assigns the time value in the header Keep-Alive: timeout=time of the response. This header can convince some browsers to close the connection, so that the server does not have to. Without this parameter, nginx does not send a Keep-Alive header (though this is not what makes a connection "keep-alive"). 4. send_timeout 10; - Directive assigns response timeout to client. Timeout is established not on entire transfer of answer, but only between two operations of reading, if after this time client will take nothing, then nginx is shutting down the connection.
### Directive describes the zone, in which the session states are stored i.e. store in slimits. ### ### 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session ### limit_zone slimits $binary_remote_addr 5m ; ### Control maximum number of simultaneous connections for one session i.e. ### ### restricts the amount of connections from a single ip address ### limit_conn slimits 5;
The above will limits remote clients to no more than 5 concurrently "open" connections per remote ip address.
HowTo: Use nginx map [10] to block image hotlinking. This is useful if you want to block tons of domains.
Edit nginx.conf and update it as follows: server { server_name example.com; listen 443; ssl on; ssl_certificate /usr/local/nginx/conf/server.crt; ssl_certificate_key /usr/local/nginx/conf/server.key; access_log /usr/local/nginx/logs/ssl.access.log; error_log /usr/local/nginx/logs/ssl.error.log; }
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 9 of 13
Restart the nginx: # /usr/local/nginx/sbin/nginx -s reload See also: For more information, read the Nginx SSL documentation [12].
# Disallow dangerous functions disable_functions = phpinfo, system, mail, exec ## Try to limit resources ##
# Maximum execution time of each script, in seconds max_execution_time = 30 # Maximum amount of time each script may spend parsing request data max_input_time = 60 # Maximum amount of memory a script may consume (8MB) memory_limit = 8M # Maximum size of POST data that PHP will accept. post_max_size = 8M # Whether to allow HTTP file uploads. file_uploads = Off # Maximum allowed size for uploaded files. upload_max_filesize = 2M # Do not expose PHP error messages to external users display_errors = Off # Turn on safe mode safe_mode = On # Only allow access to executables in isolated directory safe_mode_exec_dir = php-required-executables-path # Limit external access to PHP environment safe_mode_allowed_env_vars = PHP_ # Restrict PHP information leakage expose_php = Off # Log all errors log_errors = On # Do not register globals for input data register_globals = Off # Minimize allowable PHP post size post_max_size = 1K # Ensure PHP redirects appropriately cgi.force_redirect = 0 # Disallow uploading unless necessary file_uploads = Off # Enable SQL safe mode sql.safe_mode = On # Avoid Opening remote files
nixCraft is GIT UL++++ W+++ C++++ M+ e+++ dPage 10 of 13
allow_url_fopen = Off
See also: PHP Security: Limit Resources Used By Script [13] PHP.INI settings: Disable exec, shell_exec, system, popen and Other Functions To Improve Security [14]
/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 service iptables save
webserver_ip="202.54.1.1" table <abusive_ips> persist block in quick from <abusive_ips> pass in on $ext_if proto tcp to $webserver_ip port www flags S/SA keep state (max-src-conn 100, max-
Please adjust all values as per your requirements and traffic (browsers may open multiple connections to your site). See also: 1. Sample PF firewall [20] script. 2. Sample Iptables firewall [21] script.
Page 11 of 13
Sample outputs: -rw-r--r-- 1 root root 925 Jan -rw-r--r-- 1 root root 52 Jan -rw-r--r-- 1 root root 134 Jan 3 00:50 error4xx.html 3 10:00 error5xx.html 3 00:52 index.html
You must delete unwated backup files created by vi or other text editor: # 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 -delete option to find command and it will get rid of those files too.
/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner vivek -p tcp --dport 80 -m state --state NEW,E
Add above rule to your iptables based shell script. Do not allow nginx web server user to connect outside.
Conclusion
Your nginx server is now properly harden and ready to server webpages. However, you should be consulted further resources for your web applications security needs. For example, wordpress or any other third party apps has its own security requirements. References: HowTo: Setup nginx reverse proxy [25] and HA cluser with the help of keepalived. nginx wiki [26] - The official nginx wiki. OpenBSD specific Nginx installation [27] and security how to.
Important Message from nixCraft: 4000+ howtos and counting! Want to read more Linux / UNIX howtos, tips and tricks? We request you to sign up for the following to ensure that you make the most from our guides / howtos: 1. RSS feed for nixCraft - Get intimated about our new howtos / faqs as soon as it is released. 2. Daily email newsletter or weekly newsletter - Get intimated about our new howtos / faqs as soon as it is released via email.
Page 12 of 13
Article printed from nixCraft: http://www.cyberciti.biz/ URL to article: http://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html URLs in this post: [1] Image: http://www.cyberciti.biz/faq/category/nginx/ [2] SELinux for CentOS / RHEL: http://www.cyberciti.biz/faq/rhel-fedora-redhat-selinux-protection/ [3] fdisk and mkfs.ext3: http://www.cyberciti.biz/faq/redhat-centos-linux-ext3-filesystem-format-command/ [4] /etc/sysctl.conf: http://www.cyberciti.biz/faq/linux-kernel-etcsysctl-conf-security-hardening/ [5] Linux Tuning The VM: http://www.cyberciti.biz/faq/linux-kernel-tuning-virtual-memory-subsystem/ [6] Linux Tune Network Stack: http://www.cyberciti.biz/faq/linux-tcp-tuning/ [7] mod_security for all backend: http://www.cyberciti.biz/faq/rhel-fedora-centos-httpd-mod_security-configuration/ [8] project home: http://sourceforge.net/projects/selinuxnginx/ [9] RFC 2616: http://www.ietf.org/rfc/rfc2616.txt [10] Use nginx map: http://nginx.org/pipermail/nginx/2007-June/001082.html [11] by ip address: http://www.cyberciti.biz/faq/linux-unix-nginx-access-control-howto/ [12] Nginx SSL documentation: http://wiki.nginx.org/NginxHttpSslModule [13] PHP Security: Limit Resources Used By Script: http://www.cyberciti.biz/faq/php-resources-limits/ [14] PHP.INI settings: Disable exec, shell_exec, system, popen and Other Functions To Improve Security: http://www.cyberciti.biz/faq/linux-unix-apache-lighttpd-phpini-disable-functions/ [15] can use traditional chroot kind: http://www.cyberciti.biz/faq/howto-run-nginx-in-a-chroot-jail/ [16] FreeBSD jails: http://www.cyberciti.biz/faq/howto-setup-freebsd-jail-with-ezjail/ [17] XEN: http://www.cyberciti.biz/tips/rhel-centos-xen-virtualization-installation-howto.html [18] OpenVZ: http://www.cyberciti.biz/faq/openvz-rhel-centos-linux-tutorial/ [19] will drop incoming: http://www.cyberciti.biz/tips/lighttpd-set-throughput-connections-per-ip.html [20] PF firewall: http://bash.cyberciti.biz/firewall/pf-firewall-script/ [21] Iptables firewall: http://bash.cyberciti.biz/firewall/linux-iptables-firewall-shell-script-for-standalone-server/ [22] ipt_owner module attempts: http://www.cyberciti.biz/tips/block-outgoing-network-access-for-a-single-user-frommy-server-using-iptables.html [23] audit service: http://www.cyberciti.biz/tips/linux-audit-files-to-see-who-made-changes-to-a-file.html [24] follow our "Linux Server Hardening": http://www.cyberciti.biz/tips/linux-security.html [25] nginx reverse proxy: http://www.cyberciti.biz/faq/series/keepalived-nginx-ha-cluster/ [26] nginx wiki: http://wiki.nginx.org/Main [27] Nginx installation: https://calomel.org/nginx.html
Copyrighted material Copyright 2004-2013 nixCraft. All rights reserved. This print / pdf version is for personal non-commercial use only. Unless otherwise indicated, the documents and graphics stored on this Web server, www.cyberciti.biz, are copyrighted. Links to these documents are permitted and encouraged. No copies may be made without permission. More details - http://www.cyberciti.biz/tips/copyright
Page 13 of 13