无需重启即可在NGINX Open Source中轮换SSL/TLS证书

NGINX | 2023年9月26日

在高性能Web服务器领域,NGINX凭借轻量、高效的架构,能够处理大流量负载,因此广受青睐。随着共享字典功能作为NGINX JavaScript模块(njs)的一部分推出,NGINX的性能得到进一步提升。

本文将介绍njs共享字典的功能和优势,并说明如何配置NGINX Open Source,以便在轮换SSL/TLS证书时无需重启。

共享字典的基础知识与优势

新的js_shared_dict_zone指令允许NGINX Open Source用户启用共享内存区域,以便在工作进程之间高效交换数据。这些共享内存区域充当键值字典,用于存储可实时访问和修改的动态配置设置。

共享字典的主要优势包括:

  • 开销极低且易于使用:直接内置于njs,凭借直观的API和简单的实现方式,可轻松配置和使用。它还有助于简化工作进程之间的数据管理与共享流程。
  • 轻量高效:与NGINX无缝集成,充分利用其事件驱动的非阻塞I/O模型。这种方式可减少内存占用并提升并发能力,使NGINX能够高效处理大量并发连接。
  • 可扩展性:利用NGINX跨多个工作进程横向扩展的能力,可在这些进程之间共享和同步数据,无需复杂的进程间通信机制。生存时间(TTL)设置可用于管理共享字典条目中的记录,将因不活跃而过期的记录从区域中移除。evict参数会移除最早的键值对,为新条目腾出空间。

使用共享字典轮换SSL证书

共享字典的一项重要用例是SSL/TLS轮换。使用js_shared_dict_zone时,更新SSL/TLS证书或密钥无需重启NGINX。此外,它还提供类似REST的API,用于管理NGINX上的证书。

以下NGINX配置文件示例使用js_set和ssl_certificate指令设置HTTPS服务器。JavaScript处理程序使用js_set从文件中读取SSL/TLS证书或密钥。

此配置片段使用共享字典,将证书和密钥存储在共享内存中作为缓存。如果缓存中不存在相应的键,则从磁盘读取证书或密钥并将其放入缓存。

还可以公开一个用于清除缓存的location。磁盘上的文件更新后(例如证书和密钥续期后),共享字典会强制从磁盘读取文件。这样无需重启NGINX进程即可轮换证书和密钥。

http {     ...
    js_shared_dict_zone zone=kv:1m;
   
    server {
    …
     # Sets an njs function for the variable. Returns a value of cert/key
      js_set $dynamic_ssl_cert main.js_cert;
      js_set $dynamic_ssl_key main.js_key;
   
      # use variable's data
      ssl_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 Open Source并有任何疑问,加入NGINX Community Slack,介绍一下自己,并认识这个NGINX用户社区的成员!


分享
标签: F5 NGINX, Tech

相关博客文章

NGINX Plus R26 正式发布
NGINX | 2022/02/15

NGINX Plus R26 正式发布

NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
NGINX | 2022/02/10

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击

gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
NGINX | 2021/09/13

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划

了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。

NGINX Plus R19 正式发布
NGINX | 2019/09/03

NGINX Plus R19 正式发布

NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。

NGINX现已正式加入F5
NGINX | 2019/05/09

NGINX现已正式加入F5

NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

使用NGINX和NGINX Plus实现高性能缓存
NGINX | 2016/08/24

使用NGINX和NGINX Plus实现高性能缓存

我将介绍NGINX在内容缓存和性能方面的工作原理,并分享一些控制NGINX内容缓存方式的技巧。