Skip to content

sing-box drops TLS connection when OpenSSL sends ClientHello with padding extension #4141

@wintertee

Description

@wintertee

Summary

After upgrading from Fedora 42 to Fedora 44, all HTTPS connections through sing-box fail with:

curl: (35) TLS connect error: error:0A000126:SSL routines::unexpected eof while reading

sing-box closes the connection immediately after receiving the TLS ClientHello.

Environment

The sing-box runs on windows with a Trojan outbound. Wsl2 apps are connected to sing-box with HTTP_PROXY env var.

Component Version
sing-box 1.13.6
OS Fedora Linux 44 (WSL)
OpenSSL 3.5.5 (openssl-libs-3.5.5-2.fc44.x86_64)
crypto-policies 20251128-3.git19878fe.fc44
curl 8.18.0

Steps to Reproduce

  1. Run Fedora 44 with DEFAULT crypto policy (the default after a fresh install or upgrade from Fedora 42)
  2. Configure sing-box as an HTTP proxy (e.g., listening on 172.22.64.1:7897)
  3. Make an HTTPS request through the proxy:
curl --tlsv1.2 -x http://172.22.64.1:7897 https://google.com

Result: curl: (35) TLS connect error: error:0A000126:SSL routines::unexpected eof while reading

Workarounds

All of the following work around the issue:

# 1. Force TLS max to 1.2 (no padding extension generated)
curl --tlsv1.2 --tls-max 1.2 -x http://172.22.64.1:7897 https://google.com

# 2. Force TLS 1.3 only
curl --tlsv1.3 -x http://172.22.64.1:7897 https://google.com

# 3. Use classic ECDH curves only (suppresses ML-KEM groups, shrinks ClientHello below padding threshold)
curl --tlsv1.2 -x http://172.22.64.1:7897 --curves X25519 https://google.com

# 4. Downgrade system crypto policy to disable post-quantum cryptography
sudo update-crypto-policies --set DEFAULT:NO-PQ

The analysis below was performed by Claude Code. It investigated the system configurations and captured packets. I hope this helps.

Root Cause Analysis

The root cause is that Fedora 44's DEFAULT crypto policy (OpenSSL 3.5.5) causes OpenSSL to send an oversized ClientHello containing a TLS padding extension (type 0x0015), which sing-box appears to reject.

Fedora 44 updated crypto-policies to include post-quantum hybrid key exchange groups (ML-KEM) in the DEFAULT policy:

# /etc/crypto-policies/back-ends/opensslcnf.config
Groups = *?X25519MLKEM768:?x25519_mlkem768:?SecP256r1MLKEM768:.../*X25519:secp256r1:...

The * prefix instructs OpenSSL 3.5 to send ML-KEM key shares in the ClientHello key_share extension. This inflates the ClientHello size significantly. When the ClientHello exceeds 512 bytes, OpenSSL automatically appends a padding extension (type 0x0015) to avoid known compatibility issues with certain middleboxes (per RFC 7685).

Packet capture confirms the difference between the two cases:

Failing ClientHello (--tlsv1.2, 517 bytes after CONNECT tunnel):

  • supported_versions: TLS 1.3 + 1.2 advertised
  • key_share: X25519 only (32 bytes) — ML-KEM groups listed in supported_groups but OpenSSL chose X25519 for the actual share
  • padding extension (type 0x0015): 214 bytes of zeros ← sing-box closes connection here

Working ClientHello (--tlsv1.2 --tls-max 1.2, 224 bytes after CONNECT tunnel):

  • supported_versions: TLS 1.2 only
  • No key_share extension (TLS 1.2 uses ClientKeyExchange instead)
  • No padding extension

The padding extension is entirely valid per RFC 7685 and RFC 8446. sing-box should handle it gracefully rather than dropping the connection.

Expected Behavior

sing-box should accept a TLS ClientHello containing the padding extension (0x0015) and forward the TLS handshake to the upstream server as normal.

Additional Notes

This regression was introduced between Fedora 42 and Fedora 44. Fedora 42's DEFAULT policy did not include ML-KEM groups, so ClientHellos were smaller and the padding extension was never triggered. The same proxy configuration worked correctly on Fedora 42.

The TLS padding extension is explicitly designed for middlebox compatibility (RFC 7685). Rejecting it defeats its purpose and breaks clients on modern Linux distributions shipping OpenSSL 3.5+ with PQC-enabled crypto policies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions