server: tls-echo — ClientHello capture + JA4 on the TCP-echo port (§4 complete)
server-release / image (push) Successful in 15s
server-test / test (push) Successful in 28s
server-release / release (push) Successful in 28s

A connection opening with a TLS handshake (first byte 0x16) and ALPN
elt-echo gets the ClientHello it sent back raw (b64) and as a JA4
fingerprint (sec.clienthello_echo), then a TLS byte-echo; plain
connections are unchanged. One port, multiplexed by a timed peek:
plain echo is server-speaks-first, so a silent client (peek timeout) is
greeted, while a TLS client's immediate ClientHello (0x16) routes to the
TLS path — 500ms tolerates ~1s RTT before misdetection.

JA4 (FoxIO): full ClientHello parser (ciphers, extensions, ALPN,
supported_versions, sig algs) with GREASE exclusion; a_b_c fingerprint,
unit-tested for structure + GREASE invariance. Live-verified: elt-echo
negotiated, JA4 t13d1712eo computed, 1530-byte ClientHello returned.
Capability tls-echo. This completes spec §4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mrambossek
2026-07-31 20:59:44 +02:00
co-authored by Claude Opus 5
parent 8a854141c5
commit 1472a86508
5 changed files with 570 additions and 16 deletions
+5 -2
View File
@@ -103,11 +103,14 @@ func serve(cfg *config.Config) error {
sessions := session.NewManager(15 * time.Minute)
dp := &dataplane.Server{Sessions: sessions}
tcpSrv := &tcpecho.Server{}
// TCP echo shares the control cert for its elt-echo TLS variant.
tcpSrv := &tcpecho.Server{
TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12},
}
caps := []string{"udp-probe", "delayed-echo", "connect-back", "http-echo"}
if len(config.Addrs(cfg.TCPListen)) > 0 {
caps = append(caps, "tcp-echo")
caps = append(caps, "tcp-echo", "tls-echo")
}
ctl := &control.Server{