?原文作者:Maxim Ivanitskiy of F5
原文鏈接:無需重啟 NGINX 開源版即可實現 SSL/TLS 證書輪換
轉載來源:NGINX 開源社區
NGINX 唯一中文官方社區 ,盡在?nginx.org.cn
在高性能 Web 服務器領域,NGINX?是一個廣受歡迎的選擇,因為其輕便高效的架構支持它處理大量流量。通過在?NGINX JavaScript 模塊(njs)中引入共享字典(shared dictionary)功能,NGINX 的性能更上一層樓。
在本文中,我們將探討 njs 共享字典的功能和優勢,并展示如何設置 NGINX 開源版,以無需重啟即可輪換 SSL/TLS 證書。
共享字典簡介及其優勢
新?js_shared_dict_zone?指令允許 NGINX 開源版用戶啟用共享內存區,在 worker 進程之間高效交換數據。 這些共享內存區充當鍵值字典,存儲著可實時訪問和修改的動態配置設置。
共享字典的主要優勢包括:
-
開銷極少且易于使用 –?直接內置在 njs 中,得益于直觀的 API 和簡單的實現,可輕松配置和使用。它還能夠幫助您簡化 worker 進程之間的數據管理和共享。
-
輕量高效 –?與 NGINX 無縫集成,利用其事件驅動型非阻塞 I/O 模型。這種方法減少了內存占用,并提高了并發處理能力,支持 NGINX 高效處理大量并發連接。
-
可擴展性 –?借助 NGINX 跨多個 worker 進程的橫向擴展能力,您可以在這些進程之間共享和同步數據,而無需復雜的進程間通信機制。通過 time-to-live (TTL) 設置,您可以管理共享字典條目中的記錄,將不活動的條目從區域中刪除。evict?參數會刪除最早的鍵值對,為新條目騰出空間。
使用共享字典進行 SSL 輪換
共享字典最有效的用例之一是 SSL/TLS 輪換。使用?js_shared_dict_zone?
時,無需重啟 NGINX 就可更新 SSL/TLS 證書或密鑰。此外,它還提供了一個類似 REST 的 API,可用于管理 NGINX 上的證書。
下面是一個 NGINX 配置文件示例,該配置文件使用?js_set?和?ssl_certificate?指令來設置 HTTPS 服務器。 JavaScript 處理程序使用?js_set?
從文件中讀取 SSL/TLS 證書或密鑰。
此配置片段使用共享字典將證書和密鑰作為緩存存儲在共享內存中。如果沒有密鑰,則會從磁盤中讀取證書或密鑰,并將其放入緩存。
您還可以暴露一個位置,以便手動清除緩存。一旦磁盤上的文件更新(如證書和密鑰更新),共享字典就會從磁盤中讀取這些更新。該調整允許在不重啟 NGINX 進程的情況下輪換證書/密鑰。
http {...js_shared_dict_zone zone=kv:1m;server {…# Sets an njs function for the variable. Returns a value of cert/keyjs_set $dynamic_ssl_cert main.js_cert;js_set $dynamic_ssl_key main.js_key;# use variable's datassl_certificate data:$dynamic_ssl_cert;ssl_certificate_key data:$dynamic_ssl_key;# a location to clear cache location = /clear {js_content main.clear_cache;# allow 127.0.0.1;# deny all;}...}
下面是使用?js_shared_dict_zone?
輪換 SSL/TLS 證書和密鑰的 JavaScript 實現:
function js_cert(r) {if (r.variables['ssl_server_name']) {return read_cert_or_key(r, '.cert.pem');} else {return '';}
}function js_key(r) {if (r.variables['ssl_server_name']) {return read_cert_or_key(r, '.key.pem');} else {return '';}
}
/** * Retrieves the key/cert value from Shared memory or fallback to disk*/function read_cert_or_key(r, fileExtension) {let data = '';let path = '';const zone = 'kv';let certName = r.variables.ssl_server_name;let prefix = '/etc/nginx/certs/';path = prefix + certName + fileExtension;r.log('Resolving ${path}');const key = ['certs', path].join(':');const cache = zone && ngx.shared && ngx.shared[zone];if (cache) {data = cache.get(key) || '';if (data) {r.log(`Read ${key} from cache`);return data;}}try {data = fs.readFileSync(path, 'utf8');r.log('Read from cache');} catch (e) {data = '';r.log(`Error reading from file:${path}. Error=${e}`);}if (cache && data) {try {cache.set(key, data);r.log('Persisted in cache');} catch (e) {const errMsg = `Error writing to shared dict zone: ${zone}. Error=${e}`;r.log(errMsg);}}return data
}
可通過發送?/clear?
請求讓緩存失效,這樣 NGINX 在下一次 SSL/TLS 握手時就會從磁盤加載 SSL/TLS 證書或密鑰。此外,您還可以使用?js_content?
從請求中獲取 SSL/TLS 證書或密鑰,同時持久化和更新緩存。
本例的完整代碼可在?njs GitHub 代碼庫中找到。
立即開始
共享字典功能是一款強大的應用可編程性工具,在簡化和可擴展性方面具有顯著優勢。利用?js_shared_dict_zone?
的功能,您可以發掘新的增長機遇,并高效處理不斷增長的流量需求。
準備好使用?js_shared_dict_zone?
來加速 NGINX 部署了嗎?您可以使用?js_shared_dict_zone?
升級 NGINX 部署,解鎖新的用例。有關此功能的更多信息,請參閱我們的文檔。此外,您還可以在最近推出的?njs-acme 項目(支持 njs 模塊運行時與 ACME 提供程序協同工作)中看到共享字典功能的完整示例。
如果您對 NGINX 開源版感興趣或有任何問題,歡迎微信添加小 N 助手(微信號:nginxoss)加入 NGINX 官方微信群,以了解更多信息、提出問題并獲得有關 NGINX 開源版的反饋。
NGINX 唯一中文官方社區 ,盡在?nginx.org.cn
更多 NGINX 相關的技術干貨、互動問答、系列課程、活動資源:?開源社區官網?|?微信公眾號