[GH-ISSUE #4217] [http2]代理一个只支持http2的server, frp返回502错误码 #3320

Closed
opened 2026-05-05 14:08:26 -06:00 by gitea-mirror · 9 comments
Owner

Originally created by @shuguang101 on GitHub (May 13, 2024).
Original GitHub issue: https://github.com/fatedier/frp/issues/4217

Bug Description

使用frp代理一个只支持http2的server时, frp总是返回502错误码
HTTP 178 HTTP/1.1 502 Bad Gateway

使用curl连接frp vhost端口
强制curl使用http2连接,但最终http协议还是failback到http1.1了(frp not agree on a protocol), 返回502错误码

curl -4 -vsk --http2 --request POST  ${frp_addr:frp_port} 命令行输出信息

* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* using HTTP/1.x

使用curl直接连接原始端口
强制curl使用http2,能够协商成功,最终使用http2,返回200 服务能正常访问

curl -4 -vsk --http2  raw_ip:raw_port 命令行输出

* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
* using HTTP/2

由于被代理的服务只支持http2, 如果强制使用http1.1访问会失败

curl -4 -vsk --http1.1 raw_ip:raw_port

* ALPN: offers http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* using HTTP/1.x
* old SSL session ID is stale, removing
*** Received HTTP/0.9 when not allowed**
* Closing connection 0
* TLSv1.3 (OUT), TLS alert, close notify (256):

frpc Version

0.57.0

frps Version

0.57.0

System Architecture

linux/amd64

Configurations

frpc

user = "xx"
auth.method = "token"
auth.token = "xx"
udpPacketSize = 1400

loginFailExit = false
serverAddr = "xxxx"
serverPort = xx

transport.poolCount = 0
transport.tcpMux = false
transport.protocol = "tcp"
transport.connectServerLocalIP = "0.0.0.0"

[[proxies]]
name = "https_xxx"
type = "https"
customDomains = ["xxxxx.com"]
transport.proxyProtocolVersion = ""
[proxies.plugin]
type = "https2https"
localAddr = "127.0.0.1:12345"
crtPath = "/xxx/fullchain.pem"
keyPath = "/xxx/privkey.pem"

frps

bindAddr = "xxx"
bindPort = xx

transport.maxPoolCount = 1000
transport.tcpMux = false

vhostHTTPSPort = 443
vhostHTTPTimeout = 120
userConnTimeout = 15
tcpmuxHTTPConnectPort = 0
tcpmuxPassthrough = false

auth.method = "token"
auth.token = "xx"
udpPacketSize = 1400

Logs

No response

Steps to reproduce

  1. 创建一个只支持http2的https服务
  2. 使用https2https代理这个服务
  3. 访问frp会返回502
    ...

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @shuguang101 on GitHub (May 13, 2024). Original GitHub issue: https://github.com/fatedier/frp/issues/4217 ### Bug Description 使用frp代理一个只支持http2的server时, frp总是返回502错误码 `HTTP 178 HTTP/1.1 502 Bad Gateway` **使用curl连接frp vhost端口** 强制curl使用http2连接,但最终http协议还是failback到http1.1了(frp not agree on a protocol), 返回502错误码 ``` curl -4 -vsk --http2 --request POST ${frp_addr:frp_port} 命令行输出信息 * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * using HTTP/1.x ``` **使用curl直接连接原始端口** 强制curl使用http2,能够协商成功,最终使用http2,返回200 服务能正常访问 ``` curl -4 -vsk --http2 raw_ip:raw_port 命令行输出 * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server accepted h2 * Server certificate: * using HTTP/2 ``` 由于被代理的服务只支持http2, 如果强制使用http1.1访问会失败 ``` curl -4 -vsk --http1.1 raw_ip:raw_port * ALPN: offers http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * using HTTP/1.x * old SSL session ID is stale, removing *** Received HTTP/0.9 when not allowed** * Closing connection 0 * TLSv1.3 (OUT), TLS alert, close notify (256): ``` ### frpc Version 0.57.0 ### frps Version 0.57.0 ### System Architecture linux/amd64 ### Configurations frpc ``` user = "xx" auth.method = "token" auth.token = "xx" udpPacketSize = 1400 loginFailExit = false serverAddr = "xxxx" serverPort = xx transport.poolCount = 0 transport.tcpMux = false transport.protocol = "tcp" transport.connectServerLocalIP = "0.0.0.0" [[proxies]] name = "https_xxx" type = "https" customDomains = ["xxxxx.com"] transport.proxyProtocolVersion = "" [proxies.plugin] type = "https2https" localAddr = "127.0.0.1:12345" crtPath = "/xxx/fullchain.pem" keyPath = "/xxx/privkey.pem" ``` frps ``` bindAddr = "xxx" bindPort = xx transport.maxPoolCount = 1000 transport.tcpMux = false vhostHTTPSPort = 443 vhostHTTPTimeout = 120 userConnTimeout = 15 tcpmuxHTTPConnectPort = 0 tcpmuxPassthrough = false auth.method = "token" auth.token = "xx" udpPacketSize = 1400 ``` ### Logs _No response_ ### Steps to reproduce 1. 创建一个只支持http2的https服务 2. 使用https2https代理这个服务 3. 访问frp会返回502 ... ### Affected area - [ ] Docs - [ ] Installation - [ ] Performance and Scalability - [ ] Security - [ ] User Experience - [X] Test and Release - [ ] Developer Infrastructure - [X] Client Plugin - [ ] Server Plugin - [ ] Extensions - [X] Others
gitea-mirror 2026-05-05 14:08:26 -06:00
  • closed this issue
  • added the
    todo
    label
Author
Owner

@xqzr commented on GitHub (May 13, 2024):

看起来是 https2https 插件,返回的 alpn 列表中 不含 h2
建议在 监听 127.0.0.1:12345 的程序 正确配置证书

<!-- gh-comment-id:2107593377 --> @xqzr commented on GitHub (May 13, 2024): 看起来是 `https2https` 插件,返回的 `alpn` 列表中 不含 `h2` 建议在 监听 127.0.0.1:12345 的程序 正确配置证书
Author
Owner

@shuguang101 commented on GitHub (May 13, 2024):

建议在 监听 127.0.0.1:12345 的程序 正确配置证书

证书配置是正确的,因为不通过frp代理直接访问原始端口的情况下能正常访问,并且没有证书错误。

<!-- gh-comment-id:2107654750 --> @shuguang101 commented on GitHub (May 13, 2024): > 建议在 监听 127.0.0.1:12345 的程序 正确配置证书 证书配置是正确的,因为不通过frp代理直接访问原始端口的情况下能正常访问,并且没有证书错误。
Author
Owner

@xqzr commented on GitHub (May 13, 2024):

建议在 监听 127.0.0.1:12345 的程序 正确配置证书

证书配置是正确的,因为不通过frp代理直接访问原始端口的情况下能正常访问,并且没有证书错误。

可以尝试 注释掉 [proxies.plugin] 及以下的行
并添加 localPort = 12345

<!-- gh-comment-id:2107986745 --> @xqzr commented on GitHub (May 13, 2024): > > 建议在 监听 127.0.0.1:12345 的程序 正确配置证书 > > 证书配置是正确的,因为不通过frp代理直接访问原始端口的情况下能正常访问,并且没有证书错误。 可以尝试 注释掉 `[proxies.plugin]` 及以下的行 并添加 `localPort = 12345`
Author
Owner

@xqzr commented on GitHub (May 13, 2024):

并且没有证书错误。

那是因为,给 curl 传递了 -k

<!-- gh-comment-id:2107999010 --> @xqzr commented on GitHub (May 13, 2024): > 并且没有证书错误。 那是因为,给 `curl` 传递了 `-k`
Author
Owner

@shuguang101 commented on GitHub (May 13, 2024):

刚试了一下不带k也没有证书错误

curl -4 -vs --http2 --request POST
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
*  SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: POST]
* h2h3 [:path: /xxxxx]
* h2h3 [:scheme: https]
* h2h3 [:authority: xxxxx]
* h2h3 [user-agent: curl/7.88.1]
* Using Stream ID: 1 (easy handle 0x562d1b103070)
* * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* We are completely uploaded and fine
< HTTP/2 200 
<!-- gh-comment-id:2108098841 --> @shuguang101 commented on GitHub (May 13, 2024): 刚试了一下不带k也没有证书错误 ``` curl -4 -vs --http2 --request POST * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server accepted h2 * Server certificate: * SSL certificate verify ok. * using HTTP/2 * h2h3 [:method: POST] * h2h3 [:path: /xxxxx] * h2h3 [:scheme: https] * h2h3 [:authority: xxxxx] * h2h3 [user-agent: curl/7.88.1] * Using Stream ID: 1 (easy handle 0x562d1b103070) * * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * We are completely uploaded and fine < HTTP/2 200 ```
Author
Owner

@shuguang101 commented on GitHub (May 13, 2024):

https2https 插件和Port 12345 服务用的都是Let's Encrypt的证书(同一个证书)

<!-- gh-comment-id:2108116382 --> @shuguang101 commented on GitHub (May 13, 2024): https2https 插件和Port 12345 服务用的都是Let's Encrypt的证书(同一个证书)
Author
Owner

@xqzr commented on GitHub (May 13, 2024):

https2https 插件和Port 12345 服务用的都是Let's Encrypt的证书(同一个证书)

既然是 同一个证书,那么 不需要使用插件

<!-- gh-comment-id:2108781943 --> @xqzr commented on GitHub (May 13, 2024): > https2https 插件和Port 12345 服务用的都是Let's Encrypt的证书(同一个证书) 既然是 同一个证书,那么 不需要使用插件
Author
Owner

@shuguang101 commented on GitHub (May 14, 2024):

用插件设置了一下http header。现在能确定是什么原因吗?

不知道是否和这个有关:
https://www.cnblogs.com/embedded-linux/p/12585854.html
Golang默认支持HTTP/2协议,只要使用TLS则默认启动HTTP/2特性,但对http Client做一些定制化配置后,会覆盖掉http库的默认行为,导致开启HTTP/1.1。

<!-- gh-comment-id:2109071808 --> @shuguang101 commented on GitHub (May 14, 2024): 用插件设置了一下http header。现在能确定是什么原因吗? 不知道是否和这个有关: https://www.cnblogs.com/embedded-linux/p/12585854.html Golang默认支持HTTP/2协议,只要使用TLS则默认启动HTTP/2特性,但对http Client做一些定制化配置后,会覆盖掉http库的默认行为,导致开启HTTP/1.1。
Author
Owner

@shuguang101 commented on GitHub (May 15, 2024):

nginx在配置proxy_pass时可以指定http版本

location / {
  proxy_pass http://1.2.3.0;
  proxy_http_version 1.1;
}

如果无法准确判断http version,是否可以考虑像nginx一样,在插件配置项里添加一个proxy_http_version用于指定http版本。仅仅是个建议哈,我对nginx和http也不是十分熟悉,只是刚刚看到nginx里有这个配置项。

<!-- gh-comment-id:2112493148 --> @shuguang101 commented on GitHub (May 15, 2024): nginx在配置proxy_pass时可以指定http版本 ``` location / { proxy_pass http://1.2.3.0; proxy_http_version 1.1; } ``` 如果无法准确判断http version,是否可以考虑像nginx一样,在插件配置项里添加一个proxy_http_version用于指定http版本。仅仅是个建议哈,我对nginx和http也不是十分熟悉,只是刚刚看到nginx里有这个配置项。
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#3320
No description provided.