
安全的 Nginx 設定產生器如何運作
安全的 Nginx 設定產生器會拒絕形似設定的輸入、完全在瀏覽器中執行,並產生一個範圍明確的 HTTP 伺服器區塊,讓您在執行 nginx -t 之前可以先檢視。這份精簡的合約,正是區分「一個產生器可能悄悄放行多餘的分號或 ${變數}」與「一個產生器將每個輸入字元都視為潛在敵意輸入」的關鍵。瀏覽器無法連線到您的伺服器、無法檢查檔案擁有權,也無法讀取憑證路徑,因此這裡所謂的安全,意指限制工具可接受的內容、精確呈現它輸出的內容,並拒絕為需要部署特定證據的欄位捏造數值。Nginx 設定產生器直接遵循這份合約:document-root 欄位使用範圍明確的安全路徑字元,會拒絕分號、大括號、變數、空白字元與殼層(shell)語法;domain 欄位則只接受單一裸主機名,並拒絕帶有通訊協定的形式。輸出會監聽 IPv4 與 IPv6 的 80 埠,並使用一組精確的 server_name,且絕不會猜測萬用字元、www 或正規表示式的替代方案。HTTPS、PHP、反向代理上游、WebSocket、上傳、驗證、速率限制、自訂錯誤、MIME 包含路徑、記錄與安全標頭皆不在範圍內,因此設定表面小到可以逐行人工稽核。
這類工具的安全並非單一核取方塊,而是一連串小型、可驗證的決策。該工具將每個輸入保留在輸入時所在的分頁中,拒絕組合可能突破引號內容邊界的字元,並產生您可直接貼入檔案、從頭到尾閱讀而不會出現意外結果的輸出。它會根據固定合約驗證輸入、渲染一個範圍明確的 HTTP 伺服器區塊,並將 HTTPS、憑證路徑與模組特定行為標記為超出範圍,而不是去猜測這些值。瀏覽器無法窺見您的伺服器內部:它無法讀取檔案擁有權、DNS 記錄、憑證存放區、目前作用中的 Nginx include 鏈,或您建置版本支援哪些模組,因此安全的做法是將每個欄位視為不受信任的文字、拒絕任何看起來像指令的字串,並將部署階段的檢查——語法測試、權限、即時請求測試——留給您在主機上自行處理。這條界線既是該工具所提供的安全保證,也界定了您仍須自行確認的事項。
產生器在任何區塊建立之前就會拒絕的輸入
三個輸入欄位驅動這個區塊,每個欄位在輸出任何內容之前都會經過驗證。domain 欄位僅接受單一裸主機名。帶有通訊協定的網域名稱會被拒絕,避免產生的 server_name 被改用為路由原始元素。document root 必須是由範圍明確的安全字元所組成的絕對 POSIX 路徑。分號、大括號、帶美元符號前綴的變數、空白字元與殼層語法都會被拒絕,因為一個多餘的分號可能提早結束指令,而變數稍後可能被 Nginx 模組展開。快取持續時間是介於 1 到 365 天的單一整數,因此 expires 值不會被設定為零、無意義的年份,或解析器可能默默截斷的格式錯誤字串。
SPA fallback 選項被視為刻意的決定,而非預設行為。啟用後,未知的應用程式路徑會被導向 /index.html,以便用戶端路由接收這些請求——這對應用程式外殼(shell)來說是正確行為,但對一般內容網站則是錯誤行為。對缺失資源以狀態 200 來回傳首頁外殼,可能會掩蓋失效的 URL、扭曲分析數據,並破壞錯誤語意,因此產生器會明確呈現這個選項,而不是代為猜測。若不確定,請將 SPA fallback 保持關閉,並維持明確的 404 fallback。產生器本身合約中的負向測試固件(fixture)會拒絕帶有通訊協定的網域、具注入形態的根路徑,以及超出文件所述範圍的快取持續時間——這正是讓安全敘事可被稽核而非僅止於理想的原因。
| 安全控制項目 | 產生器如何強制執行 |
|---|---|
| 僅在本機處理 | 輸出在瀏覽器中渲染;不會將網域、路徑或快取值傳送至遠端伺服器。 |
| 輸入形態驗證 | domain、root 與快取持續時間在組合前會依固定合約進行檢查。 |
| 注入攻擊拒絕 | 路徑欄位中會拒絕分號、大括號、變數、空白字元與殼層語法。 |
| 精確的 server_name | 僅輸出一個裸主機名;不含萬用字元、不含 www 重新導向、不含正規表示式、不含推測的替代值。 |
| 範圍明確的資產快取 | expires 持續時間限制為 1-365 天,並加入 Cache-Control public。 |
| 刻意的 SPA 選擇 | SPA fallback 為選擇性啟用,並被視為刻意決定而非預設。 |
| 明確的 TLS 界線 | 憑證路徑、更新、重新導向與 HSTS 均不在範圍內,亦不會被捏造。 |
| 重新載入前先測試的指引 | 在流程中明確標示備份、nginx -t 與具代表性的請求檢查。 |
產生器會產生什麼——以及刻意省略什麼
輸出是一個 HTTP 伺服器區塊。它監聽 IPv4 與 IPv6 的 80 埠,設定精確的 server_name、絕對根目錄、index,以及一個 location /,搭配 try_files 對應所要求的 URI、目錄形式與明確的 404——或者在啟用 SPA fallback 時,對應 /index.html。第二個大小寫不敏感的 location 涵蓋一組小型、固定的副檔名清單,用於 CSS、JavaScript、常見影像格式、圖示與 WOFF2 字型。expires 指令使用所選的持續時間並加入 Cache-Control public;啟用 gzip 時,會加入標準的 filter、Vary: Accept-Encoding,以及一份有文件記載的類型清單。這些指令皆記載於 Nginx 核心與 gzip 模組中,您可以交叉對照官方參考文件:ngx_http_core_module 與 ngx_http_gzip_module。
這個區塊未包含的內容與其包含的內容同樣重要。TLS 被排除,因為正確的 HTTPS 取決於憑證路徑、更新工具、支援的通訊協定、重新導向、代理或 CDN 拓樸,以及 HSTS 政策——這些都是瀏覽器無法驗證的項目。產生器也省略 PHP、FastCGI、反向代理、WebSocket、上傳、驗證、速率限制、自訂錯誤、MIME 包含路徑、記錄與安全標頭。上述每一項都是依賴真實部署證據的設定表面,若為它們捏造數值將會產生虛假的信心。若您需要其中任何一項,請透過您的代管平台或經過審閱的伺服器程序新增,然後分別進行驗證。符合部署證據且最小、經過審閱的設定,也是最容易維護的設定。
若想更深入了解輸入如何對應到每個指令、界線又落在哪裡,範圍、輸入與限制這份逐步說明與下文所述的工作流程搭配良好。
安全地產生、檢視、備份與重新載入
可靠的流程包含五個步驟。請將第一步視為輸入衛生、第二步視為指令檢視、第三步視為回復保險,後兩步視為部署證據。
- 輸入單一精確的網域、一個絕對 document root、一個介於 1 到 365 天的快取持續時間,以及您在靜態 404 與 SPA fallback 之間所做的刻意選擇。重新確認目標主機上根路徑存在,且擁有權與讀取權限正確;瀏覽器無法確認這些。
- 產生區塊,並對照您已安裝的 Nginx 模組、實際的 document root 與快取策略,逐行閱讀每一行內容。若您發佈的是有版本或帶雜湊指紋的資產,現在正是選擇較長快取持續時間的時機;無指紋的一般內容則適合採用較短的持續時間。
- 儲存目前的 Nginx 設定,並記錄目前作用中的 include 鏈,以便在回復時不必猜測檔案來源。將審閱過的片段放置於正確的脈絡中(通常位於適當的 include site 內),而非作為獨立檔案。
- 對完整設定執行 nginx -t。成功的測試僅能證明語法與模組參照正確;並無法證明檔案權限、DNS、應用程式路由或憑證行為正確,因此請請求具代表性的路徑(包括已知資產、未知路徑、帶指紋的資產與缺失的圖片),並確認回應、標頭與狀態符合預期。
- 若平台程序支援,請採用重新載入而非突然停止服務的方式,並在過程中保持一個回復用的殼層開啟。若 nginx -t 失敗,請勿重新載入。若重新載入後請求失敗,請還原備份並檢查錯誤記錄,再嘗試第二次變更。
超越 nginx -t 的結果驗證
語法測試是必要的,但眾所周知並不充分。一個通過 nginx -t 的區塊,在正式環境仍可能出錯:若 document root 對 worker 使用者無法讀取、若精確 server_name 的 DNS 未解析到監聽埠、若資產 location 的副檔名清單漏掉您實際服務的類型,或若帶指紋的資產缺失,卻讓 fallback 路徑在應回傳 404 之處回傳 200。請將語法測試視為地板,而非天花板,並以真實請求作為天花板。
相同的謹慎態度也適用於快取。對帶指紋的 CSS、JavaScript 與 WOFF2 檔案而言,較長的 expires 值搭配 Cache-Control public 正是您想要的設定;但若未帶指紋的資產在部署後變更,這同樣的設定將會傷害使用者。請透過強制重新載入、再以停用快取的用戶端進行驗證,確認兩種方式皆能回傳正確的位元組。對 gzip 而言,請確認壓縮回應帶有 Vary: Accept-Encoding,並確認所選類型——CSS、JavaScript、JSON 與 SVG——實際上在傳輸線路上被壓縮。壓縮可能透過回應大小的差異洩漏反射型機密資訊,而預先壓縮的資產需要產生器不會輸出的獨立設定,因此請將任何壓縮決策視為需要在實際情境中量測的事項。
重新載入的紀律與設定本身同樣重要。不中斷服務的重新載入工作流程仰賴可用的備份、保持開啟的回復殼層與已知的正常 include 鏈。一次失敗的重新載入若能還原備份,只是小事;若沒有備份,則會演變成服務中斷。每當您推送產生的區塊時,請牢記這種不對稱,並抵擋因變更看似微小而略過語法測試的誘惑。
當安全產生器是錯誤的工具時
這個狹窄的合約也是一種篩選。如果您的問題是一個小型靜態來源、一台主機、一個根目錄、少數幾種資產類型,產生器會給您剛好所需的區塊,並提供最小可供審閱的表面。如果問題是託管平台面板、容器 sidecar、Kubernetes ingress、CDN 邊緣或多主機虛擬主機配置,正確的設定表面可能位於其他地方,而一個預設承諾提供 TLS、proxy 或 rate-limit 指令的產生器並不會更安全;它反而更危險,因為它捏造的值看起來合理,卻會以微妙的方式出錯。當問題真的是「這個靜態區塊中該放什麼」時,選擇產生器;當問題更大時,請改用託管平台工具或手寫的設定。