<FilesMatch> 指令:正則表達式檔案級存取控制
| 屬性 | 說明 |
| 語法 | <FilesMatch regex> ... </FilesMatch> |
| 作用域 | server config, virtual host, .htaccess |
| 狀態 | core |
| 相容性 | Apache 1.3+ |
核心功能
與 <Files> 類似,提供基於檔案名稱的存取控制,但接受 PCRE 正則表達式 作為匹配模式,支援複雜模式匹配。
經典應用範例
<FilesMatch "\.(gif|jpe?g|png)$">
# 針對圖片檔案的特殊處理
Header set Cache-Control "public, max-age=31536000"
ExpiresActive On
ExpiresDefault "access plus 1 year"
</FilesMatch>
<FilesMatch "^(?!\.well-known).+\.php$">
# 保護非 well-known 目錄下的 PHP 腳本
Require all denied
</FilesMatch>
匹配行為細節
- 針對 請求 URL 的路徑部分 (不含查詢字串) 的檔案名稱 進行匹配
- 正則預設大小寫敏感,可用
(?i) 開啟忽略大小寫:<FilesMatch "(?i)\.php$">
- 支援完整 PCRE 語法:分組、前瞻/後顧、量詞、字元類別等
與其他區塊的合併順序
請求處理時,配置區塊合併優先級 (高→低):
<Directory> (含正則 <DirectoryMatch>)
<Files> / <FilesMatch>
<Location> / <LocationMatch>
同層級按配置檔出現順序合併,後者覆蓋前者。.htaccess 在 Directory 之後、Files 之前處理。
Group 指令:設定伺服器進程執行群組
| 屬性 | 說明 |
| 語法 | Group unix-group |
| 預設值 | Group #-1 (系統預設群組) |
| 作用域 | server config, virtual host |
| 狀態 | core |
群組指定方式
| 格式 | 說明 | 範例 |
| 群組名稱 | 以名稱引用系統群組 | Group www-data |
# + GID | 以數字 ID 引用 | Group #1000 |
前置條件:必須以 root 啟動
鐵律:獨立運行的 Apache 必須以 root 身分啟動,才能在綁定埠口 (如 80/443) 後透過 setuid()/setgid() 切換到指定 User/Group。若以非 root 用戶啟動,Group 指令失效,進程將維持啟動用戶的群組身分運行。
虛擬主機中的特殊行為
- 在
<VirtualHost> 內使用 Group 需正確配置 suEXEC 包裝器
- 此模式下,僅影響 CGI 程序的執行群組;非 CGI 請求 (靜態檔案、模組處理) 仍使用主伺服器
Group 設定
安全性最佳實踐
- 建立專用群組:
groupadd www-data (或 apache、nginx),勿使用 nobody/nogroup
- 最小權限原則:該群組不擁有任何檔案寫入權限,僅具備讀取網站靜態資源、執行腳本所需的最小權限
- 隔離 CGI:搭配
suEXEC 或 PHP-FPM 以不同用戶/群組運行不同站點腳本
為何避免 nobody/nogroup?
| 風險 | 說明 |
| 權限過度共享 | 系統多個服務 (如 NFS、某些 daemon) 可能同用 nobody,導致非預期檔案可被 Web 進程存取 |
| 審計困難 | 日誌中無法區分是哪個服務進行的檔案操作 |
| 提權風險 | 若 Web 進程被攻破,攻擊者獲得 nobody 權限,可能橫向移動至其他同用 nobody 的服務 |
完整配置範例:標準生產環境 User/Group 設定
# 主伺服器設定 (httpd.conf)
User www-data
Group www-data
# 虛擬主機 1: 靜態站點 (無 CGI)
ServerName static.example.com
DocumentRoot /var/www/static
# 繼承主伺服器 User/Group
# 虛擬主機 2: PHP 站點 (使用 PHP-FPM,Apache 不執行 CGI)
ServerName app.example.com
DocumentRoot /var/www/app/public
# PHP 執行身分由 PHP-FPM 池配置決定 (user = www-app, group = www-app)
# Apache 進程仍為 www-data,僅代理請求
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/app/public/$1
# 虛擬主機 3: 傳統 CGI 站點 (需 suEXEC)
ServerName legacy.example.com
DocumentRoot /var/www/legacy
SuexecUserGroup legacy-user legacy-group
# CGI 腳本將以 legacy-user:legacy-group 執行
# 非 CGI 請求仍由 www-data:www-data 處理
驗證與排查
| 指令 | 用途 |
ps aux | grep httpd | 確認主進程 root、子進程 www-data |
id www-data | 確認 UID/GID 存在 |
sudo -u www-data ls /var/www | 測試權限是否足夠 |
apachectl -t | 配置語法檢查 |
總結
<FilesMatch>:以正則精準鎖定檔案層級行為 (快取、拒絕、壓縮),配合合併順序精確生效
Group:root 啟動前提下設定進程群組身分,專用群組 + 最小權限 + CGI 隔離 為安全基石
- 現代架構下,Apache 主進程群組固定,動態腳本執行身分下放至 PHP-FPM / suEXEC 等專用機制,實現更細緻的多租戶隔離