{"record":{"id":"742c6454525fe678","repo":"fatedier/frp","slug":"host-header-rewrite-failed","errorCode":null,"errorMessage":"host header rewrite failed","messagePattern":"host header rewrite failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/util/vhost/vhost.go","lineNumber":252,"sourceCode":"\taccept          chan net.Conn\n\tctx             context.Context\n}\n\nfunc (l *Listener) Accept() (net.Conn, error) {\n\txl := xlog.FromContextSafe(l.ctx)\n\tconn, ok := <-l.accept\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"listener closed\")\n\t}\n\n\t// if rewriteHost func is exist\n\t// rewrite http requests with a modified host header\n\t// if l.rewriteHost is empty, nothing to do\n\tif l.mux.rewriteHost != nil {\n\t\tsConn, err := l.mux.rewriteHost(conn, l.rewriteHost)\n\t\tif err != nil {\n\t\t\txl.Warnf(\"host header rewrite failed: %v\", err)\n\t\t\treturn nil, fmt.Errorf(\"host header rewrite failed\")\n\t\t}\n\t\txl.Debugf(\"rewrite host to [%s] success\", l.rewriteHost)\n\t\tconn = sConn\n\t}\n\treturn netpkg.NewContextConn(l.ctx, conn), nil\n}\n\nfunc (l *Listener) Close() error {\n\tl.mux.registryRouter.Del(l.name, l.location, l.routeByHTTPUser)\n\tclose(l.accept)\n\treturn nil\n}\n\nfunc (l *Listener) Name() string {\n\treturn l.name\n}\n\nfunc (l *Listener) Addr() net.Addr {","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/vhost/vhost.go#L234-L270","documentation":"In vhost Listener.Accept, after a connection is accepted the muxer optionally rewrites the HTTP Host header (feature used by frp's host-header rewriting for http proxies with rewriteHost). If that rewrite function fails to parse/wrap the connection's first request, the raw error is logged (Warnf) and this generic error is returned instead of the connection. The connection is dropped, not retried.","triggerScenarios":"A client connects to a vhost listener configured with host rewriting and sends data that is not a parseable HTTP request (binary, TLS bytes to a plain port, truncated request); the rewrite wrapper encounters an I/O error reading the first bytes; extremely long/malformed request headers.","commonSituations":"HTTPS traffic sent to vhostHTTPPort (plaintext) where rewriting is enabled; health-check TCP probes that connect and send non-HTTP bytes; clients disconnecting mid-request so the header read fails.","solutions":["Send valid HTTP/1.x requests on the plain vhost port; use vhostHTTPSPort (type=https) for TLS traffic","Check the accompanying Warnf line — it contains the underlying cause (e.g. malformed request, connection reset)","If a proxy needs the original Host preserved, disable host rewriting for that proxy so this code path is skipped"],"exampleFix":"# before\ncurl https://frps:8080/   # TLS bytes to plain http vhost port with rewrite\n\n# after\ncurl http://frps:8080/   # plain HTTP on vhostHTTPPort","handlingStrategy":"try-catch","validationCode":"// ensure only well-formed plain HTTP/1.x hits a rewriting vhost listener\n// (send TLS only to the https vhost port)","typeGuard":null,"tryCatchPattern":"conn, err := vl.Accept()\nif err != nil {\n    if strings.Contains(err.Error(), \"host header rewrite failed\") {\n        xl.Warnf(\"dropped non-HTTP/malformed conn: %v\", err)\n        continue // drop just this conn; the listener stays usable\n    }\n    return err\n}","preventionTips":["Point HTTPS clients at vhostHTTPSPort, never vhostHTTPPort","Exclude TCP health probes from vhost ports or teach them HTTP","Watch frps Warnf logs for the underlying rewrite cause when triaging"],"tags":["vhost","http","parsing","network"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}