{"record":{"id":"2561f3309d4c66d9","repo":"ginuerzh/gost","slug":"bad-major-version","errorCode":null,"errorMessage":"bad major version","messagePattern":"bad major version","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"obfs.go","lineNumber":321,"sourceCode":"\tcipherSuites = []uint16{\n\t\t0xc02c, 0xc030, 0x009f, 0xcca9, 0xcca8, 0xccaa, 0xc02b, 0xc02f,\n\t\t0x009e, 0xc024, 0xc028, 0x006b, 0xc023, 0xc027, 0x0067, 0xc00a,\n\t\t0xc014, 0x0039, 0xc009, 0xc013, 0x0033, 0x009d, 0x009c, 0x003d,\n\t\t0x003c, 0x0035, 0x002f, 0x00ff,\n\t}\n\n\tcompressionMethods = []uint8{0x00}\n\n\talgorithms = []uint16{\n\t\t0x0601, 0x0602, 0x0603, 0x0501, 0x0502, 0x0503, 0x0401, 0x0402,\n\t\t0x0403, 0x0301, 0x0302, 0x0303, 0x0201, 0x0202, 0x0203,\n\t}\n\n\ttlsRecordTypes   = []uint8{0x16, 0x14, 0x16, 0x17}\n\ttlsVersionMinors = []uint8{0x01, 0x03, 0x03, 0x03}\n\n\tErrBadType         = errors.New(\"bad type\")\n\tErrBadMajorVersion = errors.New(\"bad major version\")\n\tErrBadMinorVersion = errors.New(\"bad minor version\")\n\tErrMaxDataLen      = errors.New(\"bad tls data len\")\n)\n\nconst (\n\ttlsRecordStateType = iota\n\ttlsRecordStateVersion0\n\ttlsRecordStateVersion1\n\ttlsRecordStateLength0\n\ttlsRecordStateLength1\n\ttlsRecordStateData\n)\n\ntype obfsTLSParser struct {\n\tstep   uint8\n\tstate  uint8\n\tlength uint16\n}","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/obfs.go#L303-L339","documentation":"ErrBadMajorVersion is returned by the TLS obfs dissector's Parse when the major version byte of a TLS record is not 0x03. All real TLS versions (1.0–1.3) use major version 3 in the record header, so any other value means the stream is not valid TLS.","triggerScenarios":"During Parse at obfs.go:368, in state tlsRecordStateVersion0, the incoming byte (the record header's major version position) is anything other than 0x03; typically the first record of a connection from a non-TLS client.","commonSituations":"Plaintext or wrong-protocol clients connecting to an otls-obfuscated port (scanners, probes); obfs method mismatch between client and server; SSLv2-era clients (version byte 0x02); corrupted streams after desync.","solutions":["Confirm the client actually performs a TLS handshake through the obfs layer (otls on both ends).","Check the connecting client is not sending plaintext or another protocol to the otls port.","Filter/drop scanner traffic at the firewall if logs are dominated by probes.","Re-sync or reset the connection when this occurs — the stream is unrecoverable for the dissector."],"exampleFix":"// before (client without TLS obfs connecting to otls server)\ndialer: {type: \"tcp\"}\n// after\ndialer: {type: \"obfs\", obfs: \"otls\"}","handlingStrategy":"validation","validationCode":"// check record header major version byte before parsing further\nif len(buf) >= 2 && buf[1] != 0x03 {\n\treturn errors.New(\"not a TLS record: bad major version\")\n}","typeGuard":"func hasTLSMajorVersion(hdr []byte) bool {\n\treturn len(hdr) >= 2 && hdr[1] == 0x03\n}","tryCatchPattern":"n, err := dissector.Parse(conn, buf)\nif errors.Is(err, dissector.ErrBadMajorVersion) {\n\tconn.Close()\n\treturn fmt.Errorf(\"non-TLS client %s (major version byte != 0x03)\", conn.RemoteAddr())\n}","preventionTips":["Verify the peer actually speaks TLS before routing it into the otls dissector.","Drop non-TLS connections at once; state cannot be recovered.","Keep obfs configuration symmetric across client and server."],"tags":["obfs","tls","version","protocol-mismatch"],"backgroundTag":"obfs-tls-bad-record-type","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}