1、一些常識
- linux下,要讀取一個檔案,首先需要具有對檔案所在檔案夾的執行權限,然後需要對檔案的讀取權限。
- php檔案的執行不需要檔案的執行權限,隻需要nginx和php-fpm運作賬戶的讀取權限。
- 上傳木馬後,能不能列出一個檔案夾的内容,跟php-fpm的運作賬戶對檔案夾的讀取權限有關,木馬執行指令的權限跟php-fpm的賬戶權限有關。
- 如果木馬要執行指令,需要php-fpm的賬戶對相應的sh有執行權限。
- 讀取一個檔案夾内的檔案,是不需要對檔案夾有讀取權限的,隻需要對檔案夾有執行權限。
1、頂部配置
#定義 Nginx 運作的使用者和使用者組
user nginx;
#程序檔案
pid /var/run/nginx.pid;
#錯誤日志位置和級别,debug、info、notice、warn、error、crit
error_log /var/log/nginx/error.log warn;
#Nginx worker 的程序數,一般可設定為可用的CPU核心數。
worker_processes 8;
#每個 worker 打開檔案描述符的最大數量限制。理論值應該是最多打開檔案數(系統的值ulimit -n)與 nginx 程序數相除,但是 nginx 配置設定請求并不均勻,是以建議與ulimit -n的值保持一緻。
worker_rlimit_nofile 65535;
2、Events 子產品
events {
#設定一個worker程序同時打開的最大連接配接數
worker_connections 2048;
#告訴nginx收到一個新連接配接通知後接受盡可能多的連接配接
multi_accept on;
#設定用于複用用戶端線程的輪詢方法。如果你使用Linux 2.6+,你應該使用epoll。如果你使用*BSD,你應該使用kqueue。
use epoll;
}
3、HTTP 子產品
http {
#隐藏 Nginx 的版本号,提高安全性。
server_tokens off;
#開啟高效檔案傳輸模式,sendfile 指令指定 Nginx 是否調用sendfile 函數來輸出檔案,對于普通應用設為 on,如果用來進行下載下傳等應用磁盤 IO 重負載應用,可設定為 off,以平衡磁盤與網絡 I/O 處理速度,降低系統的負載。
sendfile on;
#是否開啟目錄清單通路,預設關閉。
autoindex off;
#告訴 Nginx 在一個資料包裡發送所有頭檔案,而不一個接一個的發送
tcp_nopush on;
#告訴 Nginx 不要緩存資料,而是一段一段的發送--當需要及時發送資料時,就應該給應用設定這個屬性,這樣發送一小塊資料資訊時就不能立即得到傳回值。Nginx 預設會始終工作在 tcp nopush 狀态下。但是當開啟前面的 sendfile on; 時,它的工作特點是 nopush 的最後一個包會自動轉轉換到 nopush off。為了減小那200ms的延遲,開啟 nodelay on; 将其很快傳送出去。結論就是 sendfile on; 開啟時,tcp_nopush 和 tcp_nodelay 都是on 是可以的。
tcp_nodelay on;
#日志格式設定
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#定義通路日志,設定為 off 可以關閉日志,提高性能
access_log /var/log/nginx/access.log main;
#連接配接逾時時間,機關是秒
keepalive_timeout 120;
#讀取HTTP頭部的逾時時間,預設值 60。用戶端與伺服器建立連接配接後将開始接收HTTP頭部,在這個過程中,如果在一個時間間隔(逾時時間)内沒有讀取到用戶端發來的位元組,則認為逾時,并向用戶端傳回408 ("Request timed out")響應。
client_header_timeout 60;
#預設值 60。與client_header_timeout相似,隻是這個逾時時間隻在讀取HTTP包體時才有效。
client_body_timeout 10;
#發送響應的逾時時間,預設值 60。即Nginx伺服器向用戶端發送了資料包,但用戶端一直沒有去接收這個資料包。如果某個連接配接超過send_timeout定義的逾時時間,那麼Nginx将會關閉這個連接配接。
send_timeout 60;
#連接配接逾時後将通過向用戶端發送RST包來直接重置連接配接。這個選項打開後,Nginx會在某個連接配接逾時後,不是使用正常情形下的四次握手關閉TCP連接配接,而是直接向使用者發送RST重置包,不再等待使用者的應答,直接釋放Nginx伺服器上關于這個套接字使用的所有緩存(如TCP滑動視窗)。相比正常的關閉方式,它使得伺服器避免産生許多處于FIN_WAIT_1、FIN_WAIT_2、TIME_WAIT狀态的TCP連接配接。注意,使用RST重置包關閉連接配接會帶來一些問題,預設情況下不會開啟。
reset_timedout_connection off;
#要限制連接配接,必須先有一個容器對連接配接進行計數,"zone=" 是給它一個名字,可以随便叫,這個名字要跟下面的 limit_conn 一緻。$binary_remote_addr 用二進制來儲存用戶端的位址,1m 可以儲存 32000 個并發會話。
limit_conn_zone $binary_remote_addr zone=addr:5m;
#給定的key設定最大連接配接數。這裡key是addr,我們設定的值是100,也就是說我們允許每一個IP位址最多同時打開有100個連接配接。
limit_conn addr 100;
#對每個連接配接限速100k。這如果一個IP允許兩個并發連接配接,那麼這個IP就是限速200K。
limit_rate 100k;
#include 是一個在目前檔案中包含另一個檔案内容的指令。這裡我們使用它來加載檔案擴充名與檔案類型映射表。nginx根據映射關系,設定http請求響應頭的Content-Type值。當在映射表找不到時,使用nginx.conf中default-type指定的預設值。
include /etc/nginx/mime.types;
#設定檔案使用的預設的MIME-type
default_type text/html;
#預設編碼
charset UTF-8;
#該子產品可以讀取預先壓縮的gz檔案,這樣可以減少每次請求進行gzip壓縮的CPU資源消耗。該子產品啟用後,nginx首先檢查是否存在請求靜态檔案的gz結尾的檔案,如果有則直接傳回該gz檔案内容。
gzip_static off;
#開啟 gzip 壓縮。
gzip on;
# 禁用用戶端為 IE6 時的 gzip功能。
gzip_disable "msie6";
#Nginx做為反向代理的時候啟用。可選值:off|expired|no-cache|no-sotre|private|no_last_modified|no_etag|auth|any
gzip_proxied any;
#設定允許壓縮的頁面最小位元組數,頁面位元組數從header頭中的Content-Length中進行擷取。建議設定成大于1k的位元組數,小于1k可能會越壓越大。
gzip_min_length 1024;
#設定資料的壓縮等級。這個等級可以是1-9之間的任意數值,9是最慢但是壓縮比最大的。
gzip_comp_level 5;
#設定系統擷取幾個機關的緩存用于存儲gzip的壓縮結果資料流。 例如 4 4k 代表以4k為機關,按照原始資料大小以4k為機關的4倍申請記憶體。如果沒有設定,預設值是申請跟原始資料相同大小的記憶體空間去存儲gzip壓縮結果。
gzip_buffers 4 16k;
#設定需要壓縮的資料格式。Nginx預設隻對text/html進行壓縮。
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
#為打開檔案指定緩存,預設是沒有啟用的,max 指定緩存數量,建議和打開檔案數一緻,inactive 是指經過多長時間檔案沒被請求後删除緩存。
open_file_cache max=65535 inactive=30s;
#多長時間檢查一次緩存的有效資訊
open_file_cache_valid 30s;
#open_file_cache指令中的inactive參數時間内檔案的最少使用次數,如果超過這個數字,檔案描述符一直是在緩存中打開的。出現 Last-Modified 不變的情況,就是因為當nginx對一個靜态檔案緩存後,如果30s内還在通路它,那麼它的緩存就一直存在,直到30s内你不通路了為止。
open_file_cache_min_uses 2;
#是否記錄cache錯誤
open_file_cache_errors on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
4、SERVER 子產品
server {
#監聽端口,nginx 會根據請求的 HOST 來決定使用哪個 SERVER 段的配置。如果沒有比對的 server_name,則預設使用配置檔案中第一個。加上 default_server 則可以以指定沒有比對時的預設規則。
#listen 80;
listen 80 default_server;
#域名可以有多個,用空格隔開
server_name www.test.com test.com;
root /user/share/nginx/html/test;
#404頁面配置
error_page 404 /404.html;
#配置 ssl,有需要時開啟。
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
location / {
index index.html index.php;
}
#圖檔緩存時間設定
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 10d;
}
#JS和CSS緩存時間設定
location ~ .*.(js|css)?$ {
expires 1h;
}
location ~ [^/]\.php(/|$) {
fastcgi_index index.php;
#開啟 PATH_INFO 支援,作用就是把參數按照給定的正規表達式分割成 $fastcgi_script_name 和 $fastcgi_path_info。
#例如:請求 index.php/id/1 不加此行配置時,fastcgi_script_name 是 /index.php/id/1,fastcgi_path_info 是空。
#加上之後,fastcgi_script_name 是 index.php,fastcgi_path_info 是 /id/1
fastcgi_split_path_info ^(.+\.php)(.*)$;
#此值即是 PHP 中 $_SERVER['SCRIPT_FILENAME'] 的值
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伺服器監聽端口與位址。須和 PHP-FPM 的設定相同。
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/php5-fpm.sock;
include fastcgi_params;
}
}
2、常見的方式
1. 讓木馬上傳後不能執行:針對上傳目錄,在nginx配置檔案中加入配置,使此目錄無法解析php
2. 讓木馬執行後看不到非網站目錄檔案:取消php-fpm運作賬戶對于其他目錄的讀取權限
3. 木馬執行後指令不能執行:取消php-fpm賬戶對于sh的執行權限
4. 指令執行後權限不能過高:php-fpm賬戶不要用root或者加入root組
3、具體的配置
1、禁止php檔案的通路及執行
location ~ /(attachments|upload)/.*\.(php|php5)?$ {
deny all;
}
2、禁止IP的通路
//禁止的寫法
deny 10.0.0.0/24;
//允許的寫法
allow 10.0.0.0/24;
deny all;
3、根據使用者的真實 IP 做連接配接限制
## 這裡取得原始使用者的IP位址
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
## 針對原始使用者 IP 位址做限制
limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ;
limit_conn TotalConnLimitZone 50;
limit_conn_log_level notice;
## 針對原始使用者 IP 位址做限制
limit_req_zone $clientRealIp zone=ConnLimitZone:20m rate=10r/s;
#limit_req zone=ConnLimitZone burst=10 nodelay;
limit_req_log_level notice;
## 具體伺服器配置
server {
listen 80;
location ~ \.php$ {
## 最多 5 個排隊, 由于每秒處理 10 個請求 + 5個排隊,你一秒最多發送 15 個請求過來,再多就直接傳回 503 錯誤給你了
limit_req zone=ConnLimitZone burst=5 nodelay;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
4、 經過多層CDN之後取得原始使用者的IP位址,nginx 配置
map $http_x_forwarded_for $clientRealIp {
## 沒有通過代理,直接用 remote_addr
"" $remote_addr;
## 用正則比對,從 x_forwarded_for 中取得使用者的原始IP
## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...
## 這裡第一個 202.123.123.11 是使用者的真實 IP,後面其它都是經過的 CDN 伺服器
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
## 通過 map 指令,我們為 nginx 建立了一個變量 $clientRealIp ,這個就是 原始使用者的真實 IP 位址,
## 不論使用者是直接通路,還是通過一串 CDN 之後的通路,我們都能取得正确的原始IP位址
5、隐藏版本資訊
server_tokens off;
proxy_hide_header X-Powered-By;
//或者編譯的時候修改源代碼
6、禁用非必要的方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 444;
}
7、禁用擴充名
location ~* .(txt|doc|sql|gz|svn|git)$ {
deny all;
}
8、合理配置響應頭
add_header Strict-Transport-Security "max-age=31536000";
add_header X-Frame-Options deny;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://a.disquscdn.com; img-src 'self' data: https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; frame-src https://disqus.com";
Strict-Transport-Security
(簡稱為 HSTS)可以告訴浏覽器,在指定的 max-age 内,始終通過 HTTPS 通路
X-Frame-Options
用來指定此網頁是否允許被 iframe 嵌套,deny 就是不允許任何嵌套發生
9、拒絕一些User-Agents
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
10、防止圖檔盜鍊
valid_referers blocked www.example.com example.com;
if ($invalid_referer) {
rewrite ^/images/uploads.*\.(gif|jpg|jpeg|png)$ http://www.examples.com/banned.jpg last
}
11、控制緩沖區溢出攻擊
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
解釋說明
1、client_body_buffer_size 1k-(預設8k或16k)這個指令可以指定連接配接請求實體的緩沖區大小。如果連接配接請求超過緩存區指定的值,那麼這些請求實體的整體或部分将嘗試寫入一個臨時檔案。
2、client_header_buffer_size 1k-指令指定用戶端請求頭部的緩沖區大小。絕大多數情況下一個請求頭不會大于1k,不過如果有來自于wap用戶端的較大的cookie它可能會大于1k,Nginx将配置設定給它一個更大的緩沖區,這個值可以在large_client_header_buffers裡面設定。
3、client_max_body_size 1k-指令指定允許用戶端連接配接的最大請求實體大小,它出現在請求頭部的Content-Length字段。如果請求大于指定的值,用戶端将收到一個”Request Entity Too Large” (413)錯誤。記住,浏覽器并不知道怎樣顯示這個錯誤。
4、large_client_header_buffers-指定用戶端一些比較大的請求頭使用的緩沖區數量和大小。請求字段不能大于一個緩沖區大小,如果用戶端發送一個比較大的頭,nginx将傳回”Request URI too large” (414)
1、client_body_timeout 10;-指令指定讀取請求實體的逾時時間。這裡的逾時是指一個請求實體沒有進入讀取步驟,如果連接配接超過這個時間而用戶端沒有任何響應,Nginx将傳回一個”Request time out” (408)錯誤。
2、client_header_timeout 10;-指令指定讀取用戶端請求頭标題的逾時時間。這裡的逾時是指一個請求頭沒有進入讀取步驟,如果連接配接超過這個時間而用戶端沒有任何響應,Nginx将傳回一個”Request time out” (408)錯誤。
3、keepalive_timeout 5 5; – 參數的第一個值指定了用戶端與伺服器長連接配接的逾時時間,超過這個時間,伺服器将關閉連接配接。參數的第二個值(可選)指定了應答頭中Keep-Alive: timeout=time的time值,這個值可以使一些浏覽器知道什麼時候關閉連接配接,以便伺服器不用重複關閉,如果不指定這個參數,nginx不會在應答頭中發送Keep-Alive資訊。(但這并不是指怎樣将一個連接配接“Keep-Alive”)參數的這兩個值可以不相同。
4、send_timeout 10; 指令指定了發送給用戶端應答後的逾時時間,Timeout是指沒有進入完整established狀态,隻完成了兩次握手,如果超過這個時間用戶端沒有任何響應,nginx将關閉連接配接。
12、控制并發連接配接
limit_zone slimits $binary_remote_addr 5m;
limit_conn slimits 5;
13、sysctl.conf配置
# 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
# 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
14、在防火牆級限制每個IP的連接配接數
/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
15、限制Nginx連接配接傳出
/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner vivek -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
。。。
參考連結
http://www.bzfshop.net/article/176.html
http://nginx.org/en/docs/
http://www.oschina.net/translate/nginx-setup
http://www.ha97.com/5194.html
- 作者:踏雪無痕
- 出處:http://www.cnblogs.com/chenpingzhao/
- 本文版權歸作者和部落格園共有,如需轉載,請聯系 pingzhao1990#163.com