{"record":{"id":"545129d87ac1b235","repo":"ginuerzh/gost","slug":"bad-request-545129","errorCode":null,"errorMessage":"bad request","messagePattern":"bad request","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"obfs.go","lineNumber":145,"sourceCode":"\tif err != nil {\n\t\tlog.Logf(\"[ohttp] %s -> %s : %v\", c.Conn.RemoteAddr(), c.Conn.LocalAddr(), err)\n\t\treturn\n\t}\n\n\tb := bytes.Buffer{}\n\n\tif r.Method != http.MethodGet || r.Header.Get(\"Upgrade\") != \"websocket\" {\n\t\tb.WriteString(\"HTTP/1.1 503 Service Unavailable\\r\\n\")\n\t\tb.WriteString(\"Content-Length: 0\\r\\n\")\n\t\tb.WriteString(\"Date: \" + time.Now().Format(time.RFC1123) + \"\\r\\n\")\n\t\tb.WriteString(\"\\r\\n\")\n\n\t\tif Debug {\n\t\t\tlog.Logf(\"[ohttp] %s <- %s\\n%s\", c.RemoteAddr(), c.LocalAddr(), b.String())\n\t\t}\n\n\t\tb.WriteTo(c.Conn)\n\t\treturn errors.New(\"bad request\")\n\t}\n\n\tb.WriteString(\"HTTP/1.1 101 Switching Protocols\\r\\n\")\n\tb.WriteString(\"Server: nginx/1.10.0\\r\\n\")\n\tb.WriteString(\"Date: \" + time.Now().Format(time.RFC1123) + \"\\r\\n\")\n\tb.WriteString(\"Connection: Upgrade\\r\\n\")\n\tb.WriteString(\"Upgrade: websocket\\r\\n\")\n\tb.WriteString(fmt.Sprintf(\"Sec-WebSocket-Accept: %s\\r\\n\", computeAcceptKey(r.Header.Get(\"Sec-WebSocket-Key\"))))\n\tb.WriteString(\"\\r\\n\")\n\n\tif Debug {\n\t\tlog.Logf(\"[ohttp] %s <- %s\\n%s\", c.RemoteAddr(), c.LocalAddr(), b.String())\n\t}\n\n\tif c.rbuf.Len() > 0 {\n\t\tc.wbuf = b // cache the response header if there are extra data in the request body.\n\t\treturn\n\t}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/obfs.go#L127-L163","documentation":"serverHandshake for the ohttp (HTTP obfuscation) transport returns errors.New(\"bad request\") when the client's opening HTTP request fails validation — the code writes a plain HTTP error response back to the client and then returns this error to abort the handshake. It means the incoming bytes were not a valid expected obfuscated-HTTP request.","triggerScenarios":"Client sends a malformed or non-ohttp handshake to an ohttp server; HTTP method/headers missing or wrong; a plain-HTTPS scanner or wrong-protocol client connects to the ohttp port; client and server obfs methods/params mismatch (e.g. server is ohttp but client uses plain http2 or different obfs).","commonSituations":"Port scanners and bots hitting the exposed port; clients configured with the wrong transport/obfs plugin; version mismatch between client and server ohttp implementations; direct browser access to the tunnel port.","solutions":["Verify client and server use the same obfs method and parameters (ohttp on both ends).","Check the client's handshake request format matches what serverHandshake expects (path, headers, method).","Align client/server versions of the library; the handshake format may differ between versions.","Confirm the client is pointed at the ohttp-enabled port, not another protocol's port."],"exampleFix":"// client config before\nnodes: [{addr: \"srv:443\", connector: \"http2\", dialer: \"tcp\"}]\n// after (match server obfs)\nnodes: [{addr: \"srv:443\", connector: \"http2\", dialer: \"obfs\", dialerArgs: {method: \"ohttp\", host: \"nginx.example.com\"}}]","handlingStrategy":"validation","validationCode":"// client side: verify obfs config matches server before connecting\nif clientObfsMethod != serverObfsMethod {\n\treturn fmt.Errorf(\"obfs method mismatch: client=%s server=%s\", clientObfsMethod, serverObfsMethod)\n}","typeGuard":"func isOhttpHandshakeRejected(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"bad request\")\n}","tryCatchPattern":"conn, err := client.Handshake(ctx)\nif err != nil && isOhttpHandshakeRejected(err) {\n\t// likely wrong obfs/transport on one side; recheck config or probe server type\n\tlog.Printf(\"server rejected ohttp handshake; check obfs method/params\")\n}","preventionTips":["Keep client and server obfs method and parameters identical.","Deploy matching library versions on both ends.","Expect scanner traffic on public ports and treat bad-request handshakes as noise unless they correlate with your clients."],"tags":["obfs","handshake","http","protocol-mismatch"],"backgroundTag":"obfs-handshake-bad-request","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}