1.配置文檔中有多處明確寫出了nginx的配置文件路徑,該路徑是測試環境中的路徑,線上系統的nginx配置文件與文檔中所寫的路徑可能不同,在進行相關配置時,應以線上配置文件的實際路徑爲準。html
線上系統nginx的安裝目錄在:/usr/local/nginx,默認配置文件在/usr/local/nginx/conf/nginx.conf,此外也引用了/usr/local/nginx/conf/conf.d目錄下的配置文件。nginx
2.本文檔僅包括了用於提高安全的配置方法。web
3.在聽從本文檔的方法進行配置前,請作好相關配置文件的備份,以便在配置失敗時能夠回退到變動前狀態。算法
1.新安裝,選用安全穩定版本
編號:shell |
Nginx_Sec_001vim |
適用:瀏覽器 |
LINUX下新安裝或者升級nginx服務器緩存 |
配置要求:安全 |
1.安裝包要求從nginx官方網站獲取,官方網站地址:http://nginx.org/。ruby 2.安裝包優先選用穩定版(stable)最新版,若是要跨大版本升級nginx,則要求在測試環境測試不存在兼容性問題後纔在生產環境進行部署。 3.要求對下載的源碼安裝包文件進行完整性驗證。
具體方法參考「備註」處的方法。 |
安全加強說明: |
1.從官方網站下載安裝包及對安裝包進行指紋驗證能夠最大程度確保安裝文件未被篡改; 2.使用最新版本,最大避免舊版版中已發現安全漏洞的威脅,使用穩定版能夠確保功能穩定。 |
備註: |
完整性驗證方法: (1)每一個nginx源碼包都有一個簽名文件,從官網訪問下載nginx源碼包的同時也下載該源碼包的簽名文件到同一目錄,該簽名文件是nginx官方使用pgp私鑰對源碼包進行簽名獲得,該文件後綴.爲.asc,獲取pgp簽名文件方法:
(2)nginx源碼包使用的是pgp簽名,進行簽名驗證時須要到GnuPG程序,若是沒有安裝該工具,可使用yum install gnupg進行安裝。 (3)獲取pgp簽名文件的公鑰ID,執行:# sudo gpg --verify nginx-1.11.3.tar.gz.asc gpg: Signature made Tue 26 Jul 2016 09:59:49 PM CST using RSA key ID A1C052F8 gpg: Can't check signature: No public key (4)根據ID號從公鑰服務器中下載公鑰,以下: #sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys A1C052F8 gpg: requesting key A1C052F8 from hkp server keys.gnupg.net gpg: /root/.gnupg/trustdb.gpg: trustdb created gpg: key A1C052F8: public key "Maxim Dounin <mdounin@mdounin.ru>" imported gpg: key A1C052F8: public key "Maxim Dounin <mdounin@mdounin.ru>" imported gpg: no ultimately trusted keys found gpg: Total number processed: 2 gpg: imported: 2 (RSA: 2) (5)利用公鑰驗證nginx源碼包和簽名文件,以下,說明文件沒有被篡改: # sudo gpg --verify nginx-1.11.3.tar.gz.asc gpg: Signature made Tue 26 Jul 2016 09:59:49 PM CST using RSA key ID A1C052F8 gpg: Good signature from "Maxim Dounin <mdounin@mdounin.ru>" gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: B0F4 2533 73F8 F6F5 10D4 2178 520A 9993 A1C0 52F8 |
2.使用普通帳號運行nginx服務
編號: |
Nginx_Sec_002 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置要求: |
nginx服務器的work進程不能使用root帳號運行,要求以普通帳號運行,具體方法參考「備註」處的方法。 |
安全加強說明: |
防範或下降攻擊者經過上傳webshell來獲取到的執行權限 |
備註: |
配置普通帳號運行nginx服務方法: 1.nginx(worker進程)默認以nobody運行,建立普通帳號nginx,使用nginx帳號來運行 # sudo groupadd -g 1001 nginx #建立nginx組 # sudo useradd -s /sbin/nologin -M -g nginx -u 1001 nginx #建立nginx用戶並加入到nginx組,不建立家目錄,不容許nginx帳號登陸。 說明:GID和UID定義爲1000,避免與nis系統上的帳號的ID衝突。 2.以普通帳號nginx來運行Nginx,兩個方法: 方法1:若是是新安裝nginx,編譯時添加--user=nginx --group=nginx參數; 方法2:已完成nginx的安裝,經過修該配置文件來指定,以下: 1)# sudo vim /usr/local/nginx/conf/nginx.conf 2)將#user nobody;改爲user nginx nginx; 3)測試配置文件是否正確,執行命令# sudo /usr/local/nginx/sbin/nginx –t 4)在3)步驟測試配置無錯誤後重啓Nginx服務器,執行命令# sudo /usr/local/nginx/sbin/nginx -s reload 5)查看work進程帳號,確認該進程帳號爲nginx,執行命令# sudo ps -aux |grep nginx Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ root 30153 0.0 0.1 17976 1604 ? Ss 22:53 0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 30245 0.0 0.1 18404 1528 ? S 23:05 0:00 nginx: worker process 3.修改nginx根目錄的用戶與用戶組: 1)chown –R ngin.nginx nginx根目錄
注意:設置nginx根目錄的用戶和用戶組爲nginx後,且安全加固中將umask設置成027後,nginx安裝目錄的權限爲750,普通用戶沒法訪問該目錄,此時須要nginx的安裝目錄的權限應該是755。 |
3.隱藏nginx的版本信息
編號: |
Nginx_Sec_003 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置要求: |
要求隱藏nginx的版本信息, 具體方法參考「備註」處的方法。 |
安全加強說明: |
絕大多數漏洞掃描工具經過獲取目標web服務器的版本號來判斷該web服務器是否存在安全漏洞,隱藏版本號後能夠最大減小惡意攻擊者經過漏掃工具來收集漏洞信息。 |
備註: |
隱藏nginx版本信息方法: 1.編輯nginx配置文件,在http塊中添加 server_tokens off; 2.重啓nginx服務便可。 |
4.禁止目錄列表
編號: |
Nginx_Sec_004 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置要求: |
要求禁止nginx服務器目錄列表功能,默認已禁止目錄列表功能。具體方法參考「備註」處的方法。 |
安全加強說明: |
1.當目標web服務器容許目錄時,只要訪問目標web服務器的目錄,若是該目錄下沒有設置默認訪問的文件,則會同時將該目錄的全部文件列出來,以下:
2.禁止目錄列表功能能夠避免因暴露目標網站的目錄結構和敏感文件,最終形成敏感信息丟失。 |
備註: |
在nginx配置文件的location,server 或 http塊中都容許設置autoindex on;確認nginx沒有啓用目錄列表功能,即同時檢查這幾個地方沒有配置參數autoindex on; 說明: 禁止目錄列表後,url訪問目錄應該是403錯誤,以下:
|
5.日誌規範
編號: |
Nginx_Sec_005 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置要求: |
要求nginx服務器同時啓用訪問日誌和錯誤日誌的記錄,具體方法參考「備註」處的方法。 |
安全加強說明: |
nginx訪問日誌記錄了客戶端的請求行爲,經過對訪問日誌的分析可以發現潛在的攻擊行爲;nginx的錯誤日誌反映了nginx 服務器的健康情況,經過分析或者監控nginx的報錯信息可以及時發現nginx存在故障問題。 |
備註: |
1.設置訪問日誌(access_log),日誌的格式定義以下: log_format access '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; 各個變量的說明: $remote_user :用來記錄客戶端用戶名稱; $time_local :用來記錄訪問時間與時區; $request :用來記錄請求的url與http協議; $status :用來記錄請求狀態;成功是200, $body_bytes_sent:記錄發送給客戶端文件主體內容大小; $http_referer :用來記錄從那個頁面連接訪問過來的; $http_user_agent:記錄客戶端瀏覽器的相關信息; $http_x_forwarded_for:用以記錄原始客戶端IP地址,若是原始客戶端原始請求發送到nginx前沒有通過任何代理,則該變量的值爲-。 2.生成的訪問日誌格式以下: 效果: 192.168.12.92 - - [12/Aug/2016:20:14:41 +0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0" – 3.錯誤日誌的級別要求定義爲warn,以下 error_log logs/error.log warn; 注意:若是更改日誌文件的默認路徑,則nginx運行帳號須要具備新路勁下日誌文件的讀寫權限。
說明:錯誤日誌級別包括: debug, info, notice, warn, error, crit, alert, or emerg.默認是error級別. 當前3.0系統線上環境nginx編譯時將access日誌和error日誌存在/var/log/nginx目錄下。 |
6.限制不安全請求方法
編號: |
Nginx_Sec_006 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置建議: |
建議拒絕接受除POST和GET,HEAD之外的請求方法,具體方法參考「備註」處的方法。 |
安全加強說明: |
http定義了8種請求方法,其中PUT、DELETE等請求方法是不安全的,限制不安全的請求方法下降目標網站文件被惡意篡改的風險。 |
備註: |
配置拒絕除get,head和post方法之外的請求方法: 編輯Nginx配置文件以下: server{ ... ... if ($request_method !~ ^(GET|HEAD|POST)$) { return 444; } ... ... 注:非標準的444錯誤代碼能夠強制關閉服務器與客戶端的鏈接而不返回任何響應信息給客戶端。
http的8種請求方式: GET:當瀏覽器要從服務器讀取指定文檔。Get方法要求服務器將URL定位的資源放在響應報文的正文中,回傳給瀏覽器。 HEAD:使用post方法,瀏覽器只讀取請求文件的頭部信息,而不是文件的正文; POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。 PUT:從客戶端傳送的數據取代(替換)指定文件的內容; DELETE:請求服務器刪除指定文件; TRACE:回顯服務器收到的請求,主要用於測試或診斷; OPTIONS:1)獲取服務器支持的HTTP請求方法;2)用來檢查服務器的性能; CONNECT: HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。 |
7.禁用SSL/TSL不安全協議和弱加密算法
編號: |
Tomcat_Sec_007 |
適用: |
使用提供HTTPS方式訪問的Tomcat服務器 |
配置要求: |
當nginx使用到https訪問時,要求禁止使用SSLV1.0、SSLV2.0,SSLV3.0不安全協議,建議也不要使用TLSv1.0協議,要求禁止使用如下不安全加密算法:
具體配置方法參考「備註」處的方法。 |
安全加強說明: |
下降因爲使用不安全協議和弱加密緻使被中間人攻擊,最終形成敏感信息泄露的風險。 |
備註: |
在nginx配置文件中的ssl_protocols和ssl_ciphers作以下配置: ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH:!kEDH:!kECDH; ssl_prefer_server_ciphers on; 保存配置文件並重啓nginx服務便可。
最終支持的加密協議和加密套件以下:
優先使用說明: 加密協議 優先使用順序TLSv1.2,TLSv1.1,TLS1.0。其中TLS1.0也被認爲是不安全協議,建議不使用。 加密套件: 密鑰交換算法,優先使用順序:ECDHE(支持正向安全,2048位,防止中間人攻擊),DHE,RSA(沒法防止中間人攻擊),不要使用1024位的DH。 認證算法,優先使用RSA, ECDSA 對稱加密算法,優先使用AES_256_GCM,AES_128_GCM,AES_256_CBC,AES_128_CBC,3DES_EDE_CBC 散列算法,優先使用順序SHA_256,SHA1 |
8.自定義緩衝區
編號: |
Nginx_Sec_008 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置建議: |
此方法可用於在遭受攻擊時用於減輕攻擊的防範手段,平時不強制要求配置,如要配置,相關參數則須要根據實際狀況來定,具體配置方法以下: http{ ... ... server{ ... ... client_body_buffer_size 16K; client_header_buffer_size 1k; large_client_header_buffers 4 8k; client_max_body_size 1m; |
安全加強說明: |
主要用於防範或者減輕緩衝區溢出攻擊。 |
備註: |
語法: client_body_buffer_size size; 默認: client_body_buffer_size 8k|16k; 上下文: http, server, location 參數使用說明: 設置緩衝區(buffer)大小,用於存放所讀取客戶端的請求體,在請求體(request body)大於buffer,那麼整個請求體或者請求體的一部分會寫到臨時文件(a temporary file)。默認狀況下:buffer大小等於兩個內存頁,在 x86, other 32-bit platforms, and x86-64這些平臺它的大小是8K,64-bit平臺一般是16k. -------------------------------------------------------------------------------------------------- 語法: client_header_buffer_size size; 默認: client_header_buffer_size 1k; 上下文: http, server 參數使用說明: 設置緩衝區(buffer)大小,用於存放所讀取客戶端的請求頭,在大多數的請求中1k大小的buffer已經足夠。可是,若是一個請求頭包括很長的cookies或者來自WAP客戶端,配置1k多是不適合的,若是分配的buffer沒法容納 request_line/request_header ,那麼則根據large_client_header_buffers配置的參數來分配large_buffer。 ------------------------------------------------------------------------------------------------------------------ 語法: large_client_header_buffers number size; 默認: large_client_header_buffers 4 8k; 上下文: http, server 參數使用說明: 設置單個buffers的大小以及buffers最大個數用於存放所讀取客戶端的大請求頭(reading large client request header),先根據client_header_buffer_size配置的值分配一個buffer,若是分配的buffer沒法容納 request_line/request_header,那麼就會再次根據large_client_header_buffers配置的參數分配large_buffer,若是large_buffer仍是沒法容納,那麼就會返回414(處理request_line)/400(處理request_header)錯誤。 ------------------------------------------------------------------------------------------------------------------ 語法: client_max_body_size size; 默認: client_max_body_size 1m; 上下文: http, server, location 參數使用說明: Sets the maximum allowed size of the client request body(請求體), specified in the 「Content-Length」 request header field(請求體的大小在請求頭Content-Length字體寫明,單位字節). If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client(若是請求體大小大於該設定值,則給客戶端返回413錯誤). Please be aware that browsers cannot correctly display this error(但瀏覽器不能正確顯示該錯誤). Setting size to 0 disables checking of client request body size.(設置值爲0時,不限制請求體大小) 該參數用於設置nginx容許客戶端請求體的最大值,請求體的大小在請求頭Content-Length字體寫明,單位字節。若是親請求體的大小超過了配置的值,則向客戶端返回413錯誤,但須要注意的是瀏覽器不能正確顯示該錯誤,若是該參數值設置0,則不限制請求體大小。 |
9.設置鏈接超時時間
編號: |
Nginx_Sec_009 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置建議: |
此方法可用於在遭受攻擊時用於減輕攻擊的防範手段,平時不強制要求配置,如要配置,相關參數則須要根據實際狀況來定,具體配置方法以下:
http { ... ... client_body_timeout 10; client_header_timeout 30; keepalive_timeout 30 30; send_timeout 10; |
安全加強說明: |
主要用於防範或者減輕慢鏈接攻擊。 |
備註: |
語法: client_body_timeout time; 默認: client_body_timeout 60s; 上下文: http, server, location 參數使用說明: 設置讀取客戶端的請求體(request body.)超時時間,該超時時間爲在兩個連續的讀取操做間的超時時間,而不是整個請求體的傳輸超時時間。若是在這個時間內客戶端沒有響應(transmit anything),nginx將向客戶端返回408請求超時錯誤。
注意:只有請求體須要被1次以上讀取時,該超時時間纔會被設置。 --------------------------------------------------------------------------------------------------- 語法: client_header_timeout time; 默認: client_header_timeout 60s; 上下文: http, server 參數使用說明: 設置讀取客戶端請求頭的超時時間,若是在該時間內客戶端沒有傳輸完整個請求頭(the entire header),nginx將返回408(請求超時)錯誤。 ------------------------------------------------------------------------------------------------------------------- 語法: keepalive_timeout timeout [header_timeout]; 上下文:http, server, location 參數使用說明: 第一個參數的值指定了客戶端與服務器長鏈接的超時時間,超過這個時間,服務器將關閉鏈接。值爲0時,關閉客戶端的會話保持鏈接,(即關閉長鏈接). 第二個參數的值(可選)指定了應答頭中Keep-Alive: timeout=time的time值,這個值可使一些瀏覽器知道何時關閉鏈接,以便服務器不用重複關閉,若是不指定這個參數,nginx不會在應答頭中發送Keep-Alive信息。 ---------------------------------------------------------------------------------------------------------------- 語法: send_timeout time; 默認: send_timeout 60s; 上下文: http, server, location 參數使用說明: 該指令指定了發送給客戶端應答後的超時時間,Timeout是指沒有進入完整established狀態,只完成了兩次握手,若是超過這個時間客戶端沒有任何響應,nginx將關閉鏈接。 |
10.限制併發鏈接
編號: |
Nginx_Sec_010 |
適用: |
LINUX下新安裝部署或已上線nginx服務器 |
配置建議: |
此方法可用於在遭受攻擊時用於減輕攻擊的防範手段,平時不強制要求配置,如要配置,相關參數則須要根據實際狀況來定,具體配置方法以下: 1.在nginx.conf裏的http{}里加上以下代碼: limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; 2.在須要限制併發數和下載帶寬的網站配置server{}里加上以下代碼: #每IP最大併發爲2。 limit_conn perip 2; 限制單一虛擬服務器,最大隻接受20個併發 limit_conn perserver 20; limit_rate 100k; |
安全加強說明: |
主要用以防範或者減輕DDOS攻擊。 |
備註: |
語法: limit_conn_zone key zone=name:size; 默認: — 上下文: http 參數使用說明: 定義一個用於存放key變量,大小爲szie名稱爲name的zone,key的值能夠是特定變量的任何非空值(空值將不會被考慮)。 例如: limit_conn_zone $binary_remote_addr zone=perip:10m; 定義一個大小爲10m字節,名稱爲perip的zone,該zone用於二進制來儲存客戶端的IP地址; Ipv4地址對應的 $binary_remote_addr 變量的大小爲 4 bytes ,IPv6 地址對應的是16字節。. -------------------------------------------------------------------------------------------------- 語法: limit_conn zone number; 默認: — 上下文: http, server, location 使用參數說明: Zone變量是一個須要引發的zone,zone在前面的limit_conn_zone命令中已經定義好,使用limit_conn_zone名義中定義的zone名稱便可引用,number參數用於定義一個數字,並應用到該zone,說明對該zone作併發鏈接數限制,最大併發鏈接數爲number定義的值,若是客戶端併發鏈接請求大於該值,則向客戶端返回503錯誤(服務暫時不可用)。 例如: limit_conn_zone $binary_remote_addr zone=addr:10m; server { location /download/ { limit_conn addr 1; }
在同一時間(at a time),一個IP僅容許一個鏈接。 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 語法: limit_rate rate; 默認: limit_rate 0; 上下文: http, server, location, if in location 參數使用說明 限制響應傳輸給客戶端的速率(下載速度),rate指定多少字節每秒,值爲0時不限速。注意,這裏是對鏈接限速,而不是對IP限速。若是一個IP容許兩個併發鏈接,那麼這個IP就是限速limit_rate×2。 |