在收到 OpenSSL 二进制文件时通过 NGINX 对其进行解密(即时)

Decrypt OpenSSL binary through NGINX as it is received ( on the fly )

我有一个小型嵌入式 Linux 设备,它具有 128 MB 的闪存,可用作暂存器。此设备运行 NGINX 网络服务器。为了进行固件更新 - 系统通过 NGINX 将加密的二进制文件作为 HTTPS POST 接收到暂存器。然后系统解密该文件并烧写不同的 QSPI 闪存设备以完成更新。

固件二进制文件在设备外部加密如下:

openssl smime -encrypt -binary -aes-256-cbc -in plainfile.zip -out encrypted.zip.enc -outform DER yourSslCertificate.pem

固件二进制文件在通过 NGINX 接收后被解密,在设备上是这样的:

openssl smime -decrypt -binary -in encrypted.zip.enc -inform DER -out decrypted.zip -inkey private.key -passin pass:your_password

我真的很想解密通过 NGINX 收到的二进制文件(即时),以便它以解密后的形式出现在闪存暂存器上。

我无法在 Google 上找到任何现有的 NGINX 模块来执行此操作。我怎样才能做到这一点?谢谢

有一个针对 non-event-based 服务器的 widely-known 攻击,如 Apache,称为 Slowloris,客户端发起攻击许多 HTTP 请求而不发送它们(其中每个请求被部分地发送一个延长的间隔,这是一个非常便宜的操作,发送和接收,对于像 nginx 的 event-based 架构,但同时对于其他一些服务器来说非常昂贵)。

作为代理服务器,nginx 保护其后端免受此类攻击。事实上,在某些情况下,保护可能是有代价的,可以使用 …_request_buffering 指令关闭:

您要做的是禁用请求缓冲,然后 pipe the incoming file directly to openssl 收到它。

请注意,您始终可以使用 /dev/fd/0 代替文件名来指定 stdin(取决于工具,使用 - 代替文件名也可能是一种选择).

首先,你需要明白一件事。虽然 nginx 将解密文件 - 所有其他请求都将被阻止。这就是为什么nginx不支持CGI,只支持FastCGI。

如果适合您(例如,nginx 仅用于更新目的),您可以使用 perl 或 lua 扩展名:http://nginx.org/en/docs/http/ngx_http_perl_module.html, https://github.com/openresty/lua-nginx-module

使用这个模块你可以执行shell。要访问上传的文件,需要设置 client_body_in_file_only 指令 - https://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_in_file_only

perl 模块示例(未测试):

location /upload {
  client_body_in_file_only clean;
  perl 'sub {
    my $r = shift;
    if ($r->request_body_file) {
       system("openssl smime -decrypt -binary -in ".$r->request_body_file." -inform DER -out /tmp/decrypted.zip -inkey private.key -passin pass:your_password");
    }
  }';
}

但使用 fastcgi 更好。您可以为其使用 light fastcgi 包装器,例如 fcgiwrap https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/