博客 / 詳情

返回

小白入門學習Nginx代理服務器?看這篇最新Nginx進階學習最佳配置實踐指南就OK了

<!-- more -->

前置基礎知識學習

  • 1.Nginx基礎安裝與配置詳細 https://blog.weiyigeek.top/20...
  • 2.Nginx進階學習之最佳配置實踐指南 https://blog.weiyigeek.top/20...
  • 3.Nginx模塊學習使用實踐指南 https://blog.weiyigeek.top/20...
  • 4.Nginx安全加固與性能調優最佳指南 https://blog.weiyigeek.top/20...
  • 5.Nginx常遇問題入坑出坑整理 https://blog.weiyigeek.top/20...

0x00 編譯實踐

描述:在企業線上生產環境中推薦進行Nginx編譯安裝,可以按照業務側重點進行相應 Nginx 編譯參數配置,所以編譯參數不是功能加的越多越好,應該儘可能少編譯模塊不用的最好不要加入,本小結將以最新的Nginx版本以及依賴版本進行編譯演示。

Nginx-1.21.6+OpenSSL-1.1.1n

最新源碼構建安裝整理,當前最新版本nginx-1.21.6,實踐時間【2022年3月24日】
版本説明: pcre-8.45 、zlib-1.2.11、openssl-1.1.1n、nginx-1.21.6。

官方安裝參考地址: https://docs.nginx.com/nginx/...

步驟 01.在從源代碼編譯 NGINX Open Source 之前,您需要為其依賴項安裝庫:

  • PCRE – 支持正則表達式,NGINX Core 和 Rewrite 模塊需要。

    # http://pcre.org/
    # https://sourceforge.net/projects/pcre/files/
    wget -c https://nchc.dl.sourceforge.net/project/pcre/pcre/8.45/pcre-8.45.tar.bz2
    tar -jxf pcre-8.45.tar.bz2 && cd pcre-8.45
    ./configure
    make  && sudo make install
  • zlib – 支持標頭壓縮, NGINX Gzip 模塊需要。

    # http://www.zlib.net/
    wget -c http://zlib.net/zlib-1.2.11.tar.gz
    tar -zxf zlib-1.2.11.tar.gz && cd zlib-1.2.11
    ./configure
    make && sudo make install
  • OpenSSL – 支持 HTTPS 協議, NGINX SSL 模塊和其他模塊需要。

    # https://www.openssl.org/source/
    wget -c http://www.openssl.org/source/openssl-1.1.1n.tar.gz
    tar -zxf openssl-1.1.1n.tar.gz && cd openssl-1.1.1n
    ./config --prefix=/usr/local/openssl
    make && sudo make install
    # lib 庫加載到系統
    echo "/usr/local/openssl/lib" >> /etc/ld.so.conf.d/libc.conf
    ldconfig
    # 可以看到當下系統的Openssl版本已經更新到最新
    # root@weiyigeek-top:/usr/local/openssl/bin# openssl version
    # OpenSSL 1.1.1n  15 Mar 2022

步驟 02.從 nginx.org 下載穩定版和主線版本的源代碼文件,要下載並解壓最新主線版本的源代碼,請運行:

# https://nginx.org
sudo mkdir -vp /usr/local/nginx/module /usr/lib/nginx/modules /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp} 
wget https://nginx.org/download/nginx-1.21.6.tar.gz
tar zxf nginx-1.21.6.tar.gz && cd nginx-1.21.6
$ ./configure \
--prefix=/usr/local/nginx \
--with-pcre=../pcre-8.45 \
--with-zlib=../zlib-1.2.11 \
--user=ubuntu --group=ubuntu \
--sbin-path=/usr/sbin/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--lock-path=/var/run/nginx.lock \
--modules-path=/usr/lib/nginx/modules \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_geoip_module \
--with-threads --with-mail --with-mail_ssl_module \
--with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module \
--with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module \
--with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module \
--with-compat --with-file-aio \
--with-cc-opt='-Os -fomit-frame-pointer -g' --with-ld-opt=-Wl,--as-needed,-O1,--sort-common
# <!-- --add-dynamic-module=/usr/local/nginx/module -->

Tips :請注意 geoip_module 模塊, 如果需要使用則需要提前安裝好 GeoIP library,例如在Ubuntu系統上執行apt-get install libgeoip-dev如下命令。

Tips : 請注意 通過yum或者apt安裝的nginx,通常會將nginx的配置文件放在/etc/nginx,而手動編譯構建的一般是在 /usr/local/nginx 目錄中。

步驟 03.執行./configure命令後的結果如下

Configuration summary
  + using threads
  + using PCRE library: ../pcre-8.45
  + using system OpenSSL library
  + using zlib library: ../zlib-1.2.11

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/usr/lib/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx"
  nginx configuration file: "/usr/local/nginx/nginx.conf"
  nginx pid file: "/usr/local/nginx/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/cache/nginx/client_temp"
  nginx http proxy temporary files: "/var/cache/nginx/proxy_temp"
  nginx http fastcgi temporary files: "/var/cache/nginx/fastcgi_temp"
  nginx http uwsgi temporary files: "/var/cache/nginx/uwsgi_temp"
  nginx http scgi temporary files: "/var/cache/nginx/scgi_temp"

步驟 04.執行構建安裝後查看nginx版本以及構建參數等信息

$ nginx -V
nginx version: nginx/1.21.6
built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04)
built with OpenSSL 1.1.1n  15 Mar 2022
TLS SNI support enabled
  configure arguments: --prefix=/usr/local/nginx --with-pcre=../pcre-8.45 --with-zlib=../zlib-1.2.11 --user=ubuntu --group=ubuntu --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/run/nginx.lock --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_geoip_module --with-threads --with-mail --with-mail_ssl_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-compat --with-file-aio --with-cc-opt='-Os -fomit-frame-pointer -g' --with-ld-opt=-Wl,--as-needed,-O1,--sort-common

步驟 05.執行/usr/sbin/nginx命令, 啓用nginx服務並查看提供的服務。

# 查看Nginx併發進程數
$ ps -ef | grep nginx | grep -v "grep" | wc -l
3

Nginx編譯(configure) 參數一覽

描述: 我們可以執行./configure --help便可以查看編譯相關參數。

# 常用選項 #
--prefix= #指向安裝目錄
--user= #指定程序運行時的非特權用户
--group= #指定程序運行時的非特權用户組
--with-perl= #設定perl庫文件路徑啓用pcre庫
--with-perl_modules_path= #設定perl模塊路徑
--with-pcre-opt= 在編譯時為pcre庫設置附加參數

--with-zlib= #指向zlib庫目錄
--with-zlib-opt= #在編譯時為zlib設置附加參數
--with-zlib-asm= #為指定的CPU使用zlib彙編源進行優化,CPU類型為pentium, pentiumpro

--with-openssl= #指向openssl安裝目錄
--with-openssl-opt #在編譯時為openssl設置附加參數
--with-http_ssl_module #啓用ngx_http_ssl_module支持(使支持https請求,需已安裝openssl)

--with-cc-opt= #設置C編譯器參數將被添加到CFLAGS變量(PCRE庫,需要指定–with-cc-opt=”-I /usr/local/include”,如果使用select()函數則需要同時增加文件描述符數量,可以通過–with-cc- opt=”-D FD_SETSIZE=2048”指定。)
--with-ld-opt= #設置連接文件參數鏈接系統庫。(PCRE庫,需要指定–with-ld-opt=”-L /usr/local/lib”。)
--with-cpu-opt= #指定編譯的CPU,可用的值為: pentium, pentiumpro, pentium3, pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64


#下面按需配置
--conf-path= #指向配置文件(nginx.conf)
--error-log-path= #指向錯誤日誌目錄
--pid-path= #指向pid文件(nginx.pid)
--sbin-path= #指向(執行)程序文件(nginx)
--lock-path= #指向lock文件(nginx.lock)(安裝文件鎖定,防止安裝文件被別人利用,或自己誤操作。)
--builddir= #指向編譯目錄

#模塊添加
--with-rtsig_module #啓用rtsig模塊支持(實時信號)
--with-select_module #啓用select模塊支持(一種輪詢模式,不推薦在高載環境下使用)禁用:–without-select_module
--with-poll_module #啓用poll模塊支持(功能與select相同,與select特性相同,為一種輪詢模式,不推薦在高載環境下使用)
--with-file-aio #啓用file aio支持(一種APL文件傳輸格式)
--with-ipv6 #啓用ipv6支持
--with-http_realip_module #啓用ngx_http_realip_module支持(這個模塊允許從請求標頭更改客户端的IP地址值,默認為關)
--with-http_addition_module #啓用ngx_http_addition_module支持(作為一個輸出過濾器,支持不完全緩衝,分部分響應請求)
--with-http_xslt_module #啓用ngx_http_xslt_module支持(過濾轉換XML請求)
--with-http_image_filter_module #啓用ngx_http_image_filter_module支持(傳輸JPEG/GIF/PNG 圖片的一個過濾器)(默認為不啓用、gd庫要用到)
--with-http_geoip_module #啓用ngx_http_geoip_module支持(該模塊創建基於與MaxMind GeoIP二進制文件相配的客户端IP地址的ngx_http_geoip_module變量)
--with-http_sub_module #啓用ngx_http_sub_module支持(允許用一些其他文本替換nginx響應中的一些文本)
--with-http_dav_module #啓用ngx_http_dav_module支持(增加PUT,DELETE,MKCOL:創建集合,COPY和MOVE方法)默認情況下為關閉,需編譯開啓
--with-http_flv_module #啓用ngx_http_flv_module支持(提供尋求內存使用基於時間的偏移量文件)
--with-http_gzip_static_module #啓用ngx_http_gzip_static_module支持(在線實時壓縮輸出數據流)
--with-http_random_index_module #啓用ngx_http_random_index_module支持(從目錄中隨機挑選一個目錄索引)
--with-http_secure_link_module #啓用ngx_http_secure_link_module支持(計算和檢查要求所需的安全鏈接網址)
--with-http_degradation_module  #啓用ngx_http_degradation_module支持(允許在內存不足的情況下返回204或444碼)
--with-http_stub_status_module   #啓用ngx_http_stub_status_module支持(獲取nginx自上次啓動以來的工作狀態)

--without-http_charset_module #禁用ngx_http_charset_module支持(重新編碼web頁面,但只能是一個方向–服務器端到客户端,並且只有一個字節的編碼可以被重新編碼)
--without-http_gzip_module #禁用ngx_http_gzip_module支持(該模塊同-with-http_gzip_static_module功能一樣)

--without-http_ssi_module #禁用ngx_http_ssi_module支持(該模塊提供了一個在輸入端處理處理服務器包含文件(SSI)的過濾器,目前支持SSI命令的列表是不完整的)

--without-http_userid_module #禁用ngx_http_userid_module支持(該模塊用來處理用來確定客户端後續請求的cookies)

--without-http_access_module #禁用ngx_http_access_module支持(該模塊提供了一個簡單的基於主機的訪問控制。允許/拒絕基於ip地址)

--without-http_auth_basic_module #禁用ngx_http_auth_basic_module(該模塊是可以使用用户名和密碼基於http基本認證方法來保護你的站點或其部分內容)

--without-http_autoindex_module #禁用disable ngx_http_autoindex_module支持(該模塊用於自動生成目錄列表,只在ngx_http_index_module模塊未找到索引文件時發出請求。)

--without-http_geo_module #禁用ngx_http_geo_module支持(創建一些變量,其值依賴於客户端的IP地址)

--without-http_map_module #禁用ngx_http_map_module支持(使用任意的鍵/值對設置配置變量)

--without-http_split_clients_module #禁用ngx_http_split_clients_module支持(該模塊用來基於某些條件劃分用户。條件如:ip地址、報頭、cookies等等)

--without-http_referer_module #禁用disable ngx_http_referer_module支持(該模塊用來過濾請求,拒絕報頭中Referer值不正確的請求)

--without-http_rewrite_module #禁用ngx_http_rewrite_module支持(該模塊允許使用正則表達式改變URI,並且根據變量來轉向以及選擇配置。如果在server級 別設置該選項,那麼他們將在 location之前生效。如果在location還有更進一步的重寫規則,location部分的規則依然會被執行。如果這個URI重寫是因為 location部分的規則造成的,那麼 location部分會再次被執行作為新的URI。 這個循環會執行10次,然後Nginx會返回一個500錯誤。)

--without-http_proxy_module #禁用ngx_http_proxy_module支持(有關代理服務器)

--without-http_fastcgi_module #禁用ngx_http_fastcgi_module支持(該模塊允許Nginx 與FastCGI 進程交互,並通過傳遞參數來控制FastCGI 進程工作。 )FastCGI一個常駐型的公共網關接口。

--without-http_uwsgi_module #禁用ngx_http_uwsgi_module支持(該模塊用來醫用uwsgi協議,uWSGI服務器相關)

--without-http_scgi_module #禁用ngx_http_scgi_module支持(該模塊用來啓用SCGI協議支持,SCGI協議是CGI協議的替代。它是一種應用程序與HTTP服務接口標準。它有些像FastCGI但他的設計 更容易實現。)

--without-http_memcached_module #禁用ngx_http_memcached_module支持(該模塊用來提供簡單的緩存,以提高系統效率)
-without-http_limit_zone_module #禁用ngx_http_limit_zone_module支持(該模塊可以針對條件,進行會話的併發連接數控制)
--without-http_limit_req_module #禁用ngx_http_limit_req_module支持(該模塊允許你對於一個地址進行請求數量的限制用一個給定的session或一個特定的事件)
--without-http_empty_gif_module #禁用ngx_http_empty_gif_module支持(該模塊在內存中常駐了一個1*1的透明GIF圖像,可以被非常快速的調用)
--without-http_browser_module #禁用ngx_http_browser_module支持(該模塊用來創建依賴於請求報頭的值。如果瀏覽器為modern ,則$modern_browser等於modern_browser_value指令分配的值;如 果瀏覽器為old,則$ancient_browser等於 ancient_browser_value指令分配的值;如果瀏覽器為 MSIE中的任意版本,則 $msie等於1)
--without-http_upstream_ip_hash_module #禁用ngx_http_upstream_ip_hash_module支持(該模塊用於簡單的負載均衡)
--with-http_perl_module #啓用ngx_http_perl_module支持(該模塊使nginx可以直接使用perl或通過ssi調用perl)


--http-log-path=           # 設定access log路徑
--http-client-body-temp-path= # 設定http客户端請求臨時文件路徑
--http-proxy-temp-path=    # 設定http代理臨時文件路徑
--http-fastcgi-temp-path=  # 設定http fastcgi臨時文件路徑
--http-uwsgi-temp-path=    # 設定http uwsgi臨時文件路徑
--http-scgi-temp-path=    # 設定http scgi臨時文件路徑

-without-http # 禁用http server功能
--without-http-cache # 禁用http cache功能

--with-mail #啓用POP3/IMAP4/SMTP代理模塊支持
--with-mail_ssl_module 啓用ngx_mail_ssl_module支持
--without-mail_pop3_module #禁用pop3協議(POP3即郵局協議的第3個版本,它是規定個人計算機如何連接到互聯網上的郵件服務器進行收發郵件的協議。是因特網電子郵件的第一個離 線協議標 準,POP3協議允許用户從服務器上把郵件存儲到本地主機上,同時根據客户端的操作刪除或保存在郵件服務器上的郵件。POP3協議是TCP/IP協議族中 的一員,主要用於 支持使用客户端遠程管理在服務器上的電子郵件)
--without-mail_imap_module #禁用imap協議(一種郵件獲取協議。它的主要作用是郵件客户端可以通過這種協議從郵件服務器上獲取郵件的信息,下載郵件等。IMAP協議運行在 TCP/IP協議之上, 使用的端口是143。它與POP3協議的主要區別是用户可以不用把所有的郵件全部下載,可以通過客户端直接對服務器上的郵件進行操作。)
--without-mail_smtp_module #禁用smtp協議(SMTP即簡單郵件傳輸協議,它是一組用於由源地址到目的地址傳送郵件的規則,由它來控制信件的中轉方式。SMTP協議屬於 TCP/IP協議族,它幫助每台計算機在發送或中轉信件時找到下一個目的地。)
--with-google_perftools_module #啓用ngx_google_perftools_module支持(調試用,剖析程序性能瓶頸)
--with-cpp_test_module #啓用ngx_cpp_test_module支持

--add-module= #啓用外部模塊支持

--with-cc=  # 指向C編譯器路徑
--with-cpp= # 指向C預處理路徑

--without-pcre #禁用pcre庫

--with-md5=     # 指向md5庫文件目錄(消息摘要算法第五版,用以提供消息的完整性保護)
--with-md5-opt= # 在編譯時為md5庫設置附加參數
--with-md5-asm  # 使用md5彙編源

--with-sha1=     # 指向sha1庫目錄(數字簽名算法,主要用於數字簽名)
--with-sha1-opt= # 在編譯時為sha1庫設置附加參數
--with-sha1-asm  # 使用sha1彙編源

--with-libatomic  # 為原子內存的更新操作的實現提供一個架構
--with-libatomic= # 指向libatomic_ops安裝目錄

--with-debug # 啓用debug日誌


Shell腳本一鍵部署虛擬主機(附上關鍵性腳本):
完整代碼:https://github.com/weiyigeek/...

#!/bin/bash
#@Desc:Nginx多實例部署虛擬主機
#@Author:WeiyiGeek
#@CreatTime:2020年3月8日 12點06分
#@Site:WeiyiGeek.top
#@Test_Linux: Linux weiyigeek 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
#@release:CentOS Linux release 7.4.1708 (Core)

## Define nginx variable
NGX_VER=1.16.1
NGX_URI="http://nginx.org/download/nginx-${NGX_VER}.tar.gz"
NGX_SRC="nginx-${NGX_VER}.tar.gz"
NGX_NAME=${NGX_SRC%.tar.gz}
NGX_DIR="/usr/local/nginx/${NGX_VER}"
NGX_ARGS="--prefix=${NGX_DIR} --user=nginx --group=nginx --with-http_stub_status_module"
NGX_SRCCODE="${NGX_NAME}/src/core/nginx.h"
NGX_VHDIR="${NGX_DIR}/conf/domains"

## Define 防火牆開放端口
FIREWALL_PORT=(80 8080)


## [Nginx INSTALL]
function nginx_install(){
    echo -e "\e[32m1.核查安裝依賴....... \e[0m"
    CHECK_SOFT=$(rpm -qa | grep -cE "^gcc|^pcre|^zlib")
    if [ $CHECK_SOFT -lt 2 ];then yum install -y gcc gcc-c++ pcre pcre-devel zlib-devel;fi

    echo -e "\e[32m2.檢查nginx源碼包是否存在....... \e[0m"
    if [ ! -f $NGX_SRC ];then wget -c $NGX_URI;fi
    if [ ! -d $NGX_NAME ];then tar -zxf $NGX_SRC;fi

    echo -e "\e[32m3.nginx安裝陸軍是否存在....... \e[0m"
    if [ ! -f $NGX_DIR/sbin/nginx ];then mkdir -vp $NGX_DIR;fi

    echo -e "\e[32m3.驗證nginx用户是否存在不存在則建立低權限用户....... \e[0m"
    CHECK_USER=$(getent passwd | grep -wc nginx)
    if [ $CHECK_USER -eq 0 ];then useradd -s /sbin/nologin nginx -M; fi

    echo -e "安全設置:Nginx版本隱藏......"
    sed -i "s/$NGX_VER//g" $NGX_SRCCODE
    sed -i 's/nginx\//JWS/g' $NGX_SRCCODE
    sed -i 's/"NGINX"/"JWS"/g' $NGX_SRCCODE

    echo -e "\e[32m4.進行nginx預編譯及其編譯安裝....... \e[0m"
    cd $NGX_NAME && ./configure $NGX_ARGS 
    if [ $? -eq 0 ];then
        #進行2個線程並行編譯(可以根據你處理器個數選擇)
        make -j2 && make -j2 install
    else
        echo -e "\e[31m#Error: 預編譯失敗!終止安裝,請檢查軟件依賴! \e[0m"
        exit
    fi
    if [ $? -ne 0 ];then echo -e "\e[31m#Error: 編譯安裝失敗!終止安裝 \e[0m";exit;fi
    echo -e "\e[32m Nginx 成功安裝....... \n安裝目錄:${NGX_DIR} \n 正在啓動Nginx....\e[0m"
    $NGX_DIR/sbin/nginx
}

## [Nginx CONFIG]
function nginx_vhost(){
    NGX_VHOSTS=$1
    firewall_config
    cd ${NGX_DIR}
    NGX_CNF="${NGX_DIR}/conf/nginx.conf"
    if [ ! -f $NGX_CONF ];then echo -e "Nginx-配置文件不存在請仔細檢查!";exit;fi
    #判斷是否已經存在domains配置文件是則不同重新建立;
    grep "domains" ${NGX_CNF} >>/dev/null 2>&1
    if [ $? -ne 0 ];then
        #備份NGX配置文件
        cp ${NGX_CNF}{,_$(date +%F_%H%M%S).bak}
        mkdir -vp ${NGX_VHDIR}
        sed -i "s/#user  nobody/user  nginx/g" ${NGX_CNF}
        sed -i "s/#gzip/gzip/g" ${NGX_CNF}
        #去除空行以及註釋
        grep -vE "#|^$" ${NGX_CNF} > ${NGX_CNF}.swp
        #重點刪除server字符到文件末尾
        sed -i '/server/,$d' ${NGX_CNF}.swp
        cp ${NGX_CNF}.swp ${NGX_CNF}
        echo -e "    include domains/*;\n}" >> ${NGX_CNF}
    fi
    
cat>${NGX_VHDIR}/$NGX_VHOSTS.conf<<EOF
server {
    listen       80;
    server_name  $NGX_VHOSTS;

    location / {
        root   html/$NGX_VHOSTS;
        index  index.html index.htm;
    }
    #Nginx 監控模塊啓用
    location /nginxStatus {
        stub_status;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}
EOF
   

echo -e "\e[32m$NGX_VHOSTS 網站目錄建立之中.....\e[0m"
if [ ! -d $NGX_DIR/html/$NGX_VHOSTS/ ];then
    mkdir -vp $NGX_DIR/html/$NGX_VHOSTS/
cat>$NGX_DIR/html/$NGX_VHOSTS/index.html<<EOF
<h1>$NGX_VHOSTS Test Pages. </h1>
<p>By WeiyiGeek.top </p>
<hr color=red>
EOF
fi
    echo -e "\e[32mNginx配置文件驗證中.....\e[0m"
    $NGX_DIR/sbin/nginx -t
    if [ $? -ne 0 ];then
        echo -e "\e[31mNginx配置文件有誤,請處理錯誤後重啓Nginx服務器:\n ${NGX_DIR}/sbin/nginx -s reload"
    fi
    cat ${NGX_VHDIR}/$NGX_VHOSTS.conf

    echo -e "\e[32mNginx重啓之中.....\e[0m"
    $NGX_DIR/sbin/nginx -s reload
    CHECK_STATUS=$(netstat -tlnp | grep -wc "nginx")
    if [ $CHECK_STATUS -ne 0 ];then
        echo -e "\e[32m#Nginx 啓動成功.... \e[0m"
    else
        echo -e "\e[31m#Nginx 啓動失敗.... \e[0m"
    fi
}

運行效果:
WeiyiGeek.運行效果

測試效果:
WeiyiGeek.測試效果


0x01 Nginx 配置最佳實踐

Nginx 之 多配置文件配置

描述: Nginx配置文件中支持包含多個配置文件,比如下面的虛擬主機的配置將使用,在程序加載運行時候首先會讀取nginx.conf 的配置文件,然後再讀取 /etc/nginx/conf.d/下面的配置文件;

例如,我們需要在/etc/nginx/nginx.conf文件中,進行如下設置include /etc/nginx/conf.d/*.conf;

http {
  ....
  include conf.d/*.conf;
  ....
}

WeiyiGeek.

<br/>

Nginx 之 Server 偵聽端口主機頭配置淺析

描述:常規網站編譯安裝後運行只是單個網站訪問,我們如何可以做到多網站同時運行到該Nginx服務器上,那我們便可使用Nginx提供的虛擬機主機方式, 使得一個服務端口可以訪問不同的服務應用;

常規有三種方式:

  • 1) 多端口
  • 2) 多IP
  • 3) 多域名:虛擬主機(VirtualHost)

環境準備:

cat >> /etc/hosts<<END
127.0.0.1 v1.weiyigeek.top v2.weiyigeek.top
END

流程步驟:

  • 1.修改移除Nginx.conf配置文件中的Server {...}包含的參數添加include domains/*;;

    user  nginx;
    worker_processes  1;
    events {
      worker_connections  1024;
    }
    http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    gzip  on;
    include domains/*;
    }
  • 2.在Nginx的Conf目錄中建立一個domains目錄(注意這裏不要建立到上級目錄之中,否則會出現nginx master進程已經啓動但是無監聽端口),進入該目錄中建立虛擬主機v1.weiyigeek.top.conf文件

    server {
    listen       80;
    server_name  v1.weiyigeek.top;  #關鍵點
    location / {
      #關鍵點
      root   html/v1.weiyigeek.top;
      index  index.html index.htm;
    }
    #Nginx 監控模塊啓用
    location /nginxStatus {
        stub_status;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
    }
  • 3.在nginx安裝目錄中的html中建立一個與虛擬主機同名的文件夾(當然名字您可以任意取,但是必須和v1.weiyigeek.top.conf中指定路與的root一致)

    [root@WeiyiGeek html]# pwd
    /usr/local/nginx/1.16.1/html
    [root@WeiyiGeek html]# ls
    50x.html  index.html  v1.weiyigeek.top  v2.weiyigeek.top

<br/>

配置示例

server {
  # 使用標準 HTTP 協議
  listen 80;
  # 使用標準 HTTPS 協議
  listen 443 ssl;
  # 使用 http2 協議
  listen 443 ssl http2;
  # 使用IPV6地址監聽80端口
  listen [::]:80;
  # 只使用IPV6地址監聽80端口
  listen [::]:80 ipv6only=on;

  # 匹配指定域名訪問
  server_name weiyigeek.top;
  # 匹配多域名訪問
  server_name weiyigeek.top www.weiyigeek.top;
  # 匹配weiyigeek.top下所有子域名
  server_name *.weiyigeek.top;
  # 匹配所有的包含weiyigeek.top的頂級域名
  server_name weiyigeek.top.*;
  # 僅匹配IP地址訪問
  server_name "";
  server_name _;
}

温馨提示: 當網站設置支持http2以後可以從請求響應頭中看到如下字段 X-Firefox-Spdy:h2
WeiyiGeek.nginx-http/2

<br/>

Nginx 之 Location 規則配置淺析

描述: Location 語法規則:location [=|~|~*|^~] /uri/ { … }

  • =: 表示精確匹配.
  • /: 表示通用匹配, 即任何請求都會匹配到。
  • ~: 表示區分大小寫的正則匹配.
  • ~*: 表示不區分大小寫的正則匹配.
  • !~,!~* : 分別標識為區分大小寫不匹配及不區分大小寫不匹配的正則
  • ^~: 表示URL以某個常規字符串開頭,可以理解為匹配url路徑即可,值得注意的是Nginx不對URL做編碼,例如會將請求為/static/20%/aa被^~ /static/ /aa規則匹配到。

默認情況下 location 的匹配順序為精確匹配 -> 開頭匹配(^~) -> 文件順序中的正則匹配 -> 通用匹配(/), 當有匹配成功的URL則停止匹配。

例如,有如下匹配規則:

location = / {
  #規則A.精確匹配 / URL 下的操作。
}
location = /login {
  #規則B.精確匹配 /login URL 下的操作。
}
location ^~ /static/ {
  #規則C.正則匹配 /static/ URL 下的操作。
}
location ~ \.(gif|jpg|png|svg|js|css)$ {
  #規則D,注意:是根據括號內的大小寫進行匹配,括號內全是小寫只匹配小寫。
}
location ~* \.(gif|jpg|png|svg|js|css)$ {
  #規則D,注意:忽略大寫來匹配靜態資源後綴。
}
location ~* \.png$ {
  #規則E.匹配以.png或者.PNG結尾的靜態資源。
}
location !~ \.xhtml$ {
  #規則F.不匹配.xhtml為後綴的資源。
}
location !~* \.xhtml$ {
  #規則G.不匹配.xhtml或者.XHTML為後綴的資源。
}
location / {
  #規則H.通用匹配,當上述匹配都不能匹配時,使用該規則。
}

<br/>

在實踐過程中常見, 有如下幾種匹配規則:

# 第一個必選規則是直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,
# 這裏可以是直接轉發給後端應用服務器了,也可以是一個靜態首頁。
location = / {
  root /usr/local/nginx/html
  proxy_pass http://tomcat:8080/index
}
 
# 第二個必選規則是處理靜態文件請求,這是nginx作為http服務器的強項
# 有兩種配置模式,目錄匹配或後綴匹配,任選其一或搭配使用
location ^~ /static/ {                             # // 以xx開頭
  root /webroot/static/;   # 注意,需要指定跟目錄.
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {     # // 以xx結尾
  root /webroot/res/;  
}
 
#第三個規則就是通用規則,用來轉發動態請求到後端應用服務器
#非靜態文件請求就默認是動態請求,自己根據實際把握
location / {
  proxy_pass http://tomcat:8080/
}


Nginx 之 規則判斷表達式淺析

Nginx 常用判斷表達式如下:

  • -f和!-f: 用來判斷是否存在文件
  • -d和!-d:用來判斷是否存在目錄
  • -e和!-e:用來判斷是否存在文件或目錄
  • -x和!-x:用來判斷文件是否可執行
  • 除此之外我們還可以使用上一小節的正則匹配符進行判斷。


nginx 全局變量一覽:

arg_PARAMETER      # 這個變量包含GET請求中,如果有變量PARAMETER時的值。
args               # 這個變量等於請求行中(GET請求)的參數,如:foo=123&bar=blahblah;
binary_remote_addr # 二進制的客户地址。
body_bytes_sent    # 響應時送出的body字節數數量。即使連接中斷,這個數據也是精確的。
content_length    # 請求頭中的Content-length字段。
content_type      # 請求頭中的Content-Type字段。
cookie_COOKIE     # cookie COOKIE變量的值
document_root     # 當前請求在root指令中指定的值。
document_uri      # 與uri相同。
host              # 請求主機頭字段,否則為服務器名稱。
hostname          # 設置為gethostname返回的機器主機名
http_HEADER       # 請求header頭字段
is_args           # 如果有args參數,這個變量等於”?”,否則等於”",空值。
http_user_agent   # 客户端agent信息
http_cookie       # 客户端cookie信息
limit_rate        # 這個變量可以限制連接速率。
query_string      # 與args相同。
request_body_file  #客户端請求主體信息的臨時文件名。
request_method    #客户端請求的動作,通常為GET或POST。
remote_addr          #客户端的IP地址。
remote_port          #客户端的端口。
remote_user          #已經經過Auth Basic Module驗證的用户名。
request_completion #如果請求結束,設置為OK. 當請求未結束或如果該請求不是請求鏈串的最後一個時,為空(Empty)。
request_method    #GET或POST
request_filename  #當前請求的文件路徑,由root或alias指令與URI請求生成。
request_uri          #包含請求參數的原始URI,不包含主機名,如:”/foo/bar.php?arg=baz”。不能修改。
scheme                #HTTP方法(如http,https)。
server_protocol      #請求使用的協議,通常是HTTP/1.0或HTTP/1.1。
server_addr          #服務器地址,在完成一次系統調用後可以確定這個值。
server_name        #服務器名稱。
server_port          #請求到達服務器的端口號。

<br/>

Nginx 解析URL用作判斷的全局變量,例如,訪問的URL為http://weiyigeek.top:8080/test1/test2/test.php.

$host:weiyigeek.top
$server_port:8080
$request_uri:http://weiyigeek.top:8080/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/data/nginx/html
$request_filename:/data/html/test1/test2/test.php

<br/>

簡單示例:

  • 1.判斷請求的靜態資源文件是否是存在的,如不存在則返回403.

    location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
    if (-f $request_filename) { 
      return 403;
      break;
    }
    }
  • 2.判斷Nginx全局變量並進行跳轉到指定頁面。

    if ( $host !~* weiyigeek\.top ) {
    return 301 https://space.bilibili.com/385802642;
    }
  • 3.文件反盜鏈並設置過期時間

    location ~*^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
    valid_referers none blocked *.weiyigeek.top localhost 127.0.0.1;
    if ($invalid_referer) {
        rewrite ^/ https://weiyigeek.top/wechat.html;
        return 412;
        break;
    }
    root /usr/local/nginx/html
    access_log  off;
    expires 3d;
    break;
    }
  • 4.自定義變量判斷跳轉到指定頁面.

    # 僅允許222.222.222.222或者內網的兩個IP訪問,其他IP都rewrite到停服頁面
    if ( $remote_addr = 222.222.222.222){set $my_ip 1;}
    if ( $remote_addr = 192.168.1.170 ){ set $my_ip 1;}
    if ( $remote_addr = 192.168.1.169 ){ set $my_ip 1;}
    if ( $my_ip != 1) {rewrite ^/design/(.*)\.php$ /weiyigeek.html?$1&;}  #將*.php轉到tingfu.html

温馨提示: 此處以Nginx暴露給互聯網, 所以利用 $remote_addr 變量獲取訪問者地址, 如果用了負載均衡的話此處應該是$http_x_forwarded_for 變量。

<br/>

Nginx 之 Redirect重定向與ReWrite重寫 配置淺析

Redirect(重定向)語法示例

# http 向 https 跳轉 (永久)
server {
  listen 80;
  server_name weiyigeek.top www.weiyigeek.top;
  return 301 https://$host$request_uri;
}

# http 向 https 跳轉(臨時)
server {
  listen 80;
  server_name weiyigeek.top www.weiyigeek.top;
  return 302 https://www.weiyigeek.top$request_uri;
}

<br/>

ReWrite 重寫語法示例
rewrite 正則表達式以及其可用參數:

  • last : 基本上都用這個Flag。
  • break : 中止 Rewirte 不在繼續匹配
  • redirect : 返回臨時重定向的HTTP狀態302
  • permanent : 返回永久重定向的HTTP狀態301
# http 向 https 跳轉
server {
  listen 80;
  server_name weiyigeek.top www.weiyigeek.top;
  # 判斷請求host是否是 www.weiyigeek.top ,如果是 weiyigeek.top 則重寫為 www.weiyigeek.top 
  if ($http_host !~ "^www\.weiyigeek\.top$" {
    rewrite ^(.*) https://www.weiyigeek.top$1 permanent;
  }
}

# 利用重寫規則防止盜鏈
location ~* \.(gif|jpg|png|svg|css|js)$ {
  valid_referers none blocked *.weiyigeek.top localhost 127.0.0.1 server_names ~\.google\. ~\.baidu\.;
  if ($invalid_referer) {
    rewrite ^/ https://www.weiyigeek.top/403.jpg;
  }
}

# 利用重寫功能可將網頁中舊的訪問目錄重寫到新的訪問路徑
# 例如, 如果訪問https://blogwww.weiyigeek.top/2020/10/515.html 則將顯示首頁。
if ( $document_uri ~* /([0-9]+)/([0-9]+)/([0-9]+)\.html$) {
  rewrite ^/ /index.html last;
}

温馨提示:301 與 302 狀態碼的不同區別。

  • 301 redirect: 301 代表永久性轉移( Permanently Moved ) - 網站SEO推薦。
  • 302 redirect: 302 代表暫時性轉移( Temporarily Moved )

<br/>

Nginx 之 SSL 證書安全配置淺析

描述: 通常為了保證網站數據在傳輸過程中不被竊取和篡改,我們需要為其配置SSL證書,而在Nginx中配置方法是非常的簡單的,不過最重要的還是你要生成私鑰以及證書申請文件csr向證書頒發機構生成網站證書。

# Permanent Redirect for HTTP to HTTPS
server {
  listen 80;
  listen [::]:80;
  server_name weiyigeek.top;
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name weiyigeek.top;

  # HSTS (ngx_http_headers_module is required) 應該只使用 HTTPS 而不是使用 HTTP 通信
  add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload" always;

  # XXS-Protection
  add_header X-XSS-Protection "1; mode=block";

  # MIME 模擬探測
  add_header X-Content-Type-Options nosniff;

  # Frame 安全控制
  add_header X-Frame-Options ALLOW-FROM music.163.com;

  # Spider Robots 爬取策略限制
  add_header X-Robots-Tag none;

  # 開啓 SSL ,如果想http 與 https 公用一個配置則可以將其註釋( the "ssl" directive is deprecated )
  # ssl on;

  # 配置證書鏈與證書密鑰
  ssl_certificate      /etc/nginx/ssl/fullchain.cer;
  ssl_certificate_key  /etc/nginx/ssl/weiyigeek.top.key;

  # ssl會話複用超時時間以及會話複用緩存大小
  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions

  # 配置雙證書時開啓否則應該關閉
  ssl_session_tickets off;  

  ## OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;
  # 使用根 CA 和中間證書驗證 OCSP 響應的信任鏈
  ssl_trusted_certificate /etc/nginx/ssl/ca.cer;

  # 僅使用ECDH是不用配置ssl_dhparam的否則你應該為它配置上 
  # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
  ssl_dhparam /path/to/dhparam;

  # 兼容性較為通用的SSL協議與加密算法套件
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4;
  # 安全配置: ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
  # 證書常規握手加密算法方式共十八個,ECDHE、DHE、AES開頭分別6個
  ; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:HIGH:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!MD5:!RC4;
  
  # 為了兼容性推薦服務器自動選擇要使用的算法套件
  ssl_prefer_server_ciphers  on;

  # replace with the IP address of your resolver
  resolver 223.6.6.6 8.8.8.8 192.168.12.254;
}

補充説明: 為Nginx服務器配置RSA與ECDSA雙證書的兩種方式。

# 1.首先是將兩個證書鏈都加入 Nginx 的配置文件
ssl_certificate     example.com.rsa.crt;
ssl_certificate_key example.com.rsa.key;
ssl_certificate     example.com.ecdsa.crt;
ssl_certificate_key example.com.ecdsa.key;

# 2.或者使用 CT 的話有兩種方法,一個是將兩個證書的 CT 信息放到同一目錄,並做如下設置,Nginx CT 模塊會自動在這個目錄下查找相應證書的 CT 信息併發送驗證:
ssl_ct on;
ssl_ct_static_scts /path/to/sct/dir;

# 我們也可以單獨配置每個證書的 CT 文件
ssl_ct on;
ssl_certificate example.com.rsa.crt;
ssl_certificate_key example.com.rsa.key;
ssl_ct_static_scts xample.com.rsa.scts;
 
ssl_certificate example.com.ecdsa.crt;
ssl_certificate_key example.com.ecdsa.key;
ssl_ct_static_scts example.com.ecdsa.scts;


Nginx 之 資源壓縮配置淺析

描述: 為了降低服務器帶寬壓力以及優化響應速度, 通常我們需要在Nginx服務器配置中為其開啓gzip壓縮,

配置示例:

# 開啓gzip
gzip on;
# 啓用gzip壓縮的最小文件,小於設置值的文件將不會壓縮
gzip_min_length 2k;
# gzip 壓縮級別,1-10,數字越大壓縮的越好,也越佔用CPU時間,後面會有詳細説明
gzip_comp_level 2;
# 進行壓縮的文件類型,javascript有多種形,其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/opentype image/svg+xml;
# 建議在http header中添加Vary: Accept-Encoding支持
gzip_vary on;

<br/>

Nginx 之 靜態資源expires緩存過期時間配置

描述: 在 Nginx 配置 expires 指令可以起到控制頁面緩存的作用, 配置靜態資源的 expires 可以有效的減少客户端對服務器的請求,該配置項適用於: http、server 以及 location 塊中。

expires(過期時間語法)語法示例

; 語法: `expires [time|epoch|max|off]`
* epoch:指定Expires的值為 1 January,1970,00:00:01 GMT
* max: 指定Expires的值為31 December2037 23:59:59GMT,"Cache-Control"的值為10年。
* -1:指定Expires的值為當前服務器時間-1s,即永遠過期。
* off:不修改Expires和"Cache-Control"的值

# location 塊 ~ 使用正則匹配
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
  # 靜態資源源路徑必須配置否則,靜態資源可能無法找到
  root /var/www/img/;
  # 禁用404錯誤日誌
  log_not_found off;
  # 關閉access訪問日誌
  access_log off;
  # 靜態資源過期時間
  expires 7d;
}

該指令控制HTTP應答中的"Expires"和"Cache-Control"Header頭部信息, 例如在配置後expires指令請求 https://blog.weiyigeek.top/img/avatar.jpg URL:

HTTP/1.1 304 Not Modified
Server: nginx
Date: Fri, 01 Apr 2022 09:19:09 GMT
Last-Modified: Wed, 30 Mar 2022 15:42:30 GMT
Connection: keep-alive
ETag: "62447a66-35db"
Expires: Fri, 08 Apr 2022 09:19:09 GMT # 表示資源過期時間,由當前訪問時間加上max-age指令值所得
Cache-Control: max-age=604800          # 使用max-age指令指定組件被緩存多久,負數表示no-cache,正數或零表示max-age=time
Access-Control-Allow-Origin: *.weiyigeek.top
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization

<br/>

實踐示例:

# 網頁資源緩存
location ~* \.(xml|html|htm)$ {
  # 資源決絕對目錄設置
  root /var/www/html;
  # 日誌文件的相對路徑或完整路徑
  access_log /path/to/file.log;
  # 開啓日誌記錄
  access_log on;
  # 設置過期時間
  expires 24h;
}

# 樣式、JS、圖片資源緩存
location ~* \.(css|js|ico|gif|jpg|jpeg|png)$ {
  root /var/www/html/res;
  # 禁用404錯誤日誌
  log_not_found off;
  # 關閉日誌
  access_log off;
  # 緩存時間7天
  expires 7d;
}

# 字體資源緩存
location ~* \.(eot|ttf|otf|woff|woff2|svg)$ {
  root /var/www/html/static;
  log_not_found off;
  access_log off;
  expires max;
}

<br/>

Nginx 之 反向代理資源基本緩存配置

描述: 在 Nginx 中往往我們會對指定站點進行反代(反向代理), 而在反代站點中存在動態資源與靜態資源,我們可以使用下述指令開啓簡單的緩存配置。

首先我們需要了解一下三種緩存類型:

  • 客户端緩存
  • 代理緩存(Proxy Cache)
  • 服務端緩存

這裏主要講解Nginx作為代理服務器進行代理緩存的配置採用的參數以及示例:

  • 1.proxy_cache:定義用於緩存的共享內存區域。同一個區域可以用於多個地方

    Syntax:     proxy_cache zone | off;
    Default:     proxy_cache off;
    Context:     http, server, location
  • 2.proxy_cache_path:設置緩存的路徑和其他參數緩存數據存儲在文件中,緩存中的文件名是將MD5函數應用於緩存鍵的結果

    Context: http
    Syntax: proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    
    #例如,在下面的配置中level參數定義緩存的層次結構級別:從1到3,每個級別接受值1或2。
    proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m; #10M = 10 * 8000 個密鑰
    #/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
  • 3.proxy_cache_valid:設置緩存過期時間

    Syntax:     proxy_cache_valid [code ...] time;
    Context:     http, server, location
    
    #例如,為不同的響應代碼設置緩存時間。
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404      1m;
    
    #If only caching time is specified (指定),也可以可以指定any參數來緩存任何響應:
    proxy_cache_valid 5m;
    proxy_cache_valid any      1m;
  • 4.proxy_cache_key:設置緩存維度

    Syntax:     proxy_cache_key string;
    Default:     proxy_cache_key $scheme$proxy_host$request_uri;
    Context:     http, server, location
    
    #例如,定義用於緩存的鍵,
    proxy_cache_key "$host$request_uri $cookie_user";
    proxy_cache_key $scheme$proxy_host$uri$is_args$args; #默認情況下指令也是字符串不用加上""
  • 5.proxy_cache_purge:定義將在何種條件下將請求視為緩存清除請求。如果字符串參數中至少有一個值不為空且不等於“0”,則刪除具有相應緩存鍵的緩存項。通過返回204 (No Content)響應來指示操作成功的結果。

    Syntax:     proxy_cache_purge string ...;
    Context:     http, server, location
    
    # Example configuration: 
    map $request_method $purge_method {
      PURGE   1;
      default 0;
    }
  • 6.proxy_no_cache:指定不緩存的部分頁面,可以與proxy_cache_bypass指令一起使用。

    Syntax:     proxy_no_cache string ...;
    Context:     http, server, location
    
    #如果字符串參數中至少有一個值不為空且不等於“0”,則不會保存響應:
    proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
    proxy_no_cache $http_pragma    $http_authorization;

    <br/>

proxy_cache 相關指令集簡述
描述: 其中proxy_cache_path指令配置了緩存名稱以及其存放地址、緩存大小等相關其它參數配置, 而proxy_cache指令配置是為了啓用創建的mycache名稱的緩存。

  • proxy_no_cache : 該指令用於定義滿足條件的響應不會被保存到緩存中,在條件字符串中至少有一個條件不為空或者0,符合這樣條件的響應才不會被緩存, 其一般會配合proxy_cache_bypass共同使用;
  • proxy_cache_bypass : 該指令用於定義哪些情況不從cache讀取直接從backend獲取資源配置同上。
  • proxy_cache_key : 該指令給緩存數據定義一個鍵。
  • proxy_cache_methods :該指令用於設置緩存哪些HTTP方法,默認緩存HTTP GET/HEAD方法不緩存POST方法。
  • proxy_cache_valid :該指令用於設置不同響應碼的緩存時間。
  • proxy_cache_min_uses : 該指令用於設置緩存的最小使用次數,默認值為1
  • proxy_cache_use_stale : 該指令開啓(增強)容錯能力,即使用緩存內容來響應客户端的請求

<br/>

示例演示:

# 1.其中,cookie_nocache、arg_nocache...皆為變量,可以根據你訪問的匹配策略來設置,其值只有2類,0和非0;
# 訪問匹配策略, 如果在此鏈式配置中,只要有一個值不為 0 則不會cache。
if ($request_uri ~ ^/(login|register|password\/reset)/) { set $cookie_nocache 1; }
proxy_no_cache $cookie_nocache(0) $arg_nocache(1) $arg_comment(0)
proxy_no_cache $http_pragma $http_authorization;

# 2.默認情況下,該指令的值的字符串,給緩存數據定義一個鍵。
proxy_cache_key $scheme$proxy_host$uri$is_args$args; # 缺省
proxy_cache_key $scheme$proxy_host$request_uri;

# 4.缺省緩存GET HEAD請求。
proxy_cache_methods GET HEAD;

# 5.只對響應碼為200,301,302的訪問請求資源設置緩存時間,此外可以個性化定製。
proxy_cache_valid 200 302 10m; 
proxy_cache_valid 301 1h; 
proxy_cache_valid 404 1m; 
proxy_cache_valid any 1m;

# 6.設置緩存的最小使用次數。
proxy_cache_min_uses 1;

# 7.當作為cache的NGINX收到源站返回error、timeout或者其他指定的5XX錯誤,並且在其緩存中有請求文件的陳舊版本,則會將這些陳舊版本的文件而不是錯誤信息發送給客户端。
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;  

實踐配置: 多磁盤分割緩存,如果有多個硬盤則可以用來在多個硬盤之間分割緩存。

# 假設每塊硬盤掛載在相應的目錄中:/mnt/disk1、/mnt/disk2、/mnt/disk3, 使用了3個獨立的緩存,每個緩存專用一塊硬盤,另外,3個獨立的線程池也各自專用一塊硬盤。
proxy_cache_path /mnt/disk1 levels=1:2 keys_zone=cache_1:256m max_size=1024G use_temp_path=off;
proxy_cache_path /mnt/disk2 levels=1:2 keys_zone=cache_2:256m max_size=1024G use_temp_path=off;
proxy_cache_path /mnt/disk3 levels=1:2 keys_zone=cache_3:256m max_size=1024G use_temp_path=off;

# 緩存之間(其結果就是磁盤之間)的負載均衡使用 split_clients 模塊
split_clients $request_uri $disk {
  33.3%     1;
  33.3%     2;
  *         3;
}
location / {
  proxy_pass http://127.0.0.1:9090;
  proxy_cache_key $request_uri;
  proxy_cache cache_$disk;
}


實踐示例:

  • 示例1.

    proxy_cache_path /path/to/cache levels=1:2 keys_zone=mycache:10m max_size=10g inactive=60m use_temp_path=off;
    upstream my_upstream {
    server 192.168.1.20:8080 weight=5 max_fails=5 fail_timeout=30s;
    server 192.168.1.10:8080 weight=5 max_fails=5 fail_timeout=30s;
    }
    server {
    location / {
      proxy_cache mycache;
      proxy_pass http://my_upstream;
    }
    }
  • 示例2:

    http {
      ...
      proxy_cache_path /opt/app levels:1:2 keys_zone=weiyigeek_cache:10m max_size=10g inactive=60m use_temp_path=off; 
      map $request_method $purge_method {
        PURGE   1;
        default 0;
      }
      ...
      server {
        ...
        location / {
            proxy_cache weiyigeek_cache;
            proxy_pass http://weiyigeek;
            proxy_cache_valid 200 304 12h;
            proxy_cache_valid any 10m;
            proxy_cache_key $host$uri$is_args$args;
            proxy_cache_purge $purge_method;
            add_header Nginx-Cache "$upstream_cache_status";
            proxy_net_upstream error timeout invalid_header http_500 http_502;
            include proxy_params;
        }
        ...
      }
    }

温馨提示: 在proxy_cache_path指令中的use_temp_path=off參數,表示會將臨時文件保存在緩存數據的同一目錄中,此舉避免在更新緩存時,磁盤之間互相複製響應數據,減少磁盤IO壓力。

<br/>

補充説明:
問: 如何清理指定緩存?

> 1.rm -rf 刪除緩存目錄內容
> 2.第三方擴展模塊ngx_cache_purge


Nginx 之 黑白名單限制與請求限流

描述: 通常為了防止黑客攻擊以及惡意爬蟲爬取, 我們需要針對Nginx服務器配置黑白名單和限流措施。

黑白名單之deny 與 allow
描述: 利用 include 指令添加黑白名單配置文件,該指令可以在http, server, location, limit_except語句塊,例如:

# 白名單
include whiteip.conf;
# allow 192.168.12.0/24; # 允許IP段
# allow 127.0.0.1;       # 允許單個IP
# allow all;             # 允許所有IP

# 黑名單
include blockip.conf;
# deny 127.0.0.1; # 屏蔽單個IP
# deny all; # 屏蔽所有IP

温馨提示: 當被屏蔽的 IP 再次訪問我們的nginx服務器網頁是,將會顯示 403 頁面。

<br/>

訪問限制之併發連接與請求速率
描述: 我們可以分別利用Nginx提供的 limit_conn_zone 與 limit_req_zone 模塊來限制每個IP的連接數以及請求數。$binary_remote_addr 是限制同一客户端ip地址(節約空間), 注意不是使用$remote_addr變量;

http {
  # - limit_conn_zone:限制每個IP的併發連接數
  # 例如 blogweiyigeektop 是定義的一個會話區其用於記錄會話狀態信息。
  limit_conn_zone $binary_remote_addr zone=blogweiyigeektop:10m;
  limit_conn_zone $server_name zone=serverweiyigeektop:10m;
  limit_conn_log_level info;

  # - limit_req_zone:限制每個IP的請求數
  limit_req_zone $binary_remote_addr zone=weiyigeek_top:10m rate=1r/s;
    limit_req_zone $binary_remote_addr $uri zone=blog_weiyigeek_top:3m rate=1r/s; # $uri 表示同個ip 訪問同個uri 才會進入限制
  
  server {
    # 限連接數
    location  ^~ /download1/ {  
      limit_conn serverweiyigeektop 1000; # 表示該服務提供的總連接數最大不超過1000,超過的請求會被拒絕
      limit_conn blogweiyigeektop 4;   # 表示對blogweiyigeektop空間中的每個IP的最大併發連接數為4
      limit_rate 200k;                 # 注意此處是對連接的限速不是對IP的限速
      alias /data/www.weiyigeek.top/download1/;
    }

    # 限請求速率
    location  ^~ /download2/ {  
      # 允許超過頻率限制的請求數不多於5個,無延遲表示請求超過頻次時,可提供處理(burst + rate)個請求的能力,注意 nodelay 是要和 burst 配合使用的。
            limit_req zone=weiyigeek_top burst=5 nodelay; 
            alias /data/blog.weiyigeek.top/download2/;
    }
  }
}

<br/>

動態屏蔽惡意IP
Step 1.從logs目錄下日誌文件中安裝指定規則查找要屏蔽的IP執行如下命令awk '{print $1}' access.log |sort |uniq -c|sort -n即可,就可以統計出IP的訪問次數。

68 218.76.35.4
73 42.192.96.35
94 139.155.14.45
221 223.202.212.140
  • Step 2.自動化腳本簡單實現訪問請求次數多的IP將進行封禁,
#! /bin/bash
log_nginx="/var/log/nginx"                # nginx日誌文件
blockfile="/usr/local/nginx/conf.d"     # ip黑名單存放目錄
ip_tempfile="/tmp/nginx/ip.txt"        

# 取出日誌中符合條件的ip寫入ip.txt,並過濾掉重複的
grep "/atom.xml" $log_nginx/access.log | awk '{print $1}' | sort -rn |uniq -c |awk '{print $2}' > /tmp/nginx/ip.txt

for ip in `cat /home/shell/ip.txt`;do
  result=$(grep $ip $blockfile/blockip.conf)

  #判斷ip是否已經被屏蔽
  if [ -z "$result" ]; then
 
  #分析ip請求的次數
  count=$(grep $ip $log_nginx/access.log|grep "app/user/getCode"|wc -l)
 
  # 請求次數大於等於20次就進行屏蔽
  if [ $count -ge 20 ]; then
    echo "deny $ip;" >> $blockfile/blockip.conf
  fi
fi
done
 
#重啓nginx
/usr/local/nginx/sbin/nginx -s reload

温馨提示: 上述並不是一個非常好的方式,此種方式誤殺明顯,建議與請求限制聯合使用,於此同時我們可以利用Lua + redis實現一個動態封禁與解封(這個後續在實現)。


白名單與限制聯合使用:
描述: 如果 Nginx 前面有 lvs 或者 haproxy 之類的負載均衡或者反向代理,nginx 獲取的都是來自負載均衡的連接或請求,此時是不應該限制負載均衡的連接和請求,這就需要 geo 和 map 模塊設置白名單了;

geo $whiteiplist  {
  default 1;
  10.11.15.161 0;
}
map $whiteiplist $limit {
  1 $binary_remote_addr;
  0 "";
}
limit_req_zone $limit zone=one:10m rate=10r/s;
limit_conn_zone $limit zone=addr:10m;

原文連接: https://blog.weiyigeek.top/20...

文章書寫不易,如果您覺得這篇文章還不錯的,請給這篇專欄 【點個贊、投個幣、收個藏、關個注,轉個發】(人間五大情),這將對我的肯定,謝謝!。

本文章來源 我的Blog站點 或 WeiyiGeek 公眾賬號 以及 我的BiliBili專欄 (技術交流、友鏈交換請郵我喲),謝謝支持!(๑′ᴗ‵๑) ❤
歡迎各位志同道合的朋友一起學習交流,如文章有誤請留下您寶貴的知識建議,通過郵箱【master#weiyigeek.top】聯繫我喲!
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.