Title TLS alert EOF on paste.rs
AuthorRodrigo Arias Mallo
CreatedSun, 03 May 2026 19:18:43 +0200
State open

Cannot paste in https://paste.rs/web likely due to the TLS alert which aborts the connection before we handle the 303 redirect:

>>>> a_Nav_repush <<<<
Nav_open_url: new url='https://paste.rs/web'
a_Nav_expect_done: repush!
Nav_open_url: new url='https://paste.rs/web'
Connecting to 45.63.94.214:443
>>> sending HTTP:
POST /web HTTP/1.1\x0D
Host: paste.rs\x0D
User-Agent: Dillo/3.3.0\x0D
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\x0D
Accept-Language: en\x0D
Accept-Encoding: gzip, deflate, br\x0D
DNT: 1\x0D
Referer: https://paste.rs/web\x0D
Connection: keep-alive\x0D
Content-Type: application/x-www-form-urlencoded\x0D
Content-Length: 19\x0D
\x0D
content=foo&ext=txt
<<< receiving HTTP:
HTTP/1.1 303 See Other
Server: nginx
Date: Sun, 03 May 2026 17:12:10 GMT
Content-Length: 0
Connection: close
location: /AQSoM.txt
x-content-type-options: nosniff
permissions-policy: interest-cohort=()
x-frame-options: SAMEORIGIN
Strict-Transport-Security: max-age=31536000; includeSubdomains;
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block


TLS ALERT on write: decode error
SSL_read() failed: error:0A000126:SSL routines::unexpected eof while reading
Tls_close_by_key: Avoiding SSL shutdown for: https://paste.rs/web

% dillo -v
Dillo v3.3.0-2-g9df5d021
Libraries: fltk/1.3.11 jpeg/3.1.3 png/1.6.55 webp/1.6.0 zlib/1.3.2 brotli/1.2.0 OpenSSL/3.6.1
Features: +GIF +JPEG +PNG +SVG +WEBP +BROTLI +XEMBED +TLS +IPV6 +CTL

It seems to be a case of non-compliant server. The server must send a close notify alert BEFORE a EOF. When missing, OpenSSL 3 fails at the EOF. See: https://github.com/php/php-src/issues/8369:

OpenSSL became more strict about unexpected EOF (not sending close notify) in 1.1.1e but reverted that change in 1.1.1f due to the huge amount of non-compliant servers. With the new major release 3.0.0 it came back.

Rodrigo Arias Mallo on Mon, 08 Jun 2026 19:26:00 +0200

Reproduced with curl, but they don't complain even if the close notify is not received:

% curl --version
curl 8.19.0 (x86_64-pc-linux-gnu) libcurl/8.19.0 OpenSSL/3.6.1 zlib/1.3.2 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 libpsl/0.21.5 libssh2/1.11.1 nghttp2/1.68.0 ngtcp2/1.21.0 nghttp3/1.15.0 mit-krb5/1.21.3
Release-Date: 2026-03-11
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt mqtts pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

% curl -Lv https://paste.rs/web -F content=foo -F ext=txt
* Host paste.rs:443 was resolved.
* IPv6: (none)
* IPv4: 45.63.94.214
*   Trying 45.63.94.214:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / secp256r1 / rsaEncryption
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*   subject: CN=paste.rs
*   start date: Jun  1 10:02:02 2026 GMT
*   expire date: Aug 30 10:02:01 2026 GMT
*   issuer: C=US; O=Let's Encrypt; CN=YR2
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 3: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "paste.rs" matches cert's "paste.rs"
* OpenSSL verify result: 0
* SSL certificate verified via OpenSSL.
* Established connection to paste.rs (45.63.94.214 port 443) from XXX port XXX
* using HTTP/1.x
> POST /web HTTP/1.1
> Host: paste.rs
> User-Agent: curl/8.19.0
> Accept: */*
> Content-Length: 258
> Content-Type: multipart/form-data; boundary=------------------------hWH1VVV2ciI43zjF3l9XRr
>
* upload completely sent off: 258 bytes
< HTTP/1.1 303 See Other
< Server: nginx
< Date: Mon, 08 Jun 2026 17:21:25 GMT
< Content-Length: 0
< Connection: close
* Need to rewind upload for next request
< location: /ROLMU.txt
< permissions-policy: interest-cohort=()
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< Strict-Transport-Security: max-age=31536000; includeSubdomains;
< X-Frame-Options: SAMEORIGIN
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
<
* shutting down connection #0
* Issue another request to this URL: 'https://paste.rs/ROLMU.txt'
* Hostname paste.rs was found in DNS cache
*   Trying 45.63.94.214:443...
* SSL reusing session with ALPN '-'
* SSL verify result: 0
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / secp256r1 / UNDEF
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*   subject: CN=paste.rs
*   start date: Jun  1 10:02:02 2026 GMT
*   expire date: Aug 30 10:02:01 2026 GMT
*   issuer: C=US; O=Let's Encrypt; CN=YR2
*   subjectAltName: "paste.rs" matches cert's "paste.rs"
* OpenSSL verify result: 0
* SSL certificate verified via OpenSSL.
* Established connection to paste.rs (45.63.94.214 port 443) from XXX port XXX
* using HTTP/1.x
> GET /ROLMU.txt HTTP/1.1
> Host: paste.rs
> User-Agent: curl/8.19.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
...

Here are the relevant packets (22 to 25) for that interaction captured from Wireshark:

No.     Time           Source                Destination           Protocol Length Info
     22 4.669087098    45.63.94.214          XXX                   HTTP     495    HTTP/1.1 303 See Other 

No.     Time           Source                Destination           Protocol Length Info
     23 4.669347437    45.63.94.214          XXX                   TCP      66     443 → XXX [FIN, ACK] Seq=5510 Ack=2160 Win=34752 Len=0

No.     Time           Source                Destination           Protocol Length Info
     24 4.669450854    XXX                   45.63.94.214          TLSv1.2  97     Alert (Level: Fatal, Description: Decode Error)

Internet Protocol Version 4, Src: XXX, Dst: 45.63.94.214
Transmission Control Protocol, Src Port: XXX, Dst Port: 443, Seq: 2160, Ack: 5511, Len: 31
Transport Layer Security
    [Stream index: 0]
    TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Decode Error)
        Content Type: Alert (21)
        Version: TLS 1.2 (0x0303)
        Length: 26
        [Sequence Number: 2]
        Alert Message
            Level: Fatal (2)
            Description: Decode Error (50) <------- Here is the decode error due to FIN packet above

No.     Time           Source                Destination           Protocol Length Info
     25 4.669695258    XXX                   45.63.94.214          TCP      66     XXX → 443 [FIN, ACK] Seq=2191 Ack=5511 Win=77824 Len=0