nginx 安全配置文件
1.配置文件中有多處明確寫出了nginx的配置檔案路徑,該路徑是測試環境中的路徑,線上系統的nginx配置檔案與文件中所寫的路徑可能不一樣,在進行相關配置時,應以線上配置檔案的實際路徑為準。
線上系統nginx的安裝目錄在:/usr/local/nginx,預設配置檔案在/usr/local/nginx/conf/nginx.conf,此外也引用了/usr/local/nginx/conf/conf.d目錄下的配置檔案。
2.本文件僅包括了用於提升安全的配置方法。
3.在遵從本文件的方法進行配置前,請做好相關配置檔案的備份,以便在配置失敗時可以回退到變更前狀態。
1.新安裝,選用安全穩定版本
編號: |
Nginx_Sec_001 |
適用: |
LINUX下新安裝或者升級nginx伺服器 |
配置要求: |
1.安裝包要求從nginx官方網站獲取,官方網站地址:http://nginx.org/。 2.安裝包優先選用穩定版(stable)最新版,如果要跨大版本升級nginx,則要求在測試環境測試不存在相容性問題後才在生產環境進行部署。 3.要求對下載的原始碼安裝包檔案進行完整性驗證。
具體方法參考“備註”處的方法。 |
安全增強說明: |
1.從官方網站下載安裝包及對安裝包進行指紋驗證可以最大程度確保安裝檔案未被篡改; 2.使用最新版本,最大避免舊版版中已發現安全漏洞的威脅,使用穩定版可以確保功能穩定。 |
備註: |
完整性驗證方法: (1)每個nginx原始碼包都有一個簽名檔案,從官網訪問下載nginx原始碼包的同時也下載該原始碼包的簽名檔案到同一目錄,該簽名檔案是nginx官方使用pgp私鑰對原始碼包進行簽名得到,該檔案字尾.為.asc,獲取pgp簽名檔案方法:
(2)nginx原始碼包使用的是pgp簽名,進行簽名驗證時需要到GnuPG程式,如果沒有安裝該工具,可以使用yum install gnupg進行安裝。 (3)獲取pgp簽名檔案的公鑰 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 <[email protected]>" imported gpg: key A1C052F8: public key "Maxim Dounin <[email protected]>" 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 <[email protected]>" 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。 |