萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Nginx 進階配置實戰:目錄密碼保護、防盜鏈、下載限速、多域名虛擬主機

Nginx 核心功能配置詳解:存取控制、資源保護與多站點部署

Nginx 憑藉高併發、低記憶體特性成為主流 Web 伺服器。本文實戰演示四大常見需求:目錄認證、防盜鏈、頻寬限制、多域名虛擬主機,並解決 PHP 應用中 $_SERVER['SERVER_NAME'] 取值異常問題。

一、目錄密碼保護(Basic Auth)

1. 建立密碼檔

# 安裝工具
yum install -y httpd-tools   # CentOS/RHEL
apt install -y apache2-utils # Debian/Ubuntu

# 建立密碼檔(-c 建立新檔,-b 批次模式指定密碼)
htpasswd -bc /usr/local/nginx/conf/htpasswd admin 'StrongP@ssw0rd'

# 新增使用者(不加 -c)
htpasswd -b /usr/local/nginx/conf/htpasswd user2 'Passw0rd'

2. Nginx 配置

server {
    listen 80;
    server_name example.com;
    root /var/www/html;

    # ⚠️ 關鍵:location 區塊順序!必須放在 PHP 處理區塊之前
    location ~ ^/admin/ {
        auth_basic "Admin Area - Authorization Required";
        auth_basic_user_file /usr/local/nginx/conf/htpasswd;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

原理:Nginx 依序匹配 location,若 PHP 區塊在前,.php 檔案會優先進入 fastcgi 處理,繞過 auth_basic。將保護區塊前置即可解決。

二、防盜鏈配置

基於 Referer 的防盜鏈

server {
    # ...
    location ~* \.(gif|png|jpg|jpeg|webp|flv|swf|mp4|pdf|zip|rar)$ {
        valid_referers none blocked *.example.com example.com ~.google. ~.bing.;
        if ($invalid_referer) {
            # 方案一:返回 403
            return 403;
            # 方案二:重導向到預設圖片
            # rewrite ^/ /images/hotlink.png last;
            # 方案三:重導向到警告頁
            # rewrite ^/ https://example.com/hotlink.html redirect;
        }
        # 可選:快取優化
        expires 30d;
        add_header Cache-Control "public";
    }
}

參數說明:

  • none:允許無 Referer(直接輸入網址、書籤)
  • blocked:允許 Referer 被防火牆/代理過滤的請求
  • *.example.com:允許的域名(支援萬用字元)
  • ~.google.:正則匹配允許搜尋引擎抓取

進階:基於簽名 URL 的防盜鏈(ngx_http_secure_link_module)

# 生成簽名腳本(Python 範例)
# import hmac, hashlib, base64, time
# secret = b'my_secret_key'
# expire = int(time.time()) + 3600  # 1 小時有效
# path = '/protected/video.mp4'
# sig = base64.urlsafe_b64encode(hmac.new(secret, f'{path}{expire}'.encode(), hashlib.md5).digest()).decode().rstrip('=')
# url = f'https://example.com{path}?md5={sig}&expires={expire}'

location /protected/ {
    secure_link $arg_md5,$arg_expires;
    secure_link_md5 "my_secret_key$secure_link_expires$uri";
    if ($secure_link = "") { return 403; }
    if ($secure_link = "0") { return 410; } # 過期
    # 通過驗證,提供檔案
}

三、下載限速與連線數限制

1. 限制連線數(limit_conn)

http {
    # 定義共享記憶體區域:key 為客戶端 IP,大小 10MB 可儲存約 16 萬狀態
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    # 或以 server_name 為 key 限制單站總連線
    limit_conn_zone $server_name zone=perserver:10m;
}

server {
    # 限制單 IP 單站並發連線數
    location /download/ {
        limit_conn perip 5;
        limit_conn perserver 1000;
    }
}

2. 限制下載速度(limit_rate)

location ~* \.(zip|rar|gz|tar|exe|mp4|mkv|iso)$ {
    limit_conn perip 2;        # 單 IP 最多 2 條下載連線
    limit_rate 512k;           # 每連線限速 512 KB/s
    limit_rate_after 1m;       # 前 1MB 不限速,之後限速(體驗優化)
}

進階:動態限速 根據使用者等級或時間段調整:

map $cookie_user_level $download_limit {
    default    512k;
    vip        2m;
    premium    0;   # 0 = 不限速
}

location /download/ {
    limit_rate $download_limit;
}

四、多域名虛擬主機與 SERVER_NAME 陷阱

問題現象

配置泛域名時:

server_name *.example.com example.com;

PHP 中 $_SERVER['SERVER_NAME'] 永遠返回第一個域名(*.example.com),導致多站點識別失效。

根本原因

FastCGI 參數預設傳遞 $server_name(Nginx 變數,取 server_name 第一項),而非實際請求的 Host 標頭。

解決方案

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    # 關鍵修正:使用 $host(請求 Host 標頭)而非 $server_name
    fastcgi_param SERVER_NAME $host;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

# 同時建議關閉重導向時使用 server_name 第一項
server_name_in_redirect off;

完整多站點配置範例

# 主站
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/main;
    # ...
}

# 子站 A(獨立配置檔 /etc/nginx/conf.d/site-a.conf)
server {
    listen 80;
    server_name a.example.com;
    root /var/www/site-a;
    # ...
}

# 泛域名站點(動態站點,如 SaaS 多租戶)
server {
    listen 80;
    server_name ~^(?.+)\.saas\.example\.com$;
    root /var/www/saas;
    # PHP 中可用 $subdomain 變數識別租戶
    # fastcgi_param TENANT $subdomain;
}

五、配置測試與熱重載

# 語法檢查
nginx -t

# 平滑重載(不中斷現有連線)
nginx -s reload
# 或
systemctl reload nginx

六、安全性加固建議

  • 隱藏版本號:server_tokens off;
  • 啟用 HTTPS:配置 SSL 憑證、HSTS、OCSP Stapling
  • 安全標頭:add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff;
  • 限制請求大小:client_max_body_size 10m;
  • 防暴力破解:結合 limit_req_zone 限制登入 API 頻率
copyright © 萬盛學電腦網 all rights reserved