shadow-tls
repository·master·Indexed 25 days ago
https://github.com/ihciah/shadow-tlsA TLS camouflage proxy designed to expose real TLS handshakes to firewalls using existing trusted certificates. It makes proxy traffic indistinguishable from legitimate HTTPS traffic to deep packet inspection (DPI). The project includes implementations of ShadowTLS V1, V2, and V3 protocols, offering varying levels of defense against active detection and traffic analysis. It can be deployed via prebuilt binaries or Docker Compose.
What's inside shadow-tls
- Shadow TLS is a TLS camouflage proxy designed to expose a real TLS handshake to firewalls. Unlike Trojan, it does not require you to sign your own certificates; instead, it allows you to use existing trusted certificates (e.g., from large companies or institutions). This ensures that when a browser accesses the domain directly, it shows valid, trusted content, making the traffic appear legitimate to deep packet inspection (DPI).
Understand ShadowTLS V3 Protocol Design
masterShadowTLS V3 is designed to defend against traffic feature detection, active probing, and traffic hijacking. Unlike V2, V3 aims to be resilient against middleman hijacking by implementing a robust authentication and data encapsulation mechanism that does not require hacking or implementing the TLS protocol from scratch. It acts as a TCP stream proxy.Understand ShadowTLS V2 Protocol Design
masterShadowTLS V2 is a more complex protocol designed to defend against active probing and traffic analysis. It supports TLS 1.3 and makes post-handshake traffic difficult to distinguish from real web traffic.
Capabilities:
- Defends against active probing: If an attacker uses a browser to access the server, the server relays the traffic to the TLS handshake server, making it behave like a real web server.
- Defends against traffic analysis: All data is encapsulated within TLS Application Data.
- Supports TLS 1.3.
Mechanism:
- Uses an 8-byte HMAC inserted at the beginning of the first Application Data packet to identify the client.
- The HMAC is calculated based on all data sent by the server (acting as a challenge).
Understand ShadowTLS V1 Protocol Design
masterShadowTLS V1 is a simple protocol designed to make traffic appear as a legitimate TLS handshake using a trusted certificate from a third-party domain.
Capabilities:
- Defends against traffic feature-based blocking (looks like normal TLS rather than random data).
- Defends against SNI-based blocking by using legitimate, trusted domains.
Limitations:
- Cannot defend against active probing.
- Post-handshake traffic is easily distinguishable because it uses TLS without HTTP, which is a rare pattern.
- Only supports TLS 1.2 because the server must monitor the handshake to detect completion.
Understand ShadowTLS V3 Handshake and Security
masterThe V3 protocol handshake is designed to defend against traffic signature detection, active probing, and traffic hijacking.
Key Handshake Mechanics:
- Custom SessionID: The client constructs a 32-byte
SessionID. The first 28 bytes are random, and the last 4 bytes are an HMAC signature of theClientHelloframe (excluding the 5-byte TLS header). The HMAC is created using a password. - Server Authentication: The server authenticates the
ClientHello. If authentication fails, the server acts as a standard TCP relay to the handshake server. If it succeeds, the server hijacks the stream. - ServerRandom: The server logs the
ServerRandomfrom theServerHelloand uses it to initialize an HMAC instance for data encapsulation. - Switching Mechanism: The client uses a
ReadWrapperto detect specific HMAC prefixes in theApplicationDatato determine if the server is legitimate or if the connection has been hijacked.
- Custom SessionID: The client constructs a 32-byte
Understand ShadowTLS V2 Protocol
masterShadowTLS V2 is a more advanced protocol designed to defend against active detection and traffic analysis. It supports TLS 1.3 and ensures that traffic after the handshake is hard to distinguish from real web traffic.
Key Features:
- Active Detection Defense: If an attacker accesses the server with a browser, the server behaves like a real web server by relaying traffic to the trusted TLS handshaking backend.
- Traffic Obfuscation: All data is packed within TLS application data.
- Authentication Mechanism: Uses an 8-byte HMAC inserted at the front of the first application data packet to identify legitimate clients.
- TLS Support: Supports TLS 1.3 and other versions.
Understand ShadowTLS V1 Protocol
masterShadowTLS V1 is a simple protocol designed to expose valid TLS handshaking to a man-in-the-middle (MITM) using trusted certificates from external domains. It defends against SNI-based blocking and basic traffic characteristic blocking, provided the attacker does not perform active detection or post-handshake traffic analysis.
Limitations:
- Cannot defend against active detection.
- Post-handshake traffic is easily distinguishable from normal HTTP/TLS traffic because it uses the application data protocol without modification.
- Only supports TLS 1.2 (required to sense when the handshake finishes).
Implement ShadowTLS V2 Server
masterA V2 server relays data between the client and two backends (a TLS handshaking server and a real server) using an HMAC-based switch instead of handshake monitoring.
Workflow:
- Accept connections.
- Relay traffic between the client and the TLS handshaking server. The server uses all data sent by the server to calculate an HMAC.
- Monitor incoming application data packets from the client. If a packet contains a valid 8-byte HMAC at its front, the server switches the traffic to the real server.
- If no valid HMAC is detected, the traffic continues to be relayed to the TLS handshaking server. This allows standard web browsers to access the HTTP service on the handshaking server without detection.
Implement ShadowTLS V3 Client
masterThe client performs the TLS handshake, handles the switch to encapsulated data, and manages encapsulation/decapsulation. It requires a TLS Client integrated with a
ReadWrapperand aWriteWrapperover theTCPStream.Stage 1: TLS Handshake
- ClientHello: Construct a custom
SessionID(32 bytes: 28 random bytes + 4 bytes HMAC signature of the ClientHello frame excluding the 5-byte TLS header). Use a one-time HMAC instance created with thePreSharedKey. - ReadWrapper:
- Extract
ServerRandomfrom theServerHelloand createHMAC_ServerRandom. - For
ApplicationDataframes: Check if the first 4 bytes match the HMAC of the content (excluding the 4-byte HMAC).- If it matches: The frame is a handshake residue. Rewrite the content using
XOR SHA256(PreSharedKey + ServerRandom)and strip the 4-byte HMAC. - If it does NOT match: The connection is likely hijacked. After the handshake, send a random-length 'decoy' HTTP request and then close the connection.
- If it matches: The frame is a handshake residue. Rewrite the content using
- Extract
Stage 2: Data Forwarding (Post-Handshake)
This stage does not depend on the TLS library. Use
HMAC_ServerRandomC(for client-to-server) andHMAC_ServerRandomS(for server-to-client).- Reading (Server to Client): Parse
ApplicationDataand verify the 4-byte HMAC usingHMAC_ServerRandomSorHMAC_ServerRandom:HMAC_ServerRandommatches: It is handshake residue; ignore it.HMAC_ServerRandomSmatches: This is the encapsulated data. Disable theHMAC_ServerRandombranch and forward the content (without the HMAC) to the user.- Neither matches: Treat as
Alert bad_record_macand handle error.
- Writing (Client to Server): Wrap data in
ApplicationDataand prepend a 4-byte HMAC calculated viaHMAC_ServerRandomC.
- ClientHello: Construct a custom
Deploy Shadow TLS Server using Docker Compose
masterTo deploy the Shadow TLS server, create a
docker-compose.ymlfile with the following configuration. This setup assumes you are also running a Shadowsocks server (e.g.,shadowsocks-libev) on the same host.Ensure the
SERVERenvironment variable in theshadow-tlsservice points to the local address and port of your Shadowsocks instance, and theTLSvariable points to a legitimate domain (e.g.,cloud.tencent.com:443) to mimic real TLS traffic.version: '2.4' services: shadowsocks: image: shadowsocks/shadowsocks-libev container_name: shadowsocks-raw restart: always network_mode: "host" environment: - SERVER_PORT=24000 - SERVER_ADDR=127.0.0.1 - METHOD=chacha20-ietf-poly1305 - PASSWORD=EXAMPLE_PASSWORD_CHANGE_IT shadow-tls: image: ghcr.io/ihciah/shadow-tls:latest restart: always network_mode: "host" environment: - MODE=server - LISTEN=0.0.0.0:8443 - SERVER=127.0.0.1:24000 - TLS=cloud.tencent.com:443 - PASSWORD=CHANGE_IT_123321Implement ShadowTLS V3 Server
masterThe server forwards the TLS handshake, detects the switch to encapsulated data, and manages encapsulation/decapsulation without relying on a TLS library.
Stage 1: Handshake Forwarding
- ClientHello: Inspect the
SessionID.- If authentication fails: Treat as active probing and switch to direct TCP forwarding (or SNI-based routing if implementing multi-SNI).
- If authentication succeeds: Forward the frame and proceed.
- ServerHello: Extract
ServerRandomfrom the response. - Bidirectional Forwarding (with Handshake Server):
- Create
HMAC_ServerRandomCandHMAC_ServerRandom. - Client $\rightarrow$ Handshake Server: Forward directly until a frame is encountered where the first 4 bytes match the
HMAC_ServerRandomCsignature. At this point, stop bidirectional forwarding (ensuring in-flight frames are completed). - Handshake Server $\rightarrow$ Client: Modify
ApplicationDataframes by applyingXOR SHA256(PreSharedKey + ServerRandom)and prepending a 4-byte HMAC calculated byHMAC_ServerRandom.
- Create
Stage 2: Data Forwarding (with Data Server)
- Create
HMAC_ServerRandomS. - Client $\rightarrow$ Data Server: Parse
ApplicationDataand verify the 4-byte HMAC usingHMAC_ServerRandomC. If verification fails, handle asAlert bad_record_mac. After verification, update theHMAC_ServerRandomCinstance with the 4-byte HMAC value itself to prevent cutting/pasting attacks. - Data Server $\rightarrow$ Client: Encapsulate data in
ApplicationDatawith a 4-byte HMAC calculated viaHMAC_ServerRandomS. Update theHMAC_ServerRandomSinstance with the 4-byte HMAC value.
- ClientHello: Inspect the
Implement ShadowTLS V3 Client Logic
masterA V3 client must wrap the network stream with a TLS Client and a
ReadWrapper(on the read side) and aWriteWrapper(on the write side). The process occurs in two stages:Stage 1: TLS Handshake
- Construct SessionID: Sign a custom 32-byte
SessionIDfrom the TLS library. - ReadWrapper Logic:
- Extract
ServerRandomfromServerHelloand createHMAC_ServerRandom. - If the first 4 bytes of an
ApplicationDataframe matchHMAC_ServerRandom(frame content), the server is verified. Rewrite the content usingXOR SHA256(PreSharedKey + ServerRandom)and remove the 4-byte HMAC. - If it does not match, mark the connection as hijacked and send a 'muddled request' (random length HTTP request) after the handshake.
- Extract
Stage 2: Data Forwarding
- Initialize HMACs: Create
HMAC_ServerRandomCandHMAC_ServerRandomS. - Read Side: Parse
ApplicationDataand verify the 4-byte HMAC:- If
HMAC_ServerRandommatches: It is residual handshake data; ignore it. - If
HMAC_ServerRandomSmatches: The switchover is complete; forward the data (without HMAC) to the user. - If neither matches: Handle as
Alert bad_record_mac.
- If
- Write Side: When writing to the connection, add the
ApplicationDataheader and the HMAC calculated byHMAC_ServerRandomC.
- Construct SessionID: Sign a custom 32-byte