mic.git


mic

~ proxy for JA4-TLS fingerprinting evasion
git clone https://github.com/djnnvx/mic.git
log | files | refs | archive | README | LICENSE

commit 61a7fd60396c7dc7b27ebb3d39ff4fda3d009d43
parent 8327c17435a06f5b34a9ad379e7aa7a7227edb39
Author: djnn <[email protected]>
Date: Wed, 20 Aug 2025 22:03:43 +0900

feat: adding test server and test client

Diffstat:
Atest/client/main.go | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/server/cert.pem | 19+++++++++++++++++++
Atest/server/key.pem | 28++++++++++++++++++++++++++++
Atest/server/main.go | 27+++++++++++++++++++++++++++

4 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/test/client/main.go b/test/client/main.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+	"bufio"
+	"log"
+	"net"
+	"net/http"
+	"strings"
+
+	utls "github.com/refraction-networking/utls"
+)
+
+func main() {
+	proxyAddr := "127.0.0.1:8080"
+	targetAddr := "127.0.0.1:8443"
+
+	// 1. Establish a TCP connection to the proxy.
+	log.Printf("Connecting to proxy at %s", proxyAddr)
+	proxyConn, err := net.Dial("tcp", proxyAddr)
+	if err != nil {
+		log.Fatalf("Failed to connect to proxy: %v", err)
+	}
+	defer proxyConn.Close()
+
+	// 2. Manually send the HTTP CONNECT request to the proxy.
+	connectReq, _ := http.NewRequest(http.MethodConnect, "https://"+targetAddr, nil)
+	if err := connectReq.Write(proxyConn); err != nil {
+		log.Fatalf("Failed to send CONNECT request to proxy: %v", err)
+	}
+
+	// 3. Read the proxy's response to the CONNECT request.
+	reader := bufio.NewReader(proxyConn)
+	resp, err := http.ReadResponse(reader, connectReq)
+	if err != nil {
+		log.Fatalf("Failed to read proxy response: %v", err)
+	}
+	if resp.StatusCode != http.StatusOK {
+		log.Fatalf("Proxy returned non-200 status: %s", resp.Status)
+	}
+	log.Println("Proxy connection established.")
+
+	// 4. Create a uTLS client from the proxied connection.
+	// We'll use the Chrome 116 fingerprint for the client.
+	utlsConfig := &utls.Config{ServerName: strings.Split(targetAddr, ":")[0]}
+	uclient := utls.UClient(proxyConn, utlsConfig, utls.HelloRandomized)
+
+	// 5. Perform the TLS handshake and get the handshake state.
+	if err := uclient.Handshake(); err != nil {
+		log.Fatalf("uTLS handshake failed: %v", err)
+	}
+
+
+	// 6. Extract and print key details from the server's certificate,
+	// which are used to measure the server's JA4 fingerprint.
+	log.Println("\n--- Server Fingerprint Measurement (JA4-like) ---")
+	connState := uclient.ConnectionState()
+	if len(connState.PeerCertificates) > 0 {
+		cert := connState.PeerCertificates[0]
+		log.Printf("Server Certificate Subject: %s", cert.Subject.CommonName)
+		log.Printf("Server Certificate Issuer: %s", cert.Issuer.CommonName)
+		log.Printf("Server Certificate Validity: %s to %s", cert.NotBefore, cert.NotAfter)
+	}
+
+	// 7. This section demonstrates how to use the tunneled connection to send a request.
+	// The client will use the uTLS connection to send a simple HTTP GET request to the test server.
+	log.Println("\n--- Sending Request to Test Server ---")
+	req, _ := http.NewRequest(http.MethodGet, "https://"+targetAddr+"/", nil)
+	if err := req.Write(uclient); err != nil {
+		log.Fatalf("Failed to write request: %v", err)
+	}
+
+	// Read and print the response from the test server.
+	resp, err = http.ReadResponse(bufio.NewReader(uclient), req)
+	if err != nil {
+		log.Fatalf("Failed to read response from server: %v", err)
+	}
+	defer resp.Body.Close()
+	log.Printf("Server Response Status: %s", resp.Status)
+}
diff --git a/test/server/cert.pem b/test/server/cert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/zCCAeegAwIBAgIQTs3QM4jgeBYOOKp+ZekqpjANBgkqhkiG9w0BAQsFADAS
+MRAwDgYDVQQKEwdBY21lIENvMB4XDTI1MDgyMDEyNTYwMloXDTI2MDgyMDEyNTYw
+MlowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAO2JDkMuo4bun8ZSXR3OsInpZpCXsJrcZ82SjItKyOdRcEDqNIsITmYO
+PmffVGHeTupCmONW0exZvh1BVS3HNHY80LG0usmYvR/vM0nIodUYByPiUO2xOh83
+8RpiqTZ7edp/+DiykK3pbceDzSfBs0FJi/03v/RTJxr+26xVNxnKMpTkigj8rDNA
+lKw8XMm0m7RK6CpPxP77D614hs/lDqKTo9qT9EL8tqeMfkA2+M5drsw9eAJs0ENw
+1UzS83G1EfCJE51KL93YYMFjhIh4PCf9B854gkSBSXZ0/8W51YmLLLRnCpQnxLN5
+Rb+lIbpYbnwe7LcN/N1mNkGvgvBYDKECAwEAAaNRME8wDgYDVR0PAQH/BAQDAgWg
+MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwGgYDVR0RBBMwEYIJ
+bG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCL8Ltm60bEKmNseEKF
+NLyotxv6AgF+63+WeQwEXrVFckfKb+DA8qcsFkv5/UigZPC+kQ8R90HgWtObeldK
+dJmob9g4IlPRcyY0ygURIsIdzYVeEluofn4mXjoNai4+ubaRvuVvq/IeSMV3QLxx
+8nbh5xuruxWBVuW78siwYcNwd4TTkXBd6BG1zziQMHQo24esLMJWZANte48dg2+E
+64Y0mA9pINVB4tTdgGuy6DlFt22019FGydeLIPqSvSJNAQtTXEhgphIKuusOhk/J
+C1tnexaN+NS3sYjxvbCeOZ41/UTzOzx1CZviaWWF1x5FRmwyYz1bdWejmBd9faaM
+MUvT
+-----END CERTIFICATE-----
diff --git a/test/server/key.pem b/test/server/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDtiQ5DLqOG7p/G
+Ul0dzrCJ6WaQl7Ca3GfNkoyLSsjnUXBA6jSLCE5mDj5n31Rh3k7qQpjjVtHsWb4d
+QVUtxzR2PNCxtLrJmL0f7zNJyKHVGAcj4lDtsTofN/EaYqk2e3naf/g4spCt6W3H
+g80nwbNBSYv9N7/0Uyca/tusVTcZyjKU5IoI/KwzQJSsPFzJtJu0SugqT8T++w+t
+eIbP5Q6ik6Pak/RC/LanjH5ANvjOXa7MPXgCbNBDcNVM0vNxtRHwiROdSi/d2GDB
+Y4SIeDwn/QfOeIJEgUl2dP/FudWJiyy0ZwqUJ8SzeUW/pSG6WG58Huy3DfzdZjZB
+r4LwWAyhAgMBAAECggEAE5XGj6xOxP3ApFd++fz9+idwBeGb9bwEJKNxFyMPzl+d
+A9BlWKyGQLMeWu4p3o/rFDTXHX3qsE3BKr3ySf38ycSMTu3gRzL8YdLh+OY9m0mJ
+45MlEEdM/yBbrsza6tt8QC0A+5vHHHyWSQPWOVfAce4G4gmXHowLBpZkHAd14MuH
+qXuIrVZfXa59dHrqZdsyD1v08NEqEmicEqn33Tct2iLIbA2HOuPD3VzWfdQQcxk+
+2scIMlE50OnmaGBlDKnAkX7ddoYH+zAFlJVlqu8yp5MCp6tbug65fNxGc+vpFHZE
+rbTICT2Rp7OAE89CcXxVg189DWPyUC4TViG06LCdKQKBgQDtx/cEFwmYFlLA5X5C
+rP0q8pMkiCikHiaeGm1Ou6NdD33iUr3UqNwG3jzRWpwp7GrPr9sW5uKtqDv2JDfZ
+FEh6dVD9vWN7a0/iqBUgJhA0n4+Ao+iYmPIwnu5KO4qm9MPhtX6oeQKiaqU42QMr
+26fBLUxyrW78ZMR2avy7jndIuwKBgQD/vEVLKGakas2AQRF/qxc4Kefr9gDJprIj
+wscbApVYv7iIJbbGkpOCRWcRJoVrQzKCSoPHz7CZGJhpe6CMyzQPuAnghT9xvcjo
+AKS3yb1JmFfRqmteA9PBtYCtdSaznSDpcM5NA2ZpzLmHyeDmxOGAp+jzXZ5Va2ew
+hFj/7iboUwKBgDNcWhLcFwpu5/kamSc1zomUVAw0DPNGP/kupCW5ihPz4LEeRjrF
+LqGdJ23hMJItqvSpe516ycPQ7wK/2ABfzTgGVzQ30GE8UMkYnVeQYTe8r3aN8RPl
+FYtDCR2nts9RV25Nkco6OUNz3bRly7WRgK7NZhHvPGXwLi+V9Hle0I05AoGBALFh
+VCriVfd7ARkRiOKluFBDeNMI6dj0n6EAS/wnGZHaQVNl3VX0ew4jt26E6ovQqysG
+Jkukehhmn+iiUGT32R+CBo/NvIjXG5AYSigUbQ+r9FXAQAKQ4wL8MsmddX+l4Bsr
+HFz8m7+Mua8+zpkiPEtxq7mJ2PXkrqIX2meCN0hzAoGBAIcufuifo7M2CZWvNNur
+Hm4aNxu/ejERvFjXMBwDMU9VnzY1vV8WqpQZyiZhILM5fUf6kHLLI9IorsZMe2On
+BenT06uNM6FONqO7/Tb3gOsu1c84OdhqBNSnlkGJhh9FhVekiLxDZ7tcEsXMz60J
++3yMTr67bSSBK9nxU7C8NQ1R
+-----END PRIVATE KEY-----
diff --git a/test/server/main.go b/test/server/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+)
+
+func main() {
+	// 1. Define the handler function for all requests.
+	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		log.Printf("Received request for: %s %s", r.Method, r.URL.Path)
+		w.WriteHeader(http.StatusOK)
+		fmt.Fprintf(w, "Hello! You have reached the test server. All is well.")
+	})
+
+	// 2. Set the address for the server to listen on.
+	addr := "127.0.0.1:8443"
+
+	// 3. Start the HTTPS server.
+	log.Printf("Starting HTTPS test server on %s", addr)
+	err := http.ListenAndServeTLS(addr, "cert.pem", "key.pem", nil)
+	if err != nil {
+		log.Fatalf("Test server failed: %v", err)
+	}
+}
+