當前位置: 妍妍網 > 碼農

看過來,Nginx 生產環境下的安全配置不能不會!

2024-03-19碼農

關註上方 浩道Linux ,回復 資料 ,即可獲取海量 L inux Python 網路通訊、網路安全 等學習資料!

前言

大家好,這裏是 浩道Linux ,主要給大家分享 L inux P ython 網路通訊、網路安全等 相關的IT知識平台。

今天浩道跟大家分享Nginx 生產環境下的安全配置相關硬核幹貨,可以說安全的策略,我們運維人員應該形成一種先天意識,不得不會,一起學習下吧!

文章來源:https://blog.51cto.com/u_14249042/7633794

Nginx簡介

Nginx 是開源、高效能、高可靠的 Web 和反向代理伺服器,而且支持熱部署,幾乎可以做到 7 * 24 小時不間斷執行,即使執行幾個月也不需要重新啟動,還能在不間斷服務的情況下對軟體版本進行熱更新。效能是 Nginx 最重要的考量,其占用記憶體少、並行能力強、能支持高達 5w 個並行連線數,最重要的是, Nginx 是免費的並可以商業化,配置使用也比較簡單。

Nginx是一款輕量級的Web 伺服器/反向代理伺服器及電子信件(IMAP/POP3)代理伺服器,在BSD-like 協定下發行。其特點是占有記憶體少,並行能力強,事實上nginx的並行能力在同型別的網頁伺服器中表現較好,中國大陸使用nginx網站使用者有:百度、京東、新浪、網易、騰訊、淘寶等。

官網對各個模組參數配置的解釋說明網址: https://www.nginx.cn/doc/index.html

Nginx能幹什麽

做虛擬主機

那什麽是虛擬主機呢?也就是說,這個主機是不存在的,是虛擬出來的。而我們原來所說的伺服器,實際上是一台真正的PC機。所以虛擬主機就是原本這個機器不存在,但我們可以使用軟體模擬出來,這個就叫做虛擬主機。

反向代理

原本我們需要存取A機器,但現在我們可以透過B機器,轉發到A機器來實作存取,B機器就叫做代理。

負載均衡策略

首先我們來了解一下什麽叫負載,舉個例子,我們每個人背的 "東西"就是負載。而均衡則是指每個人背的東西一樣多。

在程式中,如果有多台伺服器來承載請求,那麽每個伺服器承載的請求個數是一樣的,這就稱為負載均衡。

輪詢策略

輪詢就是每個請求按時間順序,逐一分配到不同的後端伺服器,這是預設的負載均衡策略。如果後端伺服器down掉,能自動剔除。

權重(weight)策略

weight代表權重,預設為 1,權重越高被分配的客戶端就越多。指定輪詢機率,weight權重大小和存取比率成正比,該策略常用於後端伺服器效能不均衡的情況下。

IP_hash策略

ip_hash就是會對每個請求存取的ip進行hash運算,再根據結果進行分配,這樣每個訪客固定存取一個後端伺服器。

Nginx基本目錄解析

Nginx安全配置

以上對Nginx做了基本的功能介紹,下面重點介紹一下,我們的站點部署在生產環境下,如何去做安全配置和最佳化。

Nginx常用命令

nginx -s reload # 向主行程發送訊號,重新載入配置檔,熱重新開機nginx -s reopen # 重新開機 Nginxnginx -s stop # 快速關閉nginx -s quit # 等待工作行程處理完成後關閉nginx -T # 檢視當前 Nginx 最終的配置nginx -t # 檢查配置是否有問題

nginx.conf配置檔結構

Nginx 的典型配置範例:

# main段配置資訊user nginx; # 執行使用者,預設即是nginx,可以不進行設定worker_processes auto; # Nginx 行程數,一般設定為和 CPU 核數一樣error_log /var/log/nginx/error.log warn; # Nginx 的錯誤日誌存放目錄pid /var/run/nginx.pid; # Nginx 服務啟動時的 pid 存放位置# events段配置資訊events {useepoll; # 使用epoll的I/O模型(如果你不知道Nginx該使用哪種輪詢方法,會自動選擇一個最適合你作業系統的)worker_connections1024; # 每個行程允許最大並行數}# http段配置資訊# 配置使用最頻繁的部份,代理、緩存、日誌定義等絕大多數功能和第三方模組的配置都在這裏設定http { # 設定日誌模式log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status$body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main; # Nginx存取日誌存放位置sendfileon; # 開啟高效傳輸模式tcp_nopushon; # 減少網路報文段的數量tcp_nodelayon;keepalive_timeout65; # 保持連線的時間,也叫超時時間,單位秒types_hash_max_size2048;include /etc/nginx/mime.types; # 副檔名與型別對映表default_type application/octet-stream; # 預設檔型別include /etc/nginx/conf.d/*.conf; # 載入子配置項# server段配置資訊server {listen80; # 配置監聽的埠server_name localhost; # 配置的網域名稱# location段配置資訊location / {root /usr/share/nginx/html; # 網站根目錄index index.html index.htm; # 預設首頁檔deny172.168.22.11; # 禁止存取的ip地址,可以為allallow172.168.33.44# 允許存取的ip地址,可以為all } error_page 500502503504 /50x.html; # 預設50x對應的存取頁面error_page400404error.html; # 同上 }}

  • main 全域配置,對全域生效;

  • events 配置影響 Nginx 伺服器與使用者的網路連線;

  • http 配置代理,緩存,日誌定義等絕大多數功能和第三方模組的配置;

  • server 配置虛擬主機的相關參數,一個 http 塊中可以有多個 server 塊;

  • location 用於配置匹配的 uri ;

  • upstream 配置後端伺服器具體地址,負載均衡配置不可或缺的部份;

  • 用一張圖清晰的展示它的層級結構:

    nginx.conf 配置檔的語法規則:

    1. 配置檔由指令與指令塊構成

    2. 每條指令以 「;」 分號結尾,指令與參數間以空格符號分隔

    3. 指令塊以 {} 大括弧將多條指令組織在一起

    4. include 語句允許組合多個配置檔以提升可維護性

    5. 透過 # 符號添加註釋,提高可讀性

    6. 透過 $ 符號使用變量

    7. 部份指令的參數支持正規表式,例如常用的 location 指令

    基礎防護設定

    nginx 版本資訊隱藏

    server_tokensoff;

    隱藏Nginx後端服務X-Powered-By頭

    在http下配置proxy_hide_header項;增加或修改為proxy_hide_headerX-Powered-By;proxy_hide_headerServer;

    proxy_buffers和client_body_buffer_size的區別

    client_body_buffer_size

    處理客戶端請求體buffer大小。用來處理POST送出數據,上傳檔等。

    client_body_buffer_size

    需要足夠大以容納如果需要上傳POST數據。

    proxy_buffers

    處理後端響應,一般是代理伺服器請求後端服務的response。

    如果這個buffer不夠大,會引起磁盤IO,response的body內容會先寫入臨時目錄中。

    黑白名單設定

    如果網站被惡意灌水或 CC 攻 擊,可從網站日誌中分析特征 IP,將其 IP 或 IP 段進行遮蔽。

    #語法#allow address | CIDR | all;#deny address | CIDR | all;#模組:http/server/location#參數說明:#allow:允許存取。#deny:禁止存取。#address:具體的ip地址。#CIDR:ip加掩碼形式地址。#all:所有ip地址。白名單:# 只允許192.168.1.0/24網段的主機存取,拒絕其他所有location /path/ { allow 192.168.1.0/24; deny all;}黑名單:location /path/ { deny 192.168.1.0/24; allow all;}更多的時候客戶端請求會經過層層代理,我們需要透過$http_x_forwarded_for來進行限制,可以這樣寫set$allowfalse;if ($http_x_forwarded_for = "211.144.204.2") { set$allowtrue; }if ($http_x_forwarded_for ~ "108.2.66.[89]") { set$allowtrue; }if ($allow = false) { return 404; }

    遮蔽非常見蜘蛛(爬蟲)

    分析網站日誌發現,一些奇怪的 UA 總是頻繁的來存取,而這些 UA 對網站毫無意義,反而給伺服器增加壓力,可以直接將其遮蔽。

    if ($http_user_agent ~(SemrushBot|python|MJ12bot|AhrefsBot|AhrefsBot|hubspot|opensiteexplorer|leiki|webmeup)) {return444;}

    上面規則報錯 444 狀態碼而不是 403。444 狀態碼在 nginx 的中有特殊含義,nginx 的 444 狀態是直接由伺服器中斷連線,不會向客戶端再返回任何訊息。比返回 403 更加暴力。

    禁止某個目錄執行指令碼

    網站目錄,通常存放的都是靜態檔,如果因程式驗證不嚴謹被上傳木馬程式,導致網站被黑。以下規則請根據自身情況改為您自己的目錄,需要禁止的指令碼字尾也可以自行添加。

    #uploads|templets|data 這些目錄禁止執行 <a href="https://hexsen.com/tag/phpcode" title="更多關於 PHP 的文章" target="_blank">PHP</a>location ~* ^/(uploads|templets|data)/.*.(php|php5)$ {return444;}

    防止檔被下載

    比如將網站資料庫匯出到站點根目錄進行備份,很有可能也會被別人下載,從而導致數據遺失的風險。以下規則可以防止一些常規的檔被下載,可根據實際情況增減。

    location~ \.(zip|rar|sql|bak|gz|7z)$ {return444;}

    防止XSS攻擊:server

    在通常的請求響應中,瀏覽器會根據Content-Type來分辨響應的型別,但當響應型別未指定或錯誤指定時,瀏覽會嘗試啟用MIME-sniffing來猜測資源的響應型別,這是非常危險的,例如一個.jpg的圖片檔被惡意嵌入了可執行的js程式碼,在開啟資源型別猜測的情況下,瀏覽器將執行嵌入的js程式碼,可能會有意想不到的後果。

    add_headerX-Frame-Options "SAMEORIGIN";add_headerX-XSS-Protection "1; mode=block";add_headerX-Content-Type-Options "nosniff";*X-Frame-Options:響應頭表示是否允許瀏覽器載入frame等內容,有三個配置DENY:禁止任何網頁被嵌入;SAMEORIGIN: 只允許本網站的巢狀;ALLOW-FROM: 允許指定地址的巢狀;*X-XSS-Protection:表示啟用XSS過濾(禁用過濾為X-XSS-Protection: 0),mode=block表示若檢查到XSS攻擊則停止渲染頁面*X-Content-Type-Options:響應頭用來指定瀏覽器對未指定或錯誤指定Content-Type資源真正型別的猜測行為,nosniff 表示不允許任何猜測;

    其他請求頭的安全配置:server

    定義頁面可以載入哪些資源,上邊的配置會限制所有的外部資源,都只能從當前網域名稱載入,其中default-src定義針對所有型別資源的預設載入策略,self允許來自相同來源的內容

    add_header Content-Security-Policy "default-src 'self'";

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    會告訴瀏覽器用HTTPS協定代替HTTP來存取目標站點,上邊的配置表示當使用者第一次存取後,會返回一個包含了Strict-Transport-Security響應頭的欄位,這個欄位會告訴瀏覽器,在接下來的31536000秒內,當前網站的所有請求都使用https協定存取,參數includeSubDomains是可選的,表示所有子網域名稱也將采用同樣的規則

    緩沖區溢位攻擊

    透過將數據寫入緩沖區(http、server、location )並超出緩沖區邊界和重寫記憶體片段來實作的,限制緩沖區大小可有效防止

    client_body_buffer_size 1K;client_header_buffer_size 1k;client_max_body_size 1k;large_client_header_buffers 2 1k;* client_body_buffer_size:預設8k或16k,表示客戶端請求body占用緩沖區大小。如果連線請求超過緩存區指定的值,那麽這些請求實體的整體或部份將嘗試寫入一個臨時檔。* client_header_buffer_size:表示客戶端請求頭部的緩沖區大小。絕大多數情況下一個請求頭不會大於1k,不過如果有來自於wap客戶端的較大的cookie它可能會大於 1k,Nginx將分配給它一個更大的緩沖區,這個值可以在large_client_header_buffers裏面設定* client_max_body_size:表示客戶端請求的最大可接受body大小,它出現在請求頭部的Content-Length欄位, 如果請求大於指定的值,客戶端將收到一個"Request Entity Too Large" (413)錯誤,通常在上傳檔到伺服器時會受到限制* large_client_header_buffers 表示一些比較大的請求頭使用的緩沖區數量和大小,預設一個緩沖區大小為作業系統中分頁檔大小,通常是4k或8k,請求欄位不能大於一個緩沖區大小,如果客戶端發送一個比較大的頭,nginx將返回"Request URI too large" (414),請求的頭部最長欄位不能大於一個緩沖區,否則伺服器將返回"Bad request" (400)

    同時需要修改幾個超時時間的配置:client_body_timeout 10;client_header_timeout 10;keepalive_timeout 5 5;send_timeout 10;* client_body_timeout:表示讀取請求body的超時時間,如果連線超過這個時間而客戶端沒有任何響應,Nginx將返回"Request time out" (408)錯誤* client_header_timeout:表示讀取客戶端請求頭的超時時間,如果連線超過這個時間而客戶端沒有任何響應,Nginx將返回"Request time out" (408)錯誤* keepalive_timeout:參數的第一個值表示客戶端與伺服器長連線的超時時間,超過這個時間,伺服器將關閉連線,可選的第二個參數參數列示Response頭中Keep-Alive: timeout=time的time值,這個值可以使一些瀏覽器知道什麽時候關閉連線,以便伺服器不用重復關閉,如果不指定這個參數,nginx不會在應Response頭中發送Keep-Alive資訊* send_timeout:表示發送給客戶端應答後的超時時間,Timeout是指沒有進入完整established狀態,只完成了兩次握手,如果超過這個時間客戶端沒有任何響應,nginx將關閉連線

    防盜鏈:server、location

    location/images/ {valid_referersnone blocked www.ops-coffee.cn ops-coffee.cn;if($invalid_referer) {return403;}}valid_referers:驗證referer,none:允許referer為空blocked:允許不帶協定的請求

    除了以上兩類外僅允許referer為www.ops-coffee.cn或ops-coffee.cn時存取images下的圖片資源,否則返回403

    給不符合referer規則的請求重新導向到一個預設的圖片

    location /images/ {valid_referersblocked www.ops-coffee.cn ops-coffee.cn if ($invalid_referer) {rewrite ^/images/.*\.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last; }}

    一、限制存取方法

    禁止不安全的HTTP方法

    預設情況下,Nginx支持多種HTTP方法,包括GET、POST、OPTIONS等。然而,某些HTTP方法可能存在安全風險,例如TRACE方法可以被用於跨站指令碼(XSS)攻擊。我們可以使用Nginx的"limit_except"指令來限制某些HTTP方法的存取。
    範例程式碼:

    location / {limit_except GET POST {deny all; }}

    關閉不必要的目錄列表

    如果Nginx的目錄沒有預設的index檔,會自動展示目錄下的檔列表,這可能會暴露敏感資訊。我們可以透過禁止自動目錄列表的方式來阻止此行為。
    範例程式碼:

    location / {autoindexoff;}

    添加帳號認證:http、server、location

    server {location / {auth_basic"please input user&passwd";auth_basic_user_file key/auth.key; }}

    二、防止惡意請求和攻擊

    防止惡意請求

    惡意請求包括大量的請求、大檔上傳、惡意指令碼等等,這會導致伺服器負載過高。我們可以透過設定請求限制,來防止這種情況發生。
    範例程式碼:

    http {limit_req_zone$binary_remote_addr zone=req_limit:10m rate=1r/s;server {location / {limit_req zone=req_limit burst=5 nodelay;# 其他配置}}}

    上述程式碼中,我們使用"limit_req_zone"指令來定義請求限制區域,設定限制的大小和速率(每秒最多允許1個請求)。然後,在相應的"server"配置中使用"limit_req"指令來套用該限制區域。

    限制請求方法:server、location

    if ($request_method !~ ^(GET|POST)$ ) {return 405;}$request_method能夠獲取到請求nginx的method配置只允許GET\POST方法存取,其他的method返回405

    拒絕User-Agent:server、location

    if ($http_user_agent ~* LWP::Simple|BBBike|wget|curl) {return 444;}可能有一些不法者會利用wget/curl等工具掃描我們的網站,我們可以透過禁止相應的user-agent來簡單的防範Nginx的444狀態比較特殊,如果返回444那麽客戶端將不會收到伺服端返回的資訊,就像是網站無法連線一樣

    防止常見攻擊

    Nginx預設提供了一些防止常見攻擊的配置選項,例如:

    1. 防止緩沖區溢位攻擊: proxy_buffer_size proxy_buffers 配置選項

    2. 防止HTTP請求頭過大攻擊: large_client_header_buffers 配置選項

    3. 防止URI長度過大攻擊: large_client_header_buffers 配置選項

    4. 防止惡意請求: client_max_body_size 配置選項

    5. 防止DDoS攻擊: limit_conn limit_req 配置選項

    三、使用HTTPS保證數據傳輸安全

    HTTPS協定可以保證數據傳輸的機密性和完整性,防止數據被竊取或篡改。使用HTTPS可以防止中間人攻擊、數據劫持等安全問題。我們可以使用Nginx提供的SSL模組來配置HTTPS。
    範例程式碼:

    server {listen443 ssl;server_name example.com;ssl_certificate /path/to/certificate.crt;ssl_certificate_key /path/to/private.key;location / {# 其他配置}}

    上述程式碼中,我們使用 listen 443 ssl 指令來監聽443埠,並使用 ssl_certificate ssl_certificate_key 配置選項指定SSL證書路徑。

    更多精彩

    關註公眾號 浩道Linux

    浩道Linux ,專註於 Linux系統 的相關知識、 網路通訊 網路安全 Python相關 知識以及涵蓋IT行業相關技能的學習, 理論與實戰結合,真正讓你在學習工作中真正去用到所學。同時也會分享一些面試經驗,助你找到高薪offer,讓我們一起去學習,一起去進步,一起去漲薪!期待您的加入~~~ 關註回復「資料」可 免費獲取學習資料 (含有電子書籍、視訊等)。

    喜歡的話,記得 點「贊」 「在看」