I noticed that stunnel is constantly consuming 30% of one of my CPU cores. Looking at it with strace, I see that it is frequently (every 100 milliseconds?) waking up from a poll() system call, calling getpid() a couple of times and going back to sleep. [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 AFAICT, this is a pipe that stunnel is using to talk to itself (maybe to communicate between threads)? # ls -l /proc/3498/fd total 0 lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 0 -> /dev/null lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 1 -> /dev/null lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 10 -> 'socket:[37674]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 11 -> 'socket:[37675]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 12 -> 'socket:[37676]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 2 -> /dev/null lr-x------. 1 stunnel stunnel 64 Aug 23 10:12 4 -> 'pipe:[38360]' l-wx------. 1 stunnel stunnel 64 Aug 23 10:12 5 -> 'pipe:[38360]' lr-x------. 1 stunnel stunnel 64 Aug 23 10:12 6 -> 'pipe:[38361]' l-wx------. 1 stunnel stunnel 64 Aug 23 10:12 7 -> 'pipe:[38361]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 8 -> 'socket:[37672]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 9 -> 'socket:[37673]' Is this expected behavior? Anything that can be done about it? Environment: ============ stunnel 5.80 on x86_64-redhat-linux-gnu platform Compiled/running with OpenSSL 3.5.7 9 Jun 2026 Threading:PTHREAD Sockets:POLL,IPv6,SYSTEMD TLS:ENGINE,FIPS,OCSP,PSK,SNI,DTLS Global options: fips = no RNDbytes = 1024 RNDfile = /dev/urandom RNDoverwrite = yes Service-level options: ciphers = PROFILE=SYSTEM (with "fips = yes") ciphers = PROFILE=SYSTEM (with "fips = no") ciphersuites = TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 (with TLSv1.3) curves = P-256:P-521:P-384 (with "fips = yes") curves = X25519MLKEM768:X25519:P-256:X448:P-521:P-384 (with "fips = no") debug = daemon.notice logId = sequential options = NO_SSLv2 options = NO_SSLv3 securityLevel = 2 sessionCacheSize = 1000 sessionCacheTimeout = 300 seconds stack = 131072 bytes TIMEOUTbusy = 300 seconds TIMEOUTclose = 60 seconds TIMEOUTconnect = 10 seconds TIMEOUTidle = 43200 seconds TIMEOUTocsp = 5 seconds verify = none stunnel.conf: ============= debug = warning [switch2-frontend] accept = 0.0.0.0:8402 CAfile = /etc/ipa/ca.crt cert = /etc/pki/tls/certs/stunnel/switch2.crt key = /tmp/keys/switch2.key connect = 127.255.255.254:8082 [switch2-backend] client = yes accept = 127.255.255.254:8082 connect = 172.31.4.2:443 verifyChain = yes checkHost = switch2.penurio.us CAfile = /etc/pki/tls/certs/stunnel/switch-ca.crt sslVersion = TLSv1 ciphers = DHE-RSA-AES256-SHA options = ALLOW_UNSAFE_LEGACY_RENEGOTIATION securityLevel = 0 OCSPrequire = no OCSPaia = no [switch4-frontend] accept = 0.0.0.0:8404 CAfile = /etc/ipa/ca.crt cert = /etc/pki/tls/certs/stunnel/switch4.crt key = /tmp/keys/switch4.key connect = 127.255.255.254:8084 [switch4-backend] client = yes accept = 127.255.255.254:8084 connect = 172.31.4.7:443 verifyChain = yes checkHost = switch4.penurio.us CAfile = /etc/pki/tls/certs/stunnel/switch-ca.crt sslVersion = TLSv1 ciphers = DHE-RSA-AES256-SHA options = ALLOW_UNSAFE_LEGACY_RENEGOTIATION securityLevel = 0 OCSPrequire = no OCSPaia = no -- ======================================================================== If your user interface is intuitive in retrospect ... it isn't intuitive ========================================================================
Hi Ian, A few years ago, the Red Hat/Fedora stunnel packaging was changed to use the system-wide crypto policy as the default cipher configuration: https://gitlab.com/redhat/centos-stream/rpms/stunnel/-/blob/c10s/stunnel-5.6... This third-party patch changes stunnel's default cipher list to PROFILE=SYSTEM. Since the system crypto policy enables finite-field DHE cipher suites, stunnel's existing code detects that DHE is available in your server-mode frontend sections and generates temporary 2048-bit DH parameters. The parameters are generated when the per-day worker starts and regenerated every 24 hours. The 100 ms poll() calls you are seeing come from a delay in stunnel's OpenSSL DH-generation progress callback. The delay is there to throttle CPU usage during DH parameter generation. Your explicit DHE-RSA-AES256-SHA settings in the backend sections are unrelated to this CPU usage, since those sections run in client mode and therefore do not generate DH parameters locally. Finite-field DHE cipher suites are generally not recommended for new TLS configurations in 2026. ECDHE, or TLS 1.3 key exchange, should normally be preferred. Your backend configuration appears to require DHE for compatibility with the legacy switches, but unless you also need DHE on the frontend connections, I would disable it there. Best regards, Mike On 8/23/26 17:25, Ian Pilcher via stunnel-users wrote:
I noticed that stunnel is constantly consuming 30% of one of my CPU cores. Looking at it with strace, I see that it is frequently (every 100 milliseconds?) waking up from a poll() system call, calling getpid() a couple of times and going back to sleep.
[pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494 [pid 3498] poll([{fd=6, events=POLLIN|POLLRDHUP}], 1, 100) = 0 (Timeout) [pid 3498] getpid() = 3494 [pid 3498] getpid() = 3494
AFAICT, this is a pipe that stunnel is using to talk to itself (maybe to communicate between threads)?
# ls -l /proc/3498/fd total 0 lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 0 -> /dev/null lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 1 -> /dev/null lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 10 -> 'socket:[37674]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 11 -> 'socket:[37675]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 12 -> 'socket:[37676]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 2 -> /dev/null lr-x------. 1 stunnel stunnel 64 Aug 23 10:12 4 -> 'pipe:[38360]' l-wx------. 1 stunnel stunnel 64 Aug 23 10:12 5 -> 'pipe:[38360]' lr-x------. 1 stunnel stunnel 64 Aug 23 10:12 6 -> 'pipe:[38361]' l-wx------. 1 stunnel stunnel 64 Aug 23 10:12 7 -> 'pipe:[38361]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 8 -> 'socket:[37672]' lrwx------. 1 stunnel stunnel 64 Aug 23 10:12 9 -> 'socket:[37673]'
Is this expected behavior? Anything that can be done about it?
Environment: ============
stunnel 5.80 on x86_64-redhat-linux-gnu platform Compiled/running with OpenSSL 3.5.7 9 Jun 2026 Threading:PTHREAD Sockets:POLL,IPv6,SYSTEMD TLS:ENGINE,FIPS,OCSP,PSK,SNI,DTLS
Global options: fips = no RNDbytes = 1024 RNDfile = /dev/urandom RNDoverwrite = yes
Service-level options: ciphers = PROFILE=SYSTEM (with "fips = yes") ciphers = PROFILE=SYSTEM (with "fips = no") ciphersuites = TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256 (with TLSv1.3) curves = P-256:P-521:P-384 (with "fips = yes") curves = X25519MLKEM768:X25519:P-256:X448:P-521:P-384 (with "fips = no") debug = daemon.notice logId = sequential options = NO_SSLv2 options = NO_SSLv3 securityLevel = 2 sessionCacheSize = 1000 sessionCacheTimeout = 300 seconds stack = 131072 bytes TIMEOUTbusy = 300 seconds TIMEOUTclose = 60 seconds TIMEOUTconnect = 10 seconds TIMEOUTidle = 43200 seconds TIMEOUTocsp = 5 seconds verify = none
stunnel.conf: =============
debug = warning
[switch2-frontend] accept = 0.0.0.0:8402 CAfile = /etc/ipa/ca.crt cert = /etc/pki/tls/certs/stunnel/switch2.crt key = /tmp/keys/switch2.key connect = 127.255.255.254:8082
[switch2-backend] client = yes accept = 127.255.255.254:8082 connect = 172.31.4.2:443 verifyChain = yes checkHost = switch2.penurio.us CAfile = /etc/pki/tls/certs/stunnel/switch-ca.crt sslVersion = TLSv1 ciphers = DHE-RSA-AES256-SHA options = ALLOW_UNSAFE_LEGACY_RENEGOTIATION securityLevel = 0 OCSPrequire = no OCSPaia = no
[switch4-frontend] accept = 0.0.0.0:8404 CAfile = /etc/ipa/ca.crt cert = /etc/pki/tls/certs/stunnel/switch4.crt key = /tmp/keys/switch4.key connect = 127.255.255.254:8084
[switch4-backend] client = yes accept = 127.255.255.254:8084 connect = 172.31.4.7:443 verifyChain = yes checkHost = switch4.penurio.us CAfile = /etc/pki/tls/certs/stunnel/switch-ca.crt sslVersion = TLSv1 ciphers = DHE-RSA-AES256-SHA options = ALLOW_UNSAFE_LEGACY_RENEGOTIATION securityLevel = 0 OCSPrequire = no OCSPaia = no
Hi Ian, hi Mike,
On 24. Aug 2026, at 13:49, Michał Trojnara <[email protected]> wrote:
A few years ago, the Red Hat/Fedora stunnel packaging was changed to use the system-wide crypto policy as the default cipher configuration:
https://gitlab.com/redhat/centos-stream/rpms/stunnel/-/blob/c10s/stunnel-5.6...
This third-party patch changes stunnel's default cipher list to PROFILE=SYSTEM. Since the system crypto policy enables finite-field DHE cipher suites, stunnel's existing code detects that DHE is available in your server-mode frontend sections and generates temporary 2048-bit DH parameters.
Thanks for bringing that to my attention. This is indeed unfortunate, since we enable FFDHE system-wide in the assumption that implementations use RFC 7919 (i.e., the well-known FFDHE parameters from its Appendix A) rather than generating new parameters at runtime. We can’t disable FFDHE now in existing releases, because it would break compatibility. I brought this up with my team, and we agree that we’ll probably drop FFDHE from the DEFAULT policy in RHEL 11 completely.
The parameters are generated when the per-day worker starts and regenerated every 24 hours. The 100 ms poll() calls you are seeing come from a delay in stunnel's OpenSSL DH-generation progress callback. The delay is there to throttle CPU usage during DH parameter generation.
For now, if you want to keep FFDHE enabled and/or not opt-out of crypto-policies with your stunnel config, I’d recommend following this instruction from the stunnel manpage:
Alternatively, it is possible to specify static DH parameters in the certificate file, which disables generating temporary DH parameters:
openssl dhparam 2048 >> stunnel.pem
Instead of generating a new set of parameters using `openssl dhparam`, I would recommend grabbing a PEM-encoded copy of the RFC 7919 ones from https://github.com/internetstandards/dhe_groups/tree/26f703fe44e0b4b03840e3d... These also have the advantage that they’ll definitely work in FIPS mode, which is not a given for locally generated groups. I’ll look into maybe replacing the generation with the static RFC 7919 groups instead downstream, but no promises on that one. Could you share which RHEL version you’re using? It looks like 9 or 10 based on the OpenSSL version, but both ship the same, so it’s impossible to tell from your provided output. Clemens -- Clemens Lang RHEL Crypto Team Red Hat
On 8/26/26 2:24 PM, Clemens Lang via stunnel-users wrote:
For now, if you want to keep FFDHE enabled and/or not opt-out of crypto-policies with your stunnel config, I’d recommend following this instruction from the stunnel manpage:
Alternatively, it is possible to specify static DH parameters in the certificate file, which disables generating temporary DH parameters:
openssl dhparam 2048 >> stunnel.pem
Instead of generating a new set of parameters using `openssl dhparam`, I would recommend grabbing a PEM-encoded copy of the RFC 7919 ones from
https://github.com/internetstandards/dhe_groups/ tree/26f703fe44e0b4b03840e3dc7eaacf8257f7a184
Thanks Clemens! (Sorry about the slow response.)
Could you share which RHEL version you’re using? It looks like 9 or 10 based on the OpenSSL version, but both ship the same, so it’s impossible to tell from your provided output.
I'm on Fedora 44. openssl-3.5.7-2.fc44.x86_64 stunnel-5.80-1.fc44.x86_64 -- ======================================================================== If your user interface is intuitive in retrospect ... it isn't intuitive ========================================================================
participants (3)
-
Clemens Lang -
Ian Pilcher -
Michał Trojnara