20步打造最安全的Nginx Web服务器之一

服务器
ginx是一个轻量级的,高性能的Web服务器以及反向代理和邮箱(IMAP/POP3)代理服务器。它运行在UNIX,GNU/Linux,BSD各种版本,Mac OS X,Solaris和Windows。根据调查统计,6%的网站使用Nginx Web服务器。

Nginx是一个轻量级的,高性能的Web服务器以及反向代理和邮箱(IMAP/POP3)代理服务器。它运行在UNIX,GNU/Linux,BSD各种版本,Mac OS X,Solaris和Windows。根据调查统计,6%的网站使用Nginx Web服务器。Nginx是少数能处理C10K问题的服务器之一。跟传统的服务器不同,Nginx不依赖线程来处理请求。相反,它使用了更多的可扩展的事件驱动(异步)架构。Nginx为一些高流量的网站提供动力,比如WordPress,人人网,腾讯,网易等。这篇文章主要是介绍如何提高运行在Linux或UNIX系统的Nginx Web服务器的安全性。

[[220833]]

默认配置文件和Nginx端口

/usr/local/nginx/conf/ – Nginx配置文件目录,/usr/local/nginx/conf/nginx.conf是主配置文件

/usr/local/nginx/html/ – 默认网站文件位置

/usr/local/nginx/logs/ – 默认日志文件位置

Nginx HTTP默认端口 : TCP 80

Nginx HTTPS默认端口: TCP 443

你可以使用以下命令来测试Nginx配置文件准确性。

  1. /usr/local/nginx/sbin/nginx -t 

将会输出。

the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok

configuration file /usr/local/nginx/conf/nginx.conf test is successful

执行以下命令来重新加载配置文件。

  1. /usr/local/nginx/sbin/nginx -s reload 

执行以下命令来停止服务器。

  1. /usr/local/nginx/sbin/nginx -s stop 

一、配置SELinux

安全增强型Linux(SELinux)的是一个Linux内核的功能,它提供支持访问控制的安全政策保护机制。它可以大部分的攻击。下面我们来看如何启动基于CentOS/RHEL系统的SELinux。

安装SELinux

  1. rpm -qa | grep selinux 

libselinux-1.23.10-2

selinux-policy-targeted-1.23.16-6

如果没有返回任何结果,代表没有安装 SELinux,如果返回了类似上面的结果,则说明系统安装了 SELinux。

布什值锁定

运行命令getsebool -a来锁定系统。

  1. getsebool -a | less 
  2. getsebool -a | grep off 
  3. getsebool -a | grep o 

二、通过分区挂载允许最少特权

服务器上的网页/html/php文件单独分区。例如,新建一个分区/dev/sda5(第一逻辑分区),并且挂载在/nginx。确保/nginx是以noexec, nodev and nosetuid的权限挂载。以下是我的/etc/fstab的挂载/nginx的信息:

LABEL=/nginx /nginx ext3 defaults,nosuid,noexec,nodev 1 2

注意:你需要使用fdisk和mkfs.ext3命令创建一个新分区。

三、配置/etc/sysctl.conf强化Linux安全

你可以通过编辑/etc/sysctl.conf来控制和配置Linux内核、网络设置。

  1. # Avoid a smurf attack 
  2. net.ipv4.icmp_echo_ignore_broadcasts = 1 
  3.   
  4. # Turn on protection for bad icmp error messages 
  5. net.ipv4.icmp_ignore_bogus_error_responses = 1 
  6.   
  7. # Turn on syncookies for SYN flood attack protection 
  8. net.ipv4.tcp_syncookies = 1 
  9.   
  10. # Turn on and log spoofed, source routed, and redirect packets 
  11. net.ipv4.conf.all.log_martians = 1 
  12. net.ipv4.conf.default.log_martians = 1 
  13.   
  14. No source routed packets here 
  15. net.ipv4.conf.all.accept_source_route = 0 
  16. net.ipv4.conf.default.accept_source_route = 0 
  17.   
  18. # Turn on reverse path filtering 
  19. net.ipv4.conf.all.rp_filter = 1 
  20. net.ipv4.conf.default.rp_filter = 1 
  21.   
  22. # Make sure no one can alter the routing tables 
  23. net.ipv4.conf.all.accept_redirects = 0 
  24. net.ipv4.conf.default.accept_redirects = 0 
  25. net.ipv4.conf.all.secure_redirects = 0 
  26. net.ipv4.conf.default.secure_redirects = 0 
  27.   
  28. # Don't act as a router 
  29. net.ipv4.ip_forward = 0 
  30. net.ipv4.conf.all.send_redirects = 0 
  31. net.ipv4.conf.default.send_redirects = 0 
  32.   
  33. # Turn on execshild 
  34. kernel.exec-shield = 1 
  35. kernel.randomize_va_space = 1 
  36.   
  37. # Tuen IPv6 
  38. net.ipv6.conf.default.router_solicitations = 0 
  39. net.ipv6.conf.default.accept_ra_rtr_pref = 0 
  40. net.ipv6.conf.default.accept_ra_pinfo = 0 
  41. net.ipv6.conf.default.accept_ra_defrtr = 0 
  42. net.ipv6.conf.default.autoconf = 0 
  43. net.ipv6.conf.default.dad_transmits = 0 
  44. net.ipv6.conf.default.max_addresses = 1 
  45.   
  46. # Optimization for port usefor LBs 
  47. # Increase system file descriptor limit 
  48. fs.file-max = 65535 
  49.   
  50. # Allow for more PIDs (to reduce rollover problems); may break some programs 32768 
  51. kernel.pid_max = 65536 
  52.   
  53. # Increase system IP port limits 
  54. net.ipv4.ip_local_port_range = 2000 65000 
  55.   
  56. # Increase TCP max buffer size setable using setsockopt() 
  57. net.ipv4.tcp_rmem = 4096 87380 8388608 
  58. net.ipv4.tcp_wmem = 4096 87380 8388608 
  59.   
  60. # Increase Linux auto tuning TCP buffer limits 
  61. mindefaultand max number of bytes to use 
  62. set max to at least 4MB, or higher if you use very high BDP paths 
  63. # Tcp Windows etc 
  64. net.core.rmem_max = 8388608 
  65. net.core.wmem_max = 8388608 
  66. net.core.netdev_max_backlog = 5000 
  67. net.ipv4.tcp_window_scaling = 1 

四、删除所有不需要的Nginx模块

你需要直接通过编译Nginx源代码使模块数量最少化。通过限制只允许web服务器访问模块把风险降到最低。你可以只配置安装nginx你所需要的模块。例如,禁用SSL和autoindex模块你可以执行以下命令:

  1. ./configure --without-http_autoindex_module --without-http_ssi_module 
  2.  make 
  3.  make install 

通过以下命令来查看当编译nginx服务器时哪个模块能开户或关闭:

  1. ./configure --help | less 

禁用你用不到的nginx模块。

(可选项)更改nginx版本名称。

编辑文件/http/ngx_http_header_filter_module.c:

  1. vi +48 src/http/ngx_http_header_filter_module.c 

找到行:

  1. static char ngx_http_server_string[] = "Server: nginx" CRLF; 
  2. static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; 

按照以下行修改:

  1. static char ngx_http_server_string[] = "Server: Ninja Web Server" CRLF; 
  2. static char ngx_http_server_full_string[] = "Server: Ninja Web Server" CRLF; 

保存并关闭文件。现在你可以编辑服务器了。增加以下代码到nginx.conf文件来关闭nginx版本号的显示。

server_tokens off

五、使用mod_security

只适合后端Apache服务器

mod_security为Apache提供一个应用程序级的防火墙。为后端Apache Web服务器安装mod_security,这会阻止很多注入式攻击。

六、安装SELinux策略

默认的SELinux不会保护Nginx Web服务器,但是你可以安装和编译保护软件。

1、安装编译SELinux所需环境支持

  1. yum -y install selinux-policy-targeted selinux-policy-devel 

2、下载SELinux策略以强化Nginx Web服务器。

  1. cd /opt 
  2. wget 'http://downloads.sourceforge.net/project/selinuxnginx/se-ngix_1_0_10.tar.gz?use_mirror=nchc' 

3、解压文件

  1. tar -zxvf se-ngix_1_0_10.tar.gz 

4、编译文件

  1. cd se-ngix_1_0_10/nginx  
  2. make 

将会输出如下:

Compiling targeted nginx module

/usr/bin/checkmodule: loading policy configuration from tmp/nginx.tmp

/usr/bin/checkmodule: policy configuration loaded

/usr/bin/checkmodule: writing binary representation (version 6) to tmp/nginx.mod

Creating targeted nginx.pp policy package

  1. rm tmp/nginx.mod.fc tmp/nginx.mod 

5、安装生成的nginx.pp SELinux模块:

  1. /usr/sbin/semodule -i nginx.pp 

七、基于Iptables防火墙的限制

下面的防火墙脚本阻止任何除了允许:

来自HTTP(TCP端口80)的请求

来自ICMP ping的请求

ntp(端口123)的请求输出

smtp(TCP端口25)的请求输出

  1. #!/bin/bash 
  2. IPT="/sbin/iptables" 
  3.   
  4. #### IPS ###### 
  5. # Get server public ip 
  6. SERVER_IP=$(ifconfig eth0 | grep 'inet addr:' | awk -F'inet addr:' '{ print $2}' | awk '{ print $1}'
  7. LB1_IP="204.54.1.1" 
  8. LB2_IP="204.54.1.2" 
  9.   
  10. # Do some smart logic so that we can use damm script on LB2 too 
  11. OTHER_LB="" 
  12. SERVER_IP="" 
  13. [[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB="$LB2_IP" || OTHER_LB="$LB1_IP" 
  14. [[ "$OTHER_LB" == "$LB2_IP" ]] && OPP_LB="$LB1_IP" || OPP_LB="$LB2_IP" 
  15.   
  16. ### IPs ### 
  17. PUB_SSH_ONLY="122.xx.yy.zz/29" 
  18.   
  19. #### FILES ##### 
  20. BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt 
  21. 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 255.255.255.255/32 168.254.0.0/16 224.0.0.0/4 240.0.0.0/5 248.0.0.0/5 192.0.2.0/24" 
  22. BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v "^#|^$" ${BLOCKED_IP_TDB}) 
  23.   
  24. ### Interfaces ### 
  25. PUB_IF="eth0"   # public interface 
  26. LO_IF="lo"      # loopback 
  27. VPN_IF="eth1"   # vpn / private net 
  28.   
  29. ### start firewall ### 
  30. echo "Setting LB1 $(hostname) Firewall..." 
  31.   
  32. DROP and close everything 
  33. $IPT -P INPUT DROP 
  34. $IPT -P OUTPUT DROP 
  35. $IPT -P FORWARD DROP 
  36.   
  37. # Unlimited lo access 
  38. $IPT -A INPUT -i ${LO_IF} -j ACCEPT 
  39. $IPT -A OUTPUT -o ${LO_IF} -j ACCEPT 
  40.   
  41. # Unlimited vpn / pnet access 
  42. $IPT -A INPUT -i ${VPN_IF} -j ACCEPT 
  43. $IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT 
  44.   
  45. Drop sync 
  46. $IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP 
  47.   
  48. Drop Fragments 
  49. $IPT -A INPUT -i ${PUB_IF} -f -j DROP 
  50.   
  51. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP 
  52. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP 
  53.   
  54. Drop NULL packets 
  55. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " NULL Packets " 
  56. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP 
  57.   
  58. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP 
  59.   
  60. Drop XMAS 
  61. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " XMAS Packets " 
  62. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP 
  63.   
  64. Drop FIN packet scans 
  65. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " Fin Packets Scan " 
  66. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP 
  67.   
  68. $IPT  -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP 
  69.   
  70. # Log and get rid of broadcast / multicast and invalid 
  71. $IPT  -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j LOG --log-prefix " Broadcast " 
  72. $IPT  -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j DROP 
  73.   
  74. $IPT  -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j LOG --log-prefix " Multicast " 
  75. $IPT  -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j DROP 
  76.   
  77. $IPT  -A INPUT -i ${PUB_IF} -m state --state INVALID -j LOG --log-prefix " Invalid " 
  78. $IPT  -A INPUT -i ${PUB_IF} -m state --state INVALID -j DROP 
  79.   
  80. # Log and block spoofed ips 
  81. $IPT -N spooflist 
  82. for ipblock in $SPOOFIP 
  83. do 
  84.          $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG --log-prefix " SPOOF List Block " 
  85.          $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP 
  86. done 
  87. $IPT -I INPUT -j spooflist 
  88. $IPT -I OUTPUT -j spooflist 
  89. $IPT -I FORWARD -j spooflist 
  90.   
  91. # Allow ssh only from selected public ips 
  92. for ip in ${PUB_SSH_ONLY} 
  93. do 
  94.         $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} --destination-port 22 -j ACCEPT 
  95.         $IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} --sport 22 -j ACCEPT 
  96. done 
  97.   
  98. # allow incoming ICMP ping pong stuff 
  99. $IPT -A INPUT -i ${PUB_IF} -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -m limit --limit 30/sec  -j ACCEPT 
  100. $IPT -A OUTPUT -o ${PUB_IF} -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT 
  101.   
  102. # allow incoming HTTP port 80 
  103. $IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT 
  104. $IPT -A OUTPUT -o ${PUB_IF} -p tcp --sport 80 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT 
  105.   
  106. # allow outgoing ntp 
  107. $IPT -A OUTPUT -o ${PUB_IF} -p udp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT 
  108. $IPT -A INPUT -i ${PUB_IF} -p udp --sport 123 -m state --state ESTABLISHED -j ACCEPT 
  109.   
  110. # allow outgoing smtp 
  111. $IPT -A OUTPUT -o ${PUB_IF} -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT 
  112. $IPT -A INPUT -i ${PUB_IF} -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT 
  113.   
  114. ### add your other rules here #### 
  115.   
  116. ####################### 
  117. drop and log everything else 
  118. $IPT -A INPUT -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " DEFAULT DROP " 
  119. $IPT -A INPUT -j DROP 
  120.   
  121. exit 0 
责任编辑:武晓燕 来源: 马哥Linux运维
相关推荐

2010-03-12 10:48:03

2017-05-24 12:30:34

2009-02-27 11:32:00

2010-03-24 10:32:09

CentOS服务器

2010-01-12 12:07:28

2009-12-10 10:11:08

2023-03-30 13:22:45

nginxweb服务器

2010-03-30 18:26:07

Nginx Web服务

2011-03-23 13:59:43

2011-03-22 14:08:53

2020-04-15 20:57:57

NginxWeb服务器

2017-12-27 10:18:09

ApacheNginx服务器

2019-12-30 16:03:54

Web服务器Nginx

2009-09-18 13:00:20

2010-11-22 16:15:15

2009-07-28 08:07:43

2010-05-21 13:27:02

2010-07-28 10:01:18

Web服务器LinuxCentOS

2018-08-09 09:22:55

开源web服务器

2018-08-07 08:54:18

点赞
收藏

51CTO技术栈公众号