Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v4.20+][已解决] 正确配置 caddy 等反向代理以和后端 v2ray 服务建立 h2c 连接 #296

Closed
IceCodeNew opened this issue Jul 12, 2019 · 41 comments

Comments

@IceCodeNew
Copy link

IceCodeNew commented Jul 12, 2019

refer to #1644

感谢 @lucifer9 @xiaokangwang 及其他开发者的努力,目前最新版的 v2ray 已经实现了对 h2c 的支持。
但是如何正确地配置 caddy 或其他反向代理来将收到的流量解密,转发给后端的 v2ray,其实并不是一个非常容易的事。故开一个 issue,希望与网友们共同交流思路,并把相关经验整理成文档,为后来人指路。

话休絮烦,下面是 v2ray 服务端和 caddyfile 的配置文件,注释部分是原来没有 h2c 支持的时候的配置。我先做了最简单的修改,也就是我一眼就能看出来需要调整的部分。如果还有问题,那就再一点点补充好了。

# v2ray server
{
  "inbounds": [{
    "port": {port_v2ray_listen_to},
    "listen": "127.0.0.1",
    "protocol": "vmess",
    "settings": {
      "clients": [
        {
          "id": "{uuid-uuid-uuid-uuid-uuid}",
          "alterId": 16
        }
      ]
    },
    "streamSettings": {
      "network": "http",

      # "security": "tls",
      "security": "none",

      # "tlsSettings": {
      #   "certificates": [
      #     {
      #       "certificateFile": "{crt_FullFileName}.crt",
      #       "keyFile": "{key_FullFileName}.key"
      #     }
      #   ]
      # },

      "httpSettings": {
        "host": ["{host.tld_point_to_server}"],
        "path": "{path}"
      }
    }
  }]
}
# Caddyfile
{host.tld_point_to_server} {
    root /var/www/{host.tld_point_to_server}/
    proxy {path} http://127.0.0.1:{port_v2ray_listen_to} {
        # insecure_skip_verify

        # header_upstream X-Forwarded-Proto "https"

        # header_upstream Host "{host.tld_point_to_server}"
        header_upstream X-Forwarded-Host "{host.tld_point_to_server}"
    }
}

客户端逻辑上来说不需要任何更改。

测试下来发现上面的这段配置其实上是不通的。具体的表现是服务器响应超时,留心这一点可能可以减少需要排查的问题的方向。

我现在的思路是通过指定 ALPN 来调整 Caddy 的行为,在官方文档的这一段给了我启发:

alpn is a list of space-separated protocols to use for Application-Layer Protocol Negotiation (ALPN). For HTTPS servers, HTTP versions can be enabled/disabled with this setting. Default is h2 http/1.1.

晚上空下来了仔细查了下 ALPN 这个东西,发现它原来是一个 “Transport Layer Security (TLS) extension for application-layer protocol negotiation. ”
好吧,h2c 和 ALPN 一点关系也没有……

而且在仔细阅读了下面一位非常烦人的网友若干条回复后,我居然另外看到了一段非常具有启发性的引用。顺藤摸瓜找到一个可靠的文档后,我认识到:
h2c 连接说不定都是通过在 HTTP/1.1 消息体中指明“h2c” token 来建立的——换句话说我之前抓包看到的不是一个 bug,是一个 feature……

那么为什么 v2ray 服务端没有响应这个升级请求呢?感觉可能要看看相对应的源代码了。

所以到底应该怎么样才能让 Caddy 和 v2ray 服务端之间建立 h2c 连接呢?我暂时还没有头绪,欢迎网友们贡献思路。

@vcptr
Copy link

vcptr commented Jul 12, 2019

caddy有个
grpc插件 https://caddyserver.com/docs/http.grpc

grpc跑的正是http2协议,试试能否把h2c流量正确转发

@k79e
Copy link

k79e commented Jul 12, 2019

那是因为caddy就不支持h2c把.

@k79e
Copy link

k79e commented Jul 12, 2019

好了 大羽毛支持h2c代理. 你不用谢我. 哈哈哈哈哈哈哈.
其他人知道什么使用软件快分享下哦!!!!

@k79e
Copy link

k79e commented Jul 12, 2019

The string "h2c" identifies the protocol where HTTP/2 is run over cleartext TCP. This identifier is used in the HTTP/1.1 Upgrade header field and in any place where HTTP/2 over TCP is identified.

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...

跟ws不是一个鸟样
..... nginx是不是就能那样用我操. 哈哈哈哈哈 喂 现在客户端不是不支持h2c么 你用的别人修改版么?
有么有试过nginx?

结论. 越来越逗了. 算了我不逗你了.

@vcptr
Copy link

vcptr commented Jul 12, 2019

traefik/traefik#3371

traefik支持h2c后端的,只为分流的话traefik挺合适

@k79e
Copy link

k79e commented Jul 12, 2019

你自相矛盾 终止tls是那种tls客户端接过去 后端直接http连接的 属于web自己解自己的.
h2c我看直接是从头到尾都是h2c吧. 所以他不叫终止tls代理!!!!

@k79e
Copy link

k79e commented Jul 12, 2019

NGINX can already proxy gRPC TCP connections. With this new capability, you can terminate, inspect, and route gRPC method calls. You can use it to:
.......
You can operate the service using unencrypted HTTP/2 (h2c cleartext) or wrap TLS encryption and authentication around the service.

http://nginx.org/en/docs/http/ngx_http_grpc_module.html
大法啊大法 nginx大法好!!

@IceCodeNew
Copy link
Author

你自相矛盾 终止tls是那种tls客户端接过去 后端直接http连接的 属于web自己解自己的.
h2c我看直接是从头到尾都是h2c吧. 所以他不叫终止tls代理!!!!

你连发了这么多条评论,就不知道多路复用么?
我本来还纳闷到底是谁讲话不清不楚的,你对于 h2c 的非常具有启发性的解释倒是让我想起来你是谁了。

老兄啊,GitHub 上面没有屏蔽功能,小弟我实在拿你的垃圾回复没有办法。不知道您能不能发发慈悲,放我一个清净呢?如果你真的觉得你的回复非常有价值,不如另开一贴好了。

@IceCodeNew IceCodeNew changed the title [v4.20+][未解决] 正确配置 caddy 等反向代理以实现「终止TLS」但不降级到 HTTP1.1 [v4.20+][未解决] 正确配置 caddy 等反向代理以和后端 v2ray 服务建立 h2c 连接 Jul 13, 2019
@IceCodeNew IceCodeNew reopened this Jul 13, 2019
@IceCodeNew
Copy link
Author

caddy有个
grpc插件 https://caddyserver.com/docs/http.grpc

grpc跑的正是http2协议,试试能否把h2c流量正确转发

gRPC 的确支持 h2c,而把 v2ray 类比地想象成一个 gRPC server 感觉确实也没什么问题。
我会试试看这个方向,感谢你的建议。

@IceCodeNew
Copy link
Author

containous/traefik#3371
traefik支持h2c后端的,只为分流的话traefik挺合适

好了 大羽毛支持h2c代理. 你不用谢我. 哈哈哈哈哈哈哈.
其他人知道什么使用软件快分享下哦!!!!

以上推荐的这些应用对我而言非常陌生。而总的来说我对于推荐应用的态度是:如果我们想做的事主流的应用都不给予支持(打个比方:NGINX、HaProxy、Caddy、Apache,也许还有些其他的社区比较成熟的应用),那么我们是否还应该走这条路就值得思考了。
所以如果最终我发现上面列举的几个例子中没有一个应用可以实现我们的需要,那我会耐心等待。就像我们今天等到了 Go 标准库对 h2c 的实现、等到了 v2ray 社区对 h2c 的实现一样。

@lucifer9
Copy link

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

@IceCodeNew
Copy link
Author

IceCodeNew commented Jul 13, 2019

测试的时候脑抽末尾少打一个斜杠……实际测试下来 Caddy 返回的是 HTTP 200 状态码,v2ray 那边才是 404 状态码(

测试一般 v2ray 客户端通过外网访问的情景


测试解密后的流量转发给后端的 v2ray 的情景


两边看起来都是一切正常,我还真没看到像是某人放屁说的 Caddy 不支持 h2c 这种问题的确切证据。
但是为什么这个 v2ray 他就是不通呢……

@IceCodeNew
Copy link
Author

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

感谢回复!
我理解您的意思就是说前面一层 Web 应用爱用啥用啥,然后前面解密下来的流量转手给 HaProxy 或者 nghttpx,让它们去和 v2ray 服务端交互,对吗?

@lucifer9
Copy link

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

感谢回复!
我理解您的意思就是说前面一层 Web 应用爱用啥用啥,然后前面解密下来的流量转手给 HaProxy 或者 nghttpx,让它们去和 v2ray 服务端交互,对吗?

我测试的时候就是 haproxy/nghttpx 直接接受 H2 的连接解密以后给 v2ray。当然你说的这种做法理论上也是可以的。不过建议考虑一下 haproxy/nghttpx 放最前面,然后还是根据 header 或者 path 分流给后端(Caddy 或者 v2ray)。既然 Caddy 跟 v2ray 配合有点儿问题,那干脆分开各干各的好了

@IceCodeNew
Copy link
Author

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

感谢回复!
我理解您的意思就是说前面一层 Web 应用爱用啥用啥,然后前面解密下来的流量转手给 HaProxy 或者 nghttpx,让它们去和 v2ray 服务端交互,对吗?

我测试的时候就是 haproxy/nghttpx 直接接受 H2 的连接解密以后给 v2ray。当然你说的这种做法理论上也是可以的。不过建议考虑一下 haproxy/nghttpx 放最前面,然后还是根据 header 或者 path 分流给后端(Caddy 或者 v2ray)。既然 Caddy 跟 v2ray 配合有点儿问题,那干脆分开各干各的好了

嗯,好的,谢谢建议~
HaProxy 放最前面也是我比较喜欢的布置,个人以为 Caddy 的性能是不如 HaProxy 的,不适合放在最前面用来分流。
而且这个布置要继续利用 Caddy 自动更新 TLS 证书的特性也不是不可能,稍微改改就好了。

@k79e
Copy link

k79e commented Jul 13, 2019

h2c都是明文好不好 多路复用也是明文 跟加密没什么关系.
你真会转移话题.

好了.
喂~~~开发者!!! caddy支持h2c(反向代理)么?
开发者: 不支持哦. 要加密!!! 愤怒表情!!!
image

我相信大毛家的服务器是能满足你需求的 他们自称h2只需要 一行配置. 反正介绍是那样的.
haproxy甚至都支持入站h2c 匪夷所思的. 我是不是看错了呢.

@IceCodeNew
Copy link
Author

h2c都是明文好不好 多路复用也是明文 跟加密没什么关系.
你真会转移话题.

好了.
喂~~~开发者!!! caddy支持h2c(反向代理)么?
开发者: 不支持哦. 要加密!!! 愤怒表情!!!
image

我相信大毛家的服务器是能满足你需求的 他们自称h2只需要 一行配置. 反正介绍是那样的.
haproxy甚至都支持入站h2c 匪夷所思的. 我是不是看错了呢.

现在都 9102 年了,您还在拿着几号的事情说事啊。
再最后哀求您一遍,请不要在我的眼前脱粪。


还有你「多路复用也是明文」就说明你不仅计网拎不清,连理解中文语意都有问题。真的求您不要再自我感觉良好了。您自己看看您的回复是不是牛头不对马嘴。

你连发了这么多条评论,就不知道多路复用么?

@ghost
Copy link

ghost commented Jul 14, 2019

h2c测试不通,无法联网

@IceCodeNew
Copy link
Author

h2c测试不通,无法联网

贴下错误信息让大家看看?(建议参考 v2ray-core 库给的 issue 模板)

@IceCodeNew
Copy link
Author

IceCodeNew commented Jul 15, 2019

做了下调研,NGINX 目前还不支持 reverse proxy from h2 to h2c(Refer to doc
// 如果未来哪一天支持了的话大概可以通过跟踪这个 Ticket 来第一时间获得情报。

个人认为 HAProxy 是当下的 Best option。

@aLLeENSmith
Copy link

h2c都是明文好不好多路复用也是明文跟加密没什么关系。
你真会转移话题。
好了。
喂~~~开发者!caddy支持h2c(反向代理)么?
开发者:不支持哦。要加密!愤怒表情!
图片
我相信大毛家的服务器是能满足你需求的他们自称h2只需要一行配置。反正介绍是那样的。
haproxy甚至都支持入站h2c匪夷所思的。我是不是看错了呢。

现在都9102年了,您还在拿着几号的事情说事啊。
再最后哀求您一遍,请不要在我的眼前脱粪。

还有你「多路复用也是明文」就说明你不仅计网拎不清,连理解中文语意都有问题。真的求您不要再自我感觉良好了。您自己看看您的回复是不是牛头不对马嘴。

你连发了这么多条评论,就不知道多路复用么?

看了下你们的对话😂
最然那位兄台说话有点云里雾里不明不白,但如果我没理解错的话他指的应该是这个
caddyserver/caddy#2668

@aLLeENSmith
Copy link

最近也偶然看到v2ray支持h2c了,折腾了一下,走不通,症状和你相同,放弃了😝

@ileeoyo
Copy link

ileeoyo commented Jul 18, 2019

看的4.20新版支持h2c,我也尝试在v2ray服务端和caddy中用h2c连接,也失败了。目前使用老方法客户端和caddy用h2传输,caddy解密后获取path分流,再次加密把数据转给v2ray服务端,v2ray再次解密。如果来回加密解密两次。性能影响虽然不大,但还是觉得第二次加密没有必要。还有我感觉h2也和websocket一样,有时会断流不知道怎么回事

@kingwilliam
Copy link

kingwilliam commented Jul 19, 2019

今天看到caddy doc 有这一段

websocket :

Indicates this proxy is forwarding WebSocket connections. It is shorthand for:
-header_upstream Connection {>Connection}
-header_upstream Upgrade {>Upgrade}

  • HTTP/2 does not support protocol upgrade. *

https://caddyserver.com/docs/proxy

所以 caddy h2c 反向代理 还要等等

@IceCodeNew
Copy link
Author

楼楼上和楼楼楼上配不通可以放一下配置文件,我早就已经搞出来了。
只是最近还在忙一些暑期学校的事情,暂时没空整理经验。

@ileeoyo
Copy link

ileeoyo commented Jul 22, 2019

楼楼上和楼楼楼上配不通可以放一下配置文件,我早就已经搞出来了。
只是最近还在忙一些暑期学校的事情,暂时没空整理经验。

@IceCodeNew 我的配置文件和你帖子中配置文件差不多,思路一样。v2ray接收来自caddy流量如果不开启tls就会不通。只能开启tls(多一道加密解密).希望楼主分享下经验,终结此贴。

@IceCodeNew
Copy link
Author

楼楼上和楼楼楼上配不通可以放一下配置文件,我早就已经搞出来了。
只是最近还在忙一些暑期学校的事情,暂时没空整理经验。

@IceCodeNew 我的配置文件和你帖子中配置文件差不多,思路一样。v2ray接收来自caddy流量如果不开启tls就会不通。只能开启tls(多一道加密解密).希望楼主分享下经验,终结此贴。

额,我记得我前面是说过 Caddy 不支持 h2c 的……没有的话我看楼上不远也有人帮我把具体的官方文档引出来了。
朋友,你得把 Caddy 换成 HAProxy 才能搞定这件事啊。

@cjjdaq
Copy link

cjjdaq commented Jul 25, 2019

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

haproxy的http模式反代h2断流特别严重。不晓得什么原因,网页能开,tg居然登录不上。tcp模式没问题。

@IceCodeNew
Copy link
Author

至少 haproxy 和 nghttpx 最新版都是支持的。我就是用这俩来测试的。具体来说,前端 tls termination 是一直就有支持的,按照习惯写就行;后端 H2C 的支持,haproxy 直接写 server server1 192.168.1.13:80 proto h2 这样就行,nghttpx 是 backend=serv1,8443;/;proto=h2;no-tls 这种写法。

haproxy的http模式反代h2断流特别严重。不晓得什么原因,网页能开,tg居然登录不上。tcp模式没问题。

这里是讨论如何配置 h2c,不是用来交流玄学断流问题的。
请去 v2ray-core 提交 issue 并附上日志详细说明断流问题,争取得到开发者出力帮忙解决。
再说一遍,你选择了一个错误的地方讨论问题。你的问题在这边得不到解答或解决。

@liberal-boy
Copy link
Member

caddy 是不支持的,可以考虑使用我的修改版 /~https://github.com/liberal-boy/caddy
另外,个人测试不如ws,不知道是不是使用环境的问题

@IceCodeNew IceCodeNew changed the title [v4.20+][未解决] 正确配置 caddy 等反向代理以和后端 v2ray 服务建立 h2c 连接 [v4.20+][已解决] 正确配置 caddy 等反向代理以和后端 v2ray 服务建立 h2c 连接 Aug 10, 2019
@firedent
Copy link

firedent commented Jan 5, 2020

额,你们没人试试Apache吗,Apache明确支持h2c哦~

@PillarsZhang
Copy link

PillarsZhang commented Jan 10, 2020

额,你们没人试试Apache吗,Apache明确支持h2c哦~

@firedent
看到这个issues后,我还真的试过Apache的mod_proxy_http2模块,光是编译模块就折腾了半天,最后我也成功反代了h2的网站(但是找不到能测试的h2c的网站)
于是乎我直接给v2ray反代,v2ray端的配置基本同上,apache端配置大概这样:

    ProxyPass /ray h2c://127.0.0.1:615/ray
    ProxyPassReverse /ray h2c://127.0.0.1:615/ray

但是好像出错了😨
因为时间关系我没有继续测试apache两边都h2的情况
也许h2的一大意义就是可以套国内普通cdn...
找不到支持cdn-server h2 的cdn

@scientistzjf
Copy link

scientistzjf commented Mar 1, 2020

为什么V2ray不搞个像Caddy一样的建站功能,这样单个V2ray就能实现H2+TLS+WEB了,伪装程度一点也不差啊。谁能提提议一下啊~~~

@PillarsZhang
Copy link

为什么V2ray不搞个像Caddy一样的建站功能,这样单个V2ray就能实现H2+TLS+WEB了,伪装程度一点也不差啊。谁能提提议一下啊~~~

233boy的脚本已经满足了这个需求
v2ray还是做核心的功能好

@rhjdvsgsgks
Copy link

测试了下用Nginx的grpc,不通,v2ray服务端像是没收到请求一样哪怕把loglevel调到了debug也没有输出
nginx的log

upstream rejected request with error 0 while reading response header from upstream, client: 127.0.0.1, server: _, request: "PUT / HTTP/2.0", upstream: "grpc://127.0.0.1:10000", host: "127.0.0.1"

v2ray客户端

[Warning] [3895811459] v2ray.com/core/app/proxyman/outbound: failed to process outbound traffic > v2ray.com/core/proxy/vmess/outbound: failed to find an available destination > v2ray.com/core/common/retry: [v2ray.com/core/transport/internet/http: unexpected status404] > v2ray.com/core/common/retry: all retry attempts failed
[Info] [3895811459] v2ray.com/core/app/proxyman/inbound: connection ends > v2ray.com/core/proxy/socks: connection ends > v2ray.com/core/proxy/socks: failed to transport all TCP response > io: read/write on closed pipe

@inevity
Copy link

inevity commented May 15, 2020

Have done for nginx using the stream module to reversing proxy the h2c to v.

@rhjdvsgsgks
Copy link

Have done for nginx using the stream module to reversing proxy the h2c to v.

any example config or tutorial ?
i found this in your contribution activity , but it's using "luajit" not the "stream module" you said

@inevity
Copy link

inevity commented May 21, 2020

Have done for nginx using the stream module to reversing proxy the h2c to v.

any example config or tutorial ?
i found this in your contribution activity , but it's using "luajit" not the "stream module" you said

luajit code in stream config block

@rhjdvsgsgks
Copy link

luajit code in stream config block

i haven't noticed that before, thanks

@ha-ku
Copy link

ha-ku commented Aug 27, 2020

额,你们没人试试Apache吗,Apache明确支持h2c哦~

我试了试,会出问题
使用ProxyPass "/path" "h2://localhost:port/path"时,apache的log里会有一个500报错。
使用ProxyPass "/path" "h2c://localhost:port/path"时,apache的log里空无一物。
上面两种情况(config.json里的security有对应修改),v2ray的access.log和error.log里都空空的。
非2.2.0-rc1的caddy也会有这个问题,有可能是同样的问题。

@rhjdvsgsgks
Copy link

看到最近 cloudflare 支持了 grpc ,想问下有没有人成功实现了让 v2ray 通过 grpc 通信

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests