libnginx-mod-http-fd-pass is a custom NGINX module that passes on incoming client connections to another process using an extended SimpleCGI (SCGI) protocol.
Uniquely, it sends the actual client file descriptor (FD) via an SCM_RIGHTS ancillary message along with the initial HTTP request headers.
- Receive Request: Nginx accepts a new client connection (HTTP or HTTPS with Kernel TLS offload).
- Collect Headers: Once all initial request headers have arrived from the client, the module gathers these headers.
- SCGI Forward:
- The module forwards the request headers to a backend process over a UNIX domain socket, adhering to the SCGI protocol.
- Simultaneously, the client’s file descriptor is passed via an
SCM_RIGHTSancillary message.
- Connection Handoff:
- For HTTP connections, or for HTTPS connections using kTLS offload (both receive and send), nginx is finished with the connection after handing it off. The backend process owns the client connection FD going forward.
This setup effectively lets you implement advanced workflows in your SCGI-based backend (such as specialized I/O handling, zero-copy operations, or custom protocols) while using NGINX as the initial request router.
- SCGI Integration: Uses the SCGI protocol to transmit request headers to another process.
- FD Handoff via
SCM_RIGHTS: Passes the client’s file descriptor to the backend, enabling direct control of the connection. - Minimal Overhead: Once NGINX hands off the connection, it no longer processes subsequent data for the request (if HTTP or kTLS offload is used in both directions).
- Simple Directives:
fd_passcan be configured on specific locations, making it easy to enable or disable per context.
- SCGI-only: This module uses SCGI; it does not support FastCGI, environment variables, or other CGI interfaces.
- Advanced Use Cases: Handing off the FD is powerful but also complex; ensure your SCGI backend can handle raw socket I/O.
- TLS Support: For TLS connections, the module works best with kTLS enabled for both receiving and sending. Otherwise, nginx must continue handling SSL/TLS on the connection.
Note
Specifically for OpenSSL version 3.0 and 3.1, only sending is possible to offload for TLSv1.3 clients. For these clients, Nginx retains ownership of receiving and decrypting data from the client in user space, and forwards the decrypted data to the backend over UNIX socket. Still, the backend process will have ownership over sending data to the client since encryption uses Kernel TLS offload.
| OpenSSL version | kTLS offloads for TLSv1.2 | kTLS offloads for TLSv1.3 |
|---|---|---|
| 3.0, 3.1 | Encrypt and decrypt (full handover) | Encrypt only (partial socket handover from nginx) |
| 3.2 and later | Encrypt and decrypt (full handover) | Encrypt and decrypt (full handover) |
Install a dpkg package from the Releases page or build it from source as outlined below.
Building a module on Debian/Ubuntu:
- Clone the repository:
git clone https://github.com/knneth/libnginx-mod-http-fd-pass.git cd libnginx-mod-http-fd-pass - Build the package:
dpkg-buildpackage --build=binary --unsigned-changes --unsigned-buildinfo - Install the package (change the version number as necessary):
sudo apt install ../libnginx-mod-http-fd-pass_1.0.0-0_amd64.deb
Alternatively, it can be compiled into the nginx server (embedded applications):
- Clone the repository:
git clone https://github.com/knneth/libnginx-mod-http-fd-pass - Obtain and extract nginx source code (matching your desired NGINX version)
curl -OLR https://nginx.org/download/nginx-x.x.x.tar.gz tar xvzf nginx-x.x.x.tar.gz cd nginx-x.x.x - Configure nginx with this module:
./configure --add-module=../libnginx-mod-http-fd-pass --with-http_ssl_module [other-options] make -j
To enable the module, add the fd_pass directive in the appropriate location block in your site configuration. For example:
location = /fd_pass_test {
fd_pass unix:/run/fd_pass_test.sock;
}Your SCGI backend must:
- Receive the netstring-encoded SCGI headers from the UNIX domain socket.
- Extract the client FD from the received ancillary data (
SCM_RIGHTS). - Interact directly with the client socket. For HTTP, TLSv1.2, or when the SCGI header
KTLS_RX=0is absent, you can continue reading or writing data to this FD as needed.- Only encryption is offloaded to kTLS when the SCGI header
KTLS_RX=0is present. You can continue receiving data over the UNIX socket connection, but writing data must use the client FD. Upgrade to OpenSSL 3.2 or later to support full connection handover for TLSv1.3 clients.
- Only encryption is offloaded to kTLS when the SCGI header
We welcome contributions that enhance functionality, improve performance, or fix bugs.
This project is licensed under the BSD 2-Clause "Simplified" License.
The upstream NGINX project could introduce FD passing in their ngx_http_scgi_module module.