ginuerzh/gost · error

bad tls data len

Error message

bad tls data len

What it means

Parse of a TLS obfuscation header failed because the parsed record length exceeds maxTLSDataLen. The library reads the 2-byte TLS record length field and rejects values larger than the allowed maximum, since such a record cannot be a valid TLS handshake/record emitted by the obfuscation protocol. This guards against malformed or hostile streams masquerading as TLS records.

Source

Thrown at obfs.go:323

		0x009e, 0xc024, 0xc028, 0x006b, 0xc023, 0xc027, 0x0067, 0xc00a,
		0xc014, 0x0039, 0xc009, 0xc013, 0x0033, 0x009d, 0x009c, 0x003d,
		0x003c, 0x0035, 0x002f, 0x00ff,
	}

	compressionMethods = []uint8{0x00}

	algorithms = []uint16{
		0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402,
		0x0403, 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,
	}

	tlsRecordTypes   = []uint8{0x16, 0x14, 0x16, 0x17}
	tlsVersionMinors = []uint8{0x01, 0x03, 0x03, 0x03}

	ErrBadType         = errors.New("bad type")
	ErrBadMajorVersion = errors.New("bad major version")
	ErrBadMinorVersion = errors.New("bad minor version")
	ErrMaxDataLen      = errors.New("bad tls data len")
)

const (
	tlsRecordStateType = iota
	tlsRecordStateVersion0
	tlsRecordStateVersion1
	tlsRecordStateLength0
	tlsRecordStateLength1
	tlsRecordStateData
)

type obfsTLSParser struct {
	step   uint8
	state  uint8
	length uint16
}

type obfsTLSConn struct {

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Verify both endpoints run the same obfs protocol/version and the remote actually speaks the TLS-obfuscation format
  2. Check the connection for corruption/reordering (unreliable transport) that shifts the parse state
  3. Re-sync or restart the stream; once the state machine is misaligned, re-establish the connection
  4. If you control the peer, ensure records are capped at maxTLSDataLen before sending

Example fix

// before: parsing arbitrary bytes that are not obfs-TLS
node, err := obfs.Parse(rawStream)
// after: validate the first record header length before parsing
if binary.BigEndian.Uint16(raw[3:5]) > maxTLSDataLen {
    return fmt.Errorf("stream is not valid obfs-tls traffic")
}
node, err := obfs.Parse(raw)
Defensive patterns

Strategy: validation

Validate before calling

if len(raw) >= 5 && binary.BigEndian.Uint16(raw[3:5]) > maxTLSDataLen {
    return errors.New("invalid obfs-tls record length")
}

Prevention

When it happens

Trigger: Calling Parse on a byte stream whose TLS record header carries a length field > maxTLSDataLen (checked in the state machine at obfs.go:389 when r.length is read). Typically happens when the peer is not sending the expected TLS-obfuscated traffic or the stream is corrupted mid-record.

Common situations: Pointing an obfs client at a plain TLS server (raw TLS records may exceed the crafted maximum), byte loss/corruption in the tunnel causing misaligned parsing, or a version mismatch between obfs endpoints.

Understand the failure class

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/a21f21baad29c113. Report an issue: GitHub.