{"record":{"id":"89b5df6e824389a4","repo":"fatedier/frp","slug":"connections-to-tcp-vhost-must-be-of-method-connect","errorCode":null,"errorMessage":"connections to tcp vhost must be of method CONNECT","messagePattern":"connections to tcp vhost must be of method CONNECT","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/tcpmux/httpconnect.go","lineNumber":61,"sourceCode":"\t\treturn nil, err\n\t}\n\tmux.SetCheckAuthFunc(ret.auth).\n\t\tSetSuccessHookFunc(ret.sendConnectResponse).\n\t\tSetFailHookFunc(vhostFailed)\n\tret.Muxer = mux\n\treturn ret, nil\n}\n\nfunc (muxer *HTTPConnectTCPMuxer) readHTTPConnectRequest(rd io.Reader) (host, httpUser, httpPwd string, err error) {\n\tbufioReader := bufio.NewReader(rd)\n\n\treq, err := http.ReadRequest(bufioReader)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tif req.Method != \"CONNECT\" {\n\t\terr = fmt.Errorf(\"connections to tcp vhost must be of method CONNECT\")\n\t\treturn\n\t}\n\n\thost, _ = httppkg.CanonicalHost(req.Host)\n\tproxyAuth := req.Header.Get(\"Proxy-Authorization\")\n\tif proxyAuth != \"\" {\n\t\thttpUser, httpPwd, _ = httppkg.ParseBasicAuth(proxyAuth)\n\t}\n\treturn\n}\n\nfunc (muxer *HTTPConnectTCPMuxer) sendConnectResponse(c net.Conn, _ map[string]string) error {\n\tif muxer.passthrough {\n\t\treturn nil\n\t}\n\tres := httppkg.OkResponse()\n\tif res.Body != nil {\n\t\tdefer res.Body.Close()","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/tcpmux/httpconnect.go#L43-L79","documentation":"Returned by frp's HTTPConnectTCPMuxer when it reads the first request from an incoming connection on a tcpmux port of type httpconnect and the HTTP method is not CONNECT. The httpconnect muxer expects the standard HTTP proxy CONNECT handshake (optionally with Proxy-Authorization basic auth) before it will route the connection to a proxy.","triggerScenarios":"A client opens a TCP connection to frps's tcpmuxHTTPConnectPort and sends a plain request (GET/POST) instead of `CONNECT host:port HTTP/1.1`; using an HTTP proxy client against the port with a non-tunnel request; telnet/curl (without -x / CONNECT semantics) probing the port.","commonSituations":"Configuring tcpmuxType = \"httpconnect\" on the frpc proxy but pointing a regular HTTP client or browser at that port; Squid-style proxy expectations vs plain HTTP; a health checker doing HTTP GET against the muxer port.","solutions":["Send a real CONNECT request: `curl -x http://frps:port http://target` or configure the client as an HTTP proxy","If you want plain HTTP virtual hosting on that port, use vhostHTTPPort / type = \"http\" instead of tcpmux httpconnect","Supply Proxy-Authorization (basic auth) if the proxy configured routeByHTTPUser credentials","Verify the tcpmux port in frps.toml matches the port the client connects to"],"exampleFix":"# before\nGET / HTTP/1.1\nHost: internal.example.com\n\n  -> error: connections to tcp vhost must be of method CONNECT\n\n# after\ncurl -x http://frps:7400 http://internal.example.com/  # sends CONNECT internal.example.com:80","handlingStrategy":"validation","validationCode":"// only send CONNECT to an httpconnect muxer port\nreq, _ := http.NewRequest(http.MethodConnect, \"http://target.example.com:80\", nil)\nresp, err := http.DefaultClient.Do(req) // a proxy client will issue CONNECT","typeGuard":null,"tryCatchPattern":"resp, err := client.Do(req)\nif err != nil && strings.Contains(err.Error(), \"must be of method CONNECT\") {\n    // wrong client mode: switch to proxy CONNECT semantics or use vhost http port\n}","preventionTips":["Treat tcpmux(httpconnect) ports as HTTP-proxy ports: configure clients as proxies, not browsers","Document the mux type next to the port number in your ops runbook","Health-check such ports with a raw CONNECT or TCP dial, never HTTP GET"],"tags":["tcpmux","http","proxy","config"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}