From 0b9651ca057971dc53f882760255dca1683e1876 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 15 May 2026 13:49:54 +0000 Subject: [PATCH] Systemd Patches + CVE Patch --- .gitea/workflows/build-publish.yml | 4 +- .../nginx-1.31.0-dynamic-tls-records.patch | 220 ++++++++++++++++++ .../patches/nginx-1.31.0-systemd-notify.patch | 70 ++++++ build/raccoon.sh | 63 +++-- build/trixie.sh | 63 +++-- static/Raccoon/nginx.service | 4 +- static/Trixie/nginx.service | 4 +- static/nginx/nginx.conf | 11 +- version | 30 ++- 9 files changed, 435 insertions(+), 34 deletions(-) create mode 100644 build/patches/nginx-1.31.0-dynamic-tls-records.patch create mode 100644 build/patches/nginx-1.31.0-systemd-notify.patch diff --git a/.gitea/workflows/build-publish.yml b/.gitea/workflows/build-publish.yml index a344b3a..7069633 100644 --- a/.gitea/workflows/build-publish.yml +++ b/.gitea/workflows/build-publish.yml @@ -72,7 +72,7 @@ jobs: cp -R /hostdata/default "${PKG_DIR}/hostdata/" || true cp -R /usr/nginx_lua "${PKG_DIR}/usr/" || true - for d in /usr/local/aws-lc /usr/local/LuaJIT /usr/local/modsecurity; do + for d in /usr/local/aws-lc /usr/local/LuaJIT /usr/local/modsecurity /usr/local/zlib-ng; do [ -d "$d" ] && cp -R "$d" "${PKG_DIR}/usr/local/" || true done mkdir -p "${PKG_DIR}/usr/local/lib" @@ -92,7 +92,7 @@ jobs: Section: base Priority: optional Architecture: ${ARCH} - Depends: libjemalloc2 + Depends: libjemalloc2, libsystemd0 Maintainer: Julio Description: Nginx L7 DDoS Protection (The-World-Is-Yours), built by RAWeb CI for ${TARGET}. EOF diff --git a/build/patches/nginx-1.31.0-dynamic-tls-records.patch b/build/patches/nginx-1.31.0-dynamic-tls-records.patch new file mode 100644 index 0000000..23b1375 --- /dev/null +++ b/build/patches/nginx-1.31.0-dynamic-tls-records.patch @@ -0,0 +1,220 @@ +diff -urN nginx-1.31.0-pristine2/src/event/ngx_event_openssl.c nginx-1.31.0-manual/src/event/ngx_event_openssl.c +--- nginx-1.31.0-pristine2/src/event/ngx_event_openssl.c 2026-05-15 13:37:51.446080719 +0000 ++++ nginx-1.31.0-manual/src/event/ngx_event_openssl.c 2026-05-15 13:38:11.254620535 +0000 +@@ -2115,6 +2115,7 @@ + + sc->buffer = ((flags & NGX_SSL_BUFFER) != 0); + sc->buffer_size = ssl->buffer_size; ++ sc->dyn_rec = ssl->dyn_rec; + + sc->session_ctx = ssl->ctx; + +@@ -3086,6 +3087,41 @@ + + for ( ;; ) { + ++ /* Dynamic record resizing: ++ We want the initial records to fit into one TCP segment ++ so we don't get TCP HoL blocking due to TCP Slow Start. ++ A connection always starts with small records, but after ++ a given amount of records sent, we make the records larger ++ to reduce header overhead. ++ After a connection has idled for a given timeout, begin ++ the process from the start. The actual parameters are ++ configurable. If dyn_rec_timeout is 0, we assume dyn_rec is off. */ ++ ++ if (c->ssl->dyn_rec.timeout > 0 ) { ++ ++ if (ngx_current_msec - c->ssl->dyn_rec_last_write > ++ c->ssl->dyn_rec.timeout) ++ { ++ buf->end = buf->start + c->ssl->dyn_rec.size_lo; ++ c->ssl->dyn_rec_records_sent = 0; ++ ++ } else { ++ if (c->ssl->dyn_rec_records_sent > ++ c->ssl->dyn_rec.threshold * 2) ++ { ++ buf->end = buf->start + c->ssl->buffer_size; ++ ++ } else if (c->ssl->dyn_rec_records_sent > ++ c->ssl->dyn_rec.threshold) ++ { ++ buf->end = buf->start + c->ssl->dyn_rec.size_hi; ++ ++ } else { ++ buf->end = buf->start + c->ssl->dyn_rec.size_lo; ++ } ++ } ++ } ++ + while (in && buf->last < buf->end && send < limit) { + if (in->buf->last_buf || in->buf->flush) { + flush = 1; +@@ -3225,6 +3261,9 @@ + + if (n > 0) { + ++ c->ssl->dyn_rec_records_sent++; ++ c->ssl->dyn_rec_last_write = ngx_current_msec; ++ + if (c->ssl->saved_read_handler) { + + c->read->handler = c->ssl->saved_read_handler; +diff -urN nginx-1.31.0-pristine2/src/event/ngx_event_openssl.h nginx-1.31.0-manual/src/event/ngx_event_openssl.h +--- nginx-1.31.0-pristine2/src/event/ngx_event_openssl.h 2026-05-15 13:37:51.446142384 +0000 ++++ nginx-1.31.0-manual/src/event/ngx_event_openssl.h 2026-05-15 13:38:11.246599371 +0000 +@@ -101,10 +101,19 @@ + typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t; + + ++typedef struct { ++ ngx_msec_t timeout; ++ ngx_uint_t threshold; ++ size_t size_lo; ++ size_t size_hi; ++} ngx_ssl_dyn_rec_t; ++ ++ + struct ngx_ssl_s { + SSL_CTX *ctx; + ngx_log_t *log; + size_t buffer_size; ++ ngx_ssl_dyn_rec_t dyn_rec; + + ngx_array_t certs; + +@@ -142,6 +151,10 @@ + unsigned no_send_shutdown:1; + unsigned shutdown_without_free:1; + unsigned handshake_buffer_set:1; ++ ++ ngx_ssl_dyn_rec_t dyn_rec; ++ ngx_msec_t dyn_rec_last_write; ++ ngx_uint_t dyn_rec_records_sent; + unsigned session_timeout_set:1; + unsigned try_early_data:1; + unsigned in_early:1; +diff -urN nginx-1.31.0-pristine2/src/http/modules/ngx_http_ssl_module.c nginx-1.31.0-manual/src/http/modules/ngx_http_ssl_module.c +--- nginx-1.31.0-pristine2/src/http/modules/ngx_http_ssl_module.c 2026-05-15 13:37:51.444851287 +0000 ++++ nginx-1.31.0-manual/src/http/modules/ngx_http_ssl_module.c 2026-05-15 13:38:11.254833775 +0000 +@@ -313,6 +313,41 @@ + offsetof(ngx_http_ssl_srv_conf_t, reject_handshake), + NULL }, + ++ { ngx_string("ssl_dyn_rec_enable"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_flag_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_enable), ++ NULL }, ++ ++ { ngx_string("ssl_dyn_rec_timeout"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_msec_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_timeout), ++ NULL }, ++ ++ { ngx_string("ssl_dyn_rec_size_lo"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_size_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_lo), ++ NULL }, ++ ++ { ngx_string("ssl_dyn_rec_size_hi"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_size_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_size_hi), ++ NULL }, ++ ++ { ngx_string("ssl_dyn_rec_threshold"), ++ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_num_slot, ++ NGX_HTTP_SRV_CONF_OFFSET, ++ offsetof(ngx_http_ssl_srv_conf_t, dyn_rec_threshold), ++ NULL }, ++ + ngx_null_command + }; + +@@ -668,6 +703,11 @@ + sscf->ocsp_cache_zone = NGX_CONF_UNSET_PTR; + sscf->stapling = NGX_CONF_UNSET; + sscf->stapling_verify = NGX_CONF_UNSET; ++ sscf->dyn_rec_enable = NGX_CONF_UNSET; ++ sscf->dyn_rec_timeout = NGX_CONF_UNSET_MSEC; ++ sscf->dyn_rec_size_lo = NGX_CONF_UNSET_SIZE; ++ sscf->dyn_rec_size_hi = NGX_CONF_UNSET_SIZE; ++ sscf->dyn_rec_threshold = NGX_CONF_UNSET_UINT; + + return sscf; + } +@@ -739,6 +779,20 @@ + ngx_conf_merge_str_value(conf->stapling_responder, + prev->stapling_responder, ""); + ++ ngx_conf_merge_value(conf->dyn_rec_enable, prev->dyn_rec_enable, 0); ++ ngx_conf_merge_msec_value(conf->dyn_rec_timeout, prev->dyn_rec_timeout, ++ 1000); ++ /* Default sizes for the dynamic record sizes are defined to fit maximal ++ TLS + IPv6 overhead in a single TCP segment for lo and 3 segments for hi: ++ 1369 = 1500 - 40 (IP) - 20 (TCP) - 10 (Time) - 61 (Max TLS overhead) */ ++ ngx_conf_merge_size_value(conf->dyn_rec_size_lo, prev->dyn_rec_size_lo, ++ 1369); ++ /* 4229 = (1500 - 40 - 20 - 10) * 3 - 61 */ ++ ngx_conf_merge_size_value(conf->dyn_rec_size_hi, prev->dyn_rec_size_hi, ++ 4229); ++ ngx_conf_merge_uint_value(conf->dyn_rec_threshold, prev->dyn_rec_threshold, ++ 40); ++ + conf->ssl.log = cf->log; + + if (conf->certificates) { +@@ -962,6 +1016,28 @@ + return NGX_CONF_ERROR; + } + ++ if (conf->dyn_rec_enable) { ++ conf->ssl.dyn_rec.timeout = conf->dyn_rec_timeout; ++ conf->ssl.dyn_rec.threshold = conf->dyn_rec_threshold; ++ ++ if (conf->buffer_size > conf->dyn_rec_size_lo) { ++ conf->ssl.dyn_rec.size_lo = conf->dyn_rec_size_lo; ++ ++ } else { ++ conf->ssl.dyn_rec.size_lo = conf->buffer_size; ++ } ++ ++ if (conf->buffer_size > conf->dyn_rec_size_hi) { ++ conf->ssl.dyn_rec.size_hi = conf->dyn_rec_size_hi; ++ ++ } else { ++ conf->ssl.dyn_rec.size_hi = conf->buffer_size; ++ } ++ ++ } else { ++ conf->ssl.dyn_rec.timeout = 0; ++ } ++ + return NGX_CONF_OK; + } + +diff -urN nginx-1.31.0-pristine2/src/http/modules/ngx_http_ssl_module.h nginx-1.31.0-manual/src/http/modules/ngx_http_ssl_module.h +--- nginx-1.31.0-pristine2/src/http/modules/ngx_http_ssl_module.h 2026-05-15 13:37:51.445106976 +0000 ++++ nginx-1.31.0-manual/src/http/modules/ngx_http_ssl_module.h 2026-05-15 13:38:11.252995002 +0000 +@@ -66,6 +66,12 @@ + ngx_flag_t stapling_verify; + ngx_str_t stapling_file; + ngx_str_t stapling_responder; ++ ++ ngx_flag_t dyn_rec_enable; ++ ngx_msec_t dyn_rec_timeout; ++ size_t dyn_rec_size_lo; ++ size_t dyn_rec_size_hi; ++ ngx_uint_t dyn_rec_threshold; + } ngx_http_ssl_srv_conf_t; + + diff --git a/build/patches/nginx-1.31.0-systemd-notify.patch b/build/patches/nginx-1.31.0-systemd-notify.patch new file mode 100644 index 0000000..46be61b --- /dev/null +++ b/build/patches/nginx-1.31.0-systemd-notify.patch @@ -0,0 +1,70 @@ +Add sd_notify() integration to nginx master process so the systemd unit can +use Type=notify. nginx mainline ships #if (NGX_HAVE_SYSTEMD) guards in nothing +of its own — every distro carries its own patch. This is ours, kept minimal. + +Send: + READY=1 after workers + cache manager are spawned (master enters loop) + READY=1 again after a successful reconfigure + RELOADING=1 when reconfigure starts + STOPPING=1 in ngx_master_process_exit + +The build script provides -DNGX_HAVE_SYSTEMD and -lsystemd, so this patch +doesn't touch auto/ configure scripts — only the source. + +--- a/src/os/unix/ngx_process_cycle.c ++++ b/src/os/unix/ngx_process_cycle.c +@@ -12,6 +12,10 @@ + #include + + ++#if (NGX_HAVE_SYSTEMD) ++#include ++#endif ++ + static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, + ngx_int_t type); + static void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, +@@ -132,6 +136,10 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) + sigio = 0; + live = 1; + ++#if (NGX_HAVE_SYSTEMD) ++ sd_notify(0, "READY=1\nSTATUS=nginx is ready\n"); ++#endif ++ + for ( ;; ) { + if (delay) { + if (ngx_sigalrm) { +@@ -211,6 +219,10 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) + if (ngx_reconfigure) { + ngx_reconfigure = 0; + ++#if (NGX_HAVE_SYSTEMD) ++ sd_notify(0, "RELOADING=1\nSTATUS=nginx is reloading\n"); ++#endif ++ + if (ngx_new_binary) { + ngx_start_worker_processes(cycle, ccf->worker_processes, + NGX_PROCESS_RESPAWN); +@@ -241,6 +253,10 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) + live = 1; + ngx_signal_worker_processes(cycle, + ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ++ ++#if (NGX_HAVE_SYSTEMD) ++ sd_notify(0, "READY=1\nSTATUS=nginx is ready\n"); ++#endif + } + + if (ngx_restart) { +@@ -655,6 +671,10 @@ static void + ngx_master_process_exit(ngx_cycle_t *cycle) + { + ngx_uint_t i; ++ ++#if (NGX_HAVE_SYSTEMD) ++ sd_notify(0, "STOPPING=1\nSTATUS=nginx is stopping\n"); ++#endif + + ngx_delete_pidfile(cycle); + diff --git a/build/raccoon.sh b/build/raccoon.sh index 30f63ae..20d5c47 100644 --- a/build/raccoon.sh +++ b/build/raccoon.sh @@ -1,5 +1,6 @@ . ./version set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" function reqs() { apt-get update -y; apt-get upgrade -y; apt-get dist-upgrade -y; apt-get autoremove -y DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata dialog @@ -7,9 +8,33 @@ function reqs() { apt-get -y install wget zip unzip build-essential libssl-dev curl nano git # apt-get -y install iptables ipset apt-get install libtool pkg-config make cmake automake autoconf golang-go ninja-build -y - apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev libzstd-dev libjemalloc2 -y + apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev libzstd-dev libjemalloc2 libsystemd-dev -y mkdir -p $LUA_SCRIPTS } +function apply_patches() { + local nginx_src="/opt/nginx-${NGINX}" + local patch_dir="${SCRIPT_DIR}/patches" + [ -f "${nginx_src}/.patches_applied" ] && return 0 + + apply_one() { + local toggle="$1" file="$2" + if [ "$toggle" != "1" ]; then + echo "[patch] skip $file (toggle=$toggle)"; return 0 + fi + if [ ! -f "${patch_dir}/${file}" ]; then + echo "[patch] MISSING ${patch_dir}/${file}"; return 1 + fi + echo "[patch] applying ${file}" + ( cd "$nginx_src" && patch -p1 < "${patch_dir}/${file}" ) + } + + apply_one "${APPLY_PATCH_SYSTEMD_NOTIFY:-0}" "nginx-${NGINX}-systemd-notify.patch" + apply_one "${APPLY_PATCH_DYNAMIC_TLS_RECORDS:-0}" "nginx-${NGINX}-dynamic-tls-records.patch" + apply_one "${APPLY_PATCH_HTTP2_HPACK_ENC:-0}" "nginx-${NGINX}-http2-hpack-enc.patch" + + touch "${nginx_src}/.patches_applied" +} + function clean_install() { mkdir -p /opt/mod @@ -18,6 +43,7 @@ function clean_install() { cd /opt/ && wget https://nginx.org/download/nginx-${NGINX}.tar.gz tar xf nginx-${NGINX}.tar.gz && rm -Rf nginx-${NGINX}.tar.gz fi + apply_patches # START OF SYSTEM REQUIRED LIBS # ============================================================================================================ @@ -40,10 +66,23 @@ function clean_install() { ldconfig fi - # ZLIB - if [ ! -d /opt/mod/zlib ]; then - cd /opt/mod && wget http://zlib.net/current/zlib.tar.gz - cd /opt/mod && tar xf zlib.tar.gz; rm -Rf zlib.tar.gz; mv zlib-* zlib + # ZLIB (zlib-ng, --zlib-compat mode). Drop-in libz replacement with SIMD- + # accelerated DEFLATE. Installed to /usr/local/zlib-ng/. nginx links via + # -I/-L below (no more --with-zlib=PATH; nginx finds libz via -L+rpath). + if [ ! -d /opt/mod/zlib-ng-${SYSTEM_ZLIBNG} ]; then + cd /opt/mod && wget https://github.com/zlib-ng/zlib-ng/archive/refs/tags/${SYSTEM_ZLIBNG}.tar.gz + cd /opt/mod && tar xf ${SYSTEM_ZLIBNG}.tar.gz; rm -Rf ${SYSTEM_ZLIBNG}.tar.gz + fi + if [ ! -f /usr/local/zlib-ng/lib/libz.so ]; then + cd /opt/mod/zlib-ng-${SYSTEM_ZLIBNG} && \ + cmake -GNinja -B build \ + -DCMAKE_INSTALL_PREFIX=/usr/local/zlib-ng \ + -DZLIB_COMPAT=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release && \ + cmake --build build -j`nproc` && \ + cmake --install build && \ + ldconfig fi # SYSTEM_LUAJIT @@ -223,14 +262,13 @@ test_nginx() { --sbin-path=/usr/sbin/nginx \ --conf-path=/nginx/nginx.conf \ --modules-path=/nginx/modules \ - --pid-path=/var/run/nginx.pid \ + --pid-path=/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-pcre \ --with-pcre-jit \ --with-pcre=/opt/mod/pcre2-${SYSTEM_PCRE} \ - --with-zlib=/opt/mod/zlib \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ @@ -271,8 +309,8 @@ test_nginx() { --add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \ --add-module=/opt/mod/testcookie \ - --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ - --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" + --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include -I/usr/local/zlib-ng/include -DNGX_HAVE_SYSTEMD" \ + --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib -L/usr/local/zlib-ng/lib -lz -Wl,-rpath,/usr/local/zlib-ng/lib -lsystemd" make clean } function build() { @@ -282,14 +320,13 @@ function build() { --sbin-path=/usr/sbin/nginx \ --conf-path=/nginx/nginx.conf \ --modules-path=/nginx/modules \ - --pid-path=/var/run/nginx.pid \ + --pid-path=/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-pcre \ --with-pcre-jit \ --with-pcre=/opt/mod/pcre2-${SYSTEM_PCRE} \ - --with-zlib=/opt/mod/zlib \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ @@ -330,8 +367,8 @@ function build() { --add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \ --add-module=/opt/mod/testcookie \ - --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ - --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" + --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include -I/usr/local/zlib-ng/include -DNGX_HAVE_SYSTEMD" \ + --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib -L/usr/local/zlib-ng/lib -lz -Wl,-rpath,/usr/local/zlib-ng/lib -lsystemd" # NOTE: kept as separate statements (not `make && make install && make clean`) # so `set -e` actually fires on a make failure. The && chain hides left-side # failures from set -e, which previously let half-built nginx ship. diff --git a/build/trixie.sh b/build/trixie.sh index d3f246d..4cac7fa 100644 --- a/build/trixie.sh +++ b/build/trixie.sh @@ -1,5 +1,6 @@ . ./version set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" function reqs() { apt-get update -y; apt-get upgrade -y; apt-get dist-upgrade -y; apt-get autoremove -y DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata dialog @@ -7,9 +8,33 @@ function reqs() { apt-get -y install wget zip unzip build-essential libssl-dev curl nano git # apt-get -y install iptables ipset apt-get install libtool pkg-config make cmake automake autoconf golang-go ninja-build -y - apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2 libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev libzstd-dev libjemalloc2 -y + apt-get install libyajl-dev ssdeep zlib1g-dev libxslt1-dev libgd-dev libgeoip-dev liblmdb-dev libfuzzy-dev libmaxminddb-dev liblua5.1-dev libcurl4-openssl-dev libxml2 libxml2-dev mercurial libpcre2-dev libc-ares-dev libre2-dev libzstd-dev libjemalloc2 libsystemd-dev -y mkdir -p $LUA_SCRIPTS } +function apply_patches() { + local nginx_src="/opt/nginx-${NGINX}" + local patch_dir="${SCRIPT_DIR}/patches" + [ -f "${nginx_src}/.patches_applied" ] && return 0 + + apply_one() { + local toggle="$1" file="$2" + if [ "$toggle" != "1" ]; then + echo "[patch] skip $file (toggle=$toggle)"; return 0 + fi + if [ ! -f "${patch_dir}/${file}" ]; then + echo "[patch] MISSING ${patch_dir}/${file}"; return 1 + fi + echo "[patch] applying ${file}" + ( cd "$nginx_src" && patch -p1 < "${patch_dir}/${file}" ) + } + + apply_one "${APPLY_PATCH_SYSTEMD_NOTIFY:-0}" "nginx-${NGINX}-systemd-notify.patch" + apply_one "${APPLY_PATCH_DYNAMIC_TLS_RECORDS:-0}" "nginx-${NGINX}-dynamic-tls-records.patch" + apply_one "${APPLY_PATCH_HTTP2_HPACK_ENC:-0}" "nginx-${NGINX}-http2-hpack-enc.patch" + + touch "${nginx_src}/.patches_applied" +} + function clean_install() { mkdir -p /opt/mod @@ -18,6 +43,7 @@ function clean_install() { cd /opt/ && wget https://nginx.org/download/nginx-${NGINX}.tar.gz tar xf nginx-${NGINX}.tar.gz && rm -Rf nginx-${NGINX}.tar.gz fi + apply_patches # START OF SYSTEM REQUIRED LIBS # ============================================================================================================ @@ -40,10 +66,23 @@ function clean_install() { ldconfig fi - # ZLIB - if [ ! -d /opt/mod/zlib ]; then - cd /opt/mod && wget http://zlib.net/current/zlib.tar.gz - cd /opt/mod && tar xf zlib.tar.gz; rm -Rf zlib.tar.gz; mv zlib-* zlib + # ZLIB (zlib-ng, --zlib-compat mode). Drop-in libz replacement with SIMD- + # accelerated DEFLATE. Installed to /usr/local/zlib-ng/. nginx links via + # -I/-L below (no more --with-zlib=PATH; nginx finds libz via -L+rpath). + if [ ! -d /opt/mod/zlib-ng-${SYSTEM_ZLIBNG} ]; then + cd /opt/mod && wget https://github.com/zlib-ng/zlib-ng/archive/refs/tags/${SYSTEM_ZLIBNG}.tar.gz + cd /opt/mod && tar xf ${SYSTEM_ZLIBNG}.tar.gz; rm -Rf ${SYSTEM_ZLIBNG}.tar.gz + fi + if [ ! -f /usr/local/zlib-ng/lib/libz.so ]; then + cd /opt/mod/zlib-ng-${SYSTEM_ZLIBNG} && \ + cmake -GNinja -B build \ + -DCMAKE_INSTALL_PREFIX=/usr/local/zlib-ng \ + -DZLIB_COMPAT=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release && \ + cmake --build build -j`nproc` && \ + cmake --install build && \ + ldconfig fi # SYSTEM_LUAJIT @@ -223,14 +262,13 @@ test_nginx() { --sbin-path=/usr/sbin/nginx \ --conf-path=/nginx/nginx.conf \ --modules-path=/nginx/modules \ - --pid-path=/var/run/nginx.pid \ + --pid-path=/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-pcre \ --with-pcre-jit \ --with-pcre=/opt/mod/pcre2-${SYSTEM_PCRE} \ - --with-zlib=/opt/mod/zlib \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ @@ -271,8 +309,8 @@ test_nginx() { --add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \ --add-module=/opt/mod/testcookie \ - --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ - --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" + --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include -I/usr/local/zlib-ng/include -DNGX_HAVE_SYSTEMD" \ + --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib -L/usr/local/zlib-ng/lib -lz -Wl,-rpath,/usr/local/zlib-ng/lib -lsystemd" make clean } function build() { @@ -282,14 +320,13 @@ function build() { --sbin-path=/usr/sbin/nginx \ --conf-path=/nginx/nginx.conf \ --modules-path=/nginx/modules \ - --pid-path=/var/run/nginx.pid \ + --pid-path=/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-pcre \ --with-pcre-jit \ --with-pcre=/opt/mod/pcre2-${SYSTEM_PCRE} \ - --with-zlib=/opt/mod/zlib \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ @@ -330,8 +367,8 @@ function build() { --add-module=/opt/mod/ngx_brotli \ --add-module=/opt/mod/zstd-nginx-module-${NGX_MOD_ZSTD} \ --add-module=/opt/mod/testcookie \ - --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include" \ - --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib" + --with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC -I/usr/local/aws-lc/include -I/usr/local/zlib-ng/include -DNGX_HAVE_SYSTEMD" \ + --with-ld-opt="-Wl,-rpath,/usr/local/LuaJIT/lib -Wl,-rpath,/usr/local/lib -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie -L/opt/mod/pcre2-${SYSTEM_PCRE}/.libs -lpcre2-8 -L/usr/local/aws-lc/lib -lssl -lcrypto -Wl,-rpath,/usr/local/aws-lc/lib -L/usr/local/zlib-ng/lib -lz -Wl,-rpath,/usr/local/zlib-ng/lib -lsystemd" # NOTE: kept as separate statements (not `make && make install && make clean`) # so `set -e` actually fires on a make failure. The && chain hides left-side # failures from set -e, which previously let half-built nginx ship. diff --git a/static/Raccoon/nginx.service b/static/Raccoon/nginx.service index 8b77a15..3546977 100644 --- a/static/Raccoon/nginx.service +++ b/static/Raccoon/nginx.service @@ -4,14 +4,14 @@ After=syslog.target network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] -Type=forking +Type=notify +NotifyAccess=main PIDFile=/run/nginx.pid Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ExecStartPre=/usr/bin/install -d -o nginx -g nginx -m 0755 /usr/local/nginx /usr/local/nginx/client_body_temp /usr/local/nginx/proxy_temp /usr/local/nginx/fastcgi_temp /usr/local/nginx/uwsgi_temp /usr/local/nginx/scgi_temp /var/log/nginx ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload -ExecStop=/bin/kill -s QUIT $MAINPID LimitNOFILE=65535 [Install] diff --git a/static/Trixie/nginx.service b/static/Trixie/nginx.service index 8b77a15..3546977 100644 --- a/static/Trixie/nginx.service +++ b/static/Trixie/nginx.service @@ -4,14 +4,14 @@ After=syslog.target network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] -Type=forking +Type=notify +NotifyAccess=main PIDFile=/run/nginx.pid Environment=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ExecStartPre=/usr/bin/install -d -o nginx -g nginx -m 0755 /usr/local/nginx /usr/local/nginx/client_body_temp /usr/local/nginx/proxy_temp /usr/local/nginx/fastcgi_temp /usr/local/nginx/uwsgi_temp /usr/local/nginx/scgi_temp /var/log/nginx ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload -ExecStop=/bin/kill -s QUIT $MAINPID LimitNOFILE=65535 [Install] diff --git a/static/nginx/nginx.conf b/static/nginx/nginx.conf index 7302e21..9951d30 100644 --- a/static/nginx/nginx.conf +++ b/static/nginx/nginx.conf @@ -1,5 +1,5 @@ user nginx; -pid /var/run/nginx.pid; +pid /run/nginx.pid; worker_processes auto; worker_cpu_affinity auto; worker_rlimit_nofile 65535; @@ -62,6 +62,15 @@ http { ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; + + # Cloudflare dynamic TLS record sizing (build/patches/nginx-X-dynamic-tls-records.patch). + # Small records up front cut TTFB by ~1 RTT, then ramp up to amortise TLS + # overhead once the connection is past head-of-line blocking. + ssl_dyn_rec_enable on; + ssl_dyn_rec_size_lo 1369; + ssl_dyn_rec_size_hi 4229; + ssl_dyn_rec_threshold 40; + ssl_dyn_rec_timeout 1000; # ===================== END TLS ======================== # resolver 1.1.1.1 1.0.0.1 valid=300s; resolver_timeout 5s; diff --git a/version b/version index 6dd66a2..8271674 100644 --- a/version +++ b/version @@ -1,4 +1,4 @@ -export NGINX="1.30.0" +export NGINX="1.31.0" # Lua Path export LUA_SCRIPTS="/usr/nginx_lua" @@ -58,3 +58,31 @@ export NGX_MOD_LUA_SRCACHE="0.33" # Zstandard compression module. Chrome 123+ and Firefox 126+ send # `Accept-Encoding: zstd`; older clients fall back to brotli/gzip. export NGX_MOD_ZSTD="0.1.1" + +# https://github.com/zlib-ng/zlib-ng/releases +# Drop-in libz replacement with SIMD-accelerated DEFLATE. Built in --zlib-compat +# mode, installed to /usr/local/zlib-ng/. ~2-3x faster gzip CPU vs stock zlib. +export SYSTEM_ZLIBNG="2.3.3" + +# --------------------------------------------------------------------------- +# Patches applied on top of upstream nginx source (committed at build/patches/). +# 1 = apply, 0 = skip. Each patch's filename embeds the nginx version it was +# authored against — bumping NGINX above means reviewing/refreshing every patch +# in build/patches/. +# --------------------------------------------------------------------------- +# Required for Type=notify in the systemd unit. Mainline nginx has the +# #if (NGX_HAVE_SYSTEMD) guards but no actual sd_notify call sites; every distro +# carries their own patch. Without this, `Type=notify` times out at startup. +export APPLY_PATCH_SYSTEMD_NOTIFY=1 + +# Cloudflare's dynamic TLS records: ssl_dyn_rec_* directives. Varies TLS record +# size based on connection state. -1 RTT TTFB on first byte, +reduced overhead +# at steady state. Patch shipped at build/patches/. +export APPLY_PATCH_DYNAMIC_TLS_RECORDS=1 + +# Cloudflare's HPACK dynamic-table encoder: --with-http_v2_hpack_enc. Smaller +# HTTP/2 response headers on the wire. Upstream patch is stale (last touched +# 2017; nginx 1.31 has already absorbed parts of it upstream and the remaining +# hunks reference internals that have drifted). Patch NOT yet shipped — would +# need a full rebase. Keep toggle here for the day someone ports it. +export APPLY_PATCH_HTTP2_HPACK_ENC=0