Aparecium is a proof-of-concept tool designed to detect TLS camouflage protocols, specifically ShadowTLS v3 and REALITY, by exploiting their handling of TLS 1.3 post-handshake messages.
ShadowTLS v3 and REALITY are TLS 1.3-based camouflage protocols that disguise network traffic as legitimate TLS traffic to evade deep packet inspection (DPI) and active probing. Aparecium identifies these protocols by analyzing discrepancies in post-handshake messages, particularly the NewSessionTicket
message, which these protocols fail to mimic correctly.
ShadowTLS v3 uses Pre-Shared Key (PSK) authentication and relays second-pass handshake messages (e.g., ServerHello
, EncryptedExtensions
, Certificate
, CertificateVerify
, Finished
) from the target server, tainting them with an HMAC(PSK) that adds 4 bytes to their length. After the client sends the ClientFinished
message, ShadowTLS stops relaying target server messages and handles encrypted Shadowsocks traffic.
sequenceDiagram
participant Client
participant ShadowTLS
participant Target
Client->>ShadowTLS: ClientHello (Challenge, PSK)
ShadowTLS->>Target: ClientHello
Target->>ShadowTLS: ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished
ShadowTLS->>Client: ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished (tainted with HMAC(PSK), +4 bytes)
Client->>ShadowTLS: ClientFinished
Client->>ShadowTLS: Shadowsocks (Encrypted)
ShadowTLS->>Client: Shadowsocks (Encrypted)
REALITY operates as a "real" TLS 1.3 server, generating a fake Certificate message and padding responses to match the target server’s message lengths. Like ShadowTLS, it only relays second-pass handshake messages and switches to encrypted TLS AEAD traffic after the ClientFinished
message.
sequenceDiagram
participant Client
participant REALITY
participant Target
Client->>REALITY: ClientHello (Challenge, AuthKey)
REALITY->>Target: ClientHello
Target->>REALITY: ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished
REALITY->>Client: ServerHello, EncryptedExtensions, Certificate (fake), CertificateVerify, Finished (padded to match original length)
Client->>REALITY: ClientFinished
Client->>REALITY: TLS AEAD (Encrypted)
REALITY->>Client: TLS AEAD (Encrypted)
Aparecium exploits a key vulnerability: both protocols fail to handle post-handshake messages, specifically the NewSessionTicket
message, as defined in the TLS 1.3 RFC. In standard TLS 1.3, servers normally (e.g., those using OpenSSL) send one or two NewSessionTicket
messages after receiving the ClientFinished
message. ShadowTLS and REALITY do not relay or mimic these messages correctly, especially when mimicking OpenSSL-based servers.
- OpenSSL-based servers (common in Nginx, Apache) send two
NewSessionTicket
messages afterClientFinished
.
sequenceDiagram
participant Client
participant Server
Client->>Server: ClientHello
Server->>Client: ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished
Client->>Server: ClientFinished
Server->>Client: NewSessionTicket0 (OpenSSL)
Server->>Client: NewSessionTicket1 (OpenSSL)
- Go-based servers send one
NewSessionTicket
message beforeClientFinished
, which ShadowTLS and REALITY relay since it occurs earlier.
sequenceDiagram
participant Client
participant Server
Client->>Server: ClientHello
Server->>Client: ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished, NewSessionTicket (Go)
Client->>Server: ClientFinished
Since most web servers (e.g., Nginx, Apache) use OpenSSL, ShadowTLS and REALITY fail to mimic their post-handshake behavior, discarding NewSessionTicket
messages.
Aparecium detects TLS camouflage protocols in two phases:
- Capture a
ClientHello
message and generate its fingerprint using utls.Fingerprinter. - Replay a modified
ClientHello
(with newClientRandom
,SessionID
, andKeyShare
) to the suspected server. - Complete the TLS handshake and send a probe request based on the negotiated application protocol (e.g., HTTP).
- Record the lengths of any
NewSessionTicket
messages (typically two equal-length messages for OpenSSL servers). - If no NewSessionTicket messages are received, the server is likely a legitimate TLS server.
- Monitor the server’s response after the
ServerFinished
message (fixed at 53 or 69 bytes in TLS 1.3). - Check the lengths of the next two messages:
- If they do not match the
NewSessionTicket
lengths from Phase 1, the server is likely using a TLS camouflage protocol. - If the lengths match, the server is likely a legitimate TLS server.
- If they do not match the
- For ShadowTLS, verify if the
ServerFinished
message is 4 bytes longer (57 or 73 bytes) due to HMAC(PSK) tainting.
Some servers, like those operated by Google, do not send NewSessionTicket
messages. When ShadowTLS or REALITY mimics these servers, they are immune to this detection method, as described in Phase 1.5.
- Clone the Aparecium repository:
git clone https://github.com/ban6cat6/aparecium.git cd aparecium
- Install dependencies:
go mod tidy
- Start the proxy server and client with the appropriate configuration files for ShadowTLS or REALITY:
$SERVER run -c $PROTOCOL/client.json $SERVER run -c $PROTOCOL/server.json
- Launch Aparecium to intercept traffic between the proxy client and server:
# $protocol can be either "reality" or "shadowtls", default to "reality". go run ./main.go -victim $protocol
Probe the server at 127.0.0.1:10444
using a TLS client, such as curl
:
curl -vik --resolve wechat.com:10444:127.0.0.1 https://wechat.com:10444
Alternatively, use this Go code snippet:
package main
import (
"crypto/tls"
"net"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:10444")
if err != nil {
panic(err)
}
tlsConn := tls.Client(conn, &tls.Config{
ServerName: "wechat.com",
})
err = tlsConn.Handshake()
if err != nil {
panic(err)
}
}
The TLS handshake should complete without errors.
Send a request through a SOCKS5 proxy to verify detection:
curl -x socks5://127.0.0.1:10080 http://www.example.com
If a TLS camouflage protocol is detected, Aparecium will output:
TLS camouflage connection detected
To resist detection, REALITY servers should mimic OpenSSL-based servers:
- Delay sending
NewSessionTicket
messages until after receiving theClientFinished
message. - Actively probe the target server to capture
NewSessionTicket
message lengths. - Send fake, padded
NewSessionTicket
messages matching the target’s lengths.
The HMAC(PSK) tainting in ShadowTLS adds 4 bytes to handshake messages, making it highly detectable. To mitigate:
- Remove or modify the HMAC mechanism to avoid length discrepancies.
- Mimic OpenSSL’s post-handshake behavior by sending fake
NewSessionTicket
messages afterClientFinished
.
ShadowTLS v3 is hereby declared "dead" due to its inherent design flaws. The HMAC(PSK) tainting adds 4 bytes to handshake messages (e.g., ServerFinished, resulting in 57 or 73 bytes instead of the standard 53 or 69 bytes), creating a glaring signature that tools like Aparecium easily detect.
Contributions are welcome! Please submit a pull request or open an issue on the GitHub repository.
This project is licensed under the MIT License.