nps icon indicating copy to clipboard operation
nps copied to clipboard

websocket不能正常工作

Open snowie2000 opened this issue 4 years ago • 30 comments

使用域名解析功能连接内网hassbian(homeassistant),该服务主要使用websocket作为通信手段。

期望结果: 网页正常展示

实际情况: 可以进入登录页并认证,但最终界面无法展示。 开发者工具显示websocket能建立连接,但数据只发不收,不能获得服务端的返回 ws 上图是正常通信的websocket报文。 使用nps时只有第一行,后面的没有。

完全相同的配置下frp无此问题。

snowie2000 avatar Apr 13 '20 08:04 snowie2000

hass服务端出现错误日志:

Log Details (WARNING) Logger: homeassistant.components.websocket_api.http.connection.1728204624 Source: components/websocket_api/http.py:217 Integration: websocket_api (documentation, issues) First occurred: 4:36:52 PM (1 occurrences) Last logged: 4:36:52 PM

Disconnected: Did not receive auth message within 10 seconds

snowie2000 avatar Apr 13 '20 08:04 snowie2000

#474 websocket 域名解析模式暂时还不支持

ffdfgdfg avatar Apr 13 '20 10:04 ffdfgdfg

我读了一下http.go代码,发现其中存在的问题非常多,你是自己实现了一个简单的反向代理,但为了实现flow控制代码逻辑过于简单,对于例如response都是先dump再write,如果客户端发送一个很大的文件,将对服务端产生巨大压力,并且由于需要完全接受,所以FTTB就会很长。

另外在for循环中bufio.NewReader的行为也不可接受,创建了一大堆临时对象却不释放,并且bufio本身会从io.Reader中缓存数据,这也就是 https://github.com/ehang-io/nps/blob/c9b755360c3b3513e53bb265ae49703f06d6f34f/server/proxy/http.go#L239 的问题所在。

snowie2000 avatar Apr 14 '20 02:04 snowie2000

我读了一下http.go代码,发现其中存在的问题非常多,你是自己实现了一个简单的反向代理,但为了实现flow控制代码逻辑过于简单,对于例如response都是先dump再write,如果客户端发送一个很大的文件,将对服务端产生巨大压力,并且由于需要完全接受,所以FTTB就会很长。

另外在for循环中bufio.NewReader的行为也不可接受,创建了一大堆临时对象却不释放,并且bufio本身会从io.Reader中缓存数据,这也就是

https://github.com/ehang-io/nps/blob/c9b755360c3b3513e53bb265ae49703f06d6f34f/server/proxy/http.go#L239

的问题所在。 对于你说的【response都是先dump再write】这个只是针对需要缓存的情况,正常情况不会dump,bufio.NewReader确实是个问题。 代码刚开始写的比较粗糙,确实有很多不足之处,也欢迎大家pr修改。

cnlh avatar Apr 14 '20 04:04 cnlh

不光是bufio有重复创建的情况,LenConn也是在不停的重复创建,目的只是为了统计流量。 现有的http代理架构确实存在比较大的问题,不建议hijack以后自己处理。

建议可以从httputil.ReverseProxy上进行继承修改,很容易就能实现websocket的支持和流量统计

snowie2000 avatar Apr 14 '20 05:04 snowie2000

经过基于reverseproxy的修改,nps可以正常连上websocket并进行交互。nps现有的架构确实存在问题。 ws1 服务端日志:正确创建了ws链接 ws2 ws正确发送报文。

由于改动很大,并且不符合nps现有的流量统计,也不能支持nps的auth,所以pr暂时就不发了,发了也不可能合并。只是证实了基于reverseproxy修改的可行性。

snowie2000 avatar Apr 14 '20 09:04 snowie2000

是的,计划排在后面,现在主要处理些小改动

ffdfgdfg avatar Apr 14 '20 10:04 ffdfgdfg

请问这个问题解决了吗,我在使用jupyter notebook时发现依旧存在该问题无法正常使用

LogicJake avatar Dec 29 '20 12:12 LogicJake

同上,找不到另一个更好用的内网穿透工具,可惜nps不支持ws

icanc0 avatar Apr 11 '21 16:04 icanc0

同上,找不到另一个更好用的内网穿透工具,可惜nps不支持ws

frp比这个稳定太多了,nps只是界面比较好看而已……

snowie2000 avatar Apr 12 '21 02:04 snowie2000

看了看frp的doc,frp的界面没法比呀

icanc0 avatar Apr 13 '21 18:04 icanc0

Frp可以说没有界面,都是配置文件设置的。你想要稳定就用它,想要界面好看只能用nps

snowie2000 avatar Apr 14 '21 00:04 snowie2000

这个问题我也是,frp正常。本来打算全部切nps无奈,这个网页打不开。

anylines avatar Jun 26 '21 12:06 anylines

Frp可以说没有界面,都是配置文件设置的。你想要稳定就用它,想要界面好看只能用nps

我用nps就是因为有界面,我在外面的时候可以直接通过网页端修改,太方便了。

本来想自己把cache和keepalive加进去,可惜我水平有限,没写过这么大的project。

icanc0 avatar Jun 28 '21 04:06 icanc0

Frp可以说没有界面,都是配置文件设置的。你想要稳定就用它,想要界面好看只能用nps

我用nps就是因为有界面,我在外面的时候可以直接通过网页端修改,太方便了。

本来想自己把cache和keepalive加进去,可惜我水平有限,没写过这么大的project。

那么有几个办法

  • 把tcp连接当http用,ws就不是问题了,但是端口就没法复用了。
  • 放弃ws,乖乖http
  • 自己实现ws支持
  • 找我以前发的pr改改,直接merge肯定不可能了

snowie2000 avatar Jun 28 '21 14:06 snowie2000

现在支持了吗??? 最近遇到类似的问题,折腾了半天用TCP隧道解决了。。。搜了搜果然是不支持websocket。。。。

befantasy avatar Jan 11 '22 11:01 befantasy

v2.0 应该可以支持了吧?

icanc0 avatar Mar 07 '22 13:03 icanc0

现在支持了吗??? 最近遇到类似的问题,折腾了半天用TCP隧道解决了。。。搜了搜果然是不支持websocket。。。。

麻烦问下,怎么用 tcp 隧道解决的?我试了半天还是不行

YYCoder avatar Mar 27 '22 05:03 YYCoder

现在支持了吗??? 最近遇到类似的问题,折腾了半天用TCP隧道解决了。。。搜了搜果然是不支持websocket。。。。

麻烦问下,怎么用 tcp 隧道解决的?我试了半天还是不行

homeassistant?直接新增tcp隧道,映射内网目标服务器8123端口啊,然后公网的服务端用nginx反代

befantasy avatar Mar 27 '22 05:03 befantasy

看到了一个dev-2.0的branch,感觉要有websocket支持了。

icanc0 avatar Mar 27 '22 05:03 icanc0

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥

YYCoder avatar Mar 27 '22 05:03 YYCoder

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥 NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

befantasy avatar Mar 27 '22 05:03 befantasy

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥 NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

我配置了,但是不知道哪里的配置有问题,现象是报了 404,如下: image 我怀疑是不是我的 nginx 配置的 proxy_pass 的端口有问题,请问这个端口应该配置成 nps 配置项里的 bridge_port 还是http_proxy_port? image

YYCoder avatar Mar 27 '22 05:03 YYCoder

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥 NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

我配置了,但是不知道哪里的配置有问题,现象是报了 404,如下: image 我怀疑是不是我的 nginx 配置的 proxy_pass 的端口有问题,请问这个端口应该配置成 nps 配置项里的 bridge_port 还是http_proxy_port? image

都不是,这个是要配置成你新建的TCP隧道的“服务端端口”(local port)

befantasy avatar Mar 27 '22 06:03 befantasy

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥 NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

我配置了,但是不知道哪里的配置有问题,现象是报了 404,如下: image 我怀疑是不是我的 nginx 配置的 proxy_pass 的端口有问题,请问这个端口应该配置成 nps 配置项里的 bridge_port 还是http_proxy_port? image

都不是,这个是要配置成你新建的TCP隧道的“服务端端口”(local port)

大佬牛逼!!!http 请求可以了,但是为什么 wss 还是不行,我看 nginx 日志是报这个,需要 nginx 做额外配置吗? image

YYCoder avatar Mar 27 '22 06:03 YYCoder

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥

NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

我配置了,但是不知道哪里的配置有问题,现象是报了 404,如下: image 我怀疑是不是我的 nginx 配置的 proxy_pass 的端口有问题,请问这个端口应该配置成 nps 配置项里的 bridge_port 还是http_proxy_port? image

都不是,这个是要配置成你新建的TCP隧道的“服务端端口”(local port)

大佬牛逼!!!http 请求可以了,但是为什么 wss 还是不行,我看 nginx 日志是报这个,需要 nginx 做额外配置吗?

image

我看你没加http upgrade,没有http upgrade的话ws工作不了

icanc0 avatar Mar 27 '22 06:03 icanc0

不是 homeassistant,是我自己搭的一个内网 http 服务,里面依赖了 ws。我建了 tcp 隧道,但是没有配置域名解析的话,http 服务就会用不了,不知道为啥

NPS服务端所在的服务器80或443端口上,配置一个Nginx Proxy Manager之类的做反向代理。

我配置了,但是不知道哪里的配置有问题,现象是报了 404,如下: image 我怀疑是不是我的 nginx 配置的 proxy_pass 的端口有问题,请问这个端口应该配置成 nps 配置项里的 bridge_port 还是http_proxy_port? image

都不是,这个是要配置成你新建的TCP隧道的“服务端端口”(local port)

大佬牛逼!!!http 请求可以了,但是为什么 wss 还是不行,我看 nginx 日志是报这个,需要 nginx 做额外配置吗? image

我看你没加http upgrade,没有http upgrade的话ws工作不了

有道理,我 google 一下 nginx 怎么配置 ws 代理,感谢大佬~

BTW,感觉 nps 的配置好难,好多端口要配置,自己也理解不清楚什么时候要用哪个,不知道有没有简单容易理解的做法~

YYCoder avatar Mar 27 '22 06:03 YYCoder

nps算简单的了,但是nps dashboard和doc上的解释的不是很清楚,nps又涉及到客户端和服务端,对networking不怎么了解的人不是很友好

icanc0 avatar Mar 27 '22 06:03 icanc0

nps算简单的了,但是nps dashboard和doc上的解释的不是很清楚,nps又涉及到客户端和服务端,对networking不怎么了解的人不是很友好

确实,感觉我得补一补网络方面的知识了,感谢各位大佬帮助😁。

YYCoder avatar Mar 27 '22 06:03 YYCoder

我在用Nginx进行反向代理,遇到了类似的问题, 场景如下: 公网服务器部署NPS。家中内网电脑开启Stable Diffusion,并开启NPC, 外网通过域名访问Stable Diffusion,可以打开网页,但提示连接错误,且无法出图。 而通过域名:端口,或IP:端口访问却一切正常。

至此可确定必然为Nginx的锅。

这时打开浏览器的检查,看到控制台有如下输出: WebSocket connection to 'ws://xxx.xxx.com/queue/join' failed 显然,WebSocket未能被Nginx正常转发。 带着这个问题点去问ChatGPT,很容易就找到了对策:

server {
    listen 80;
    server_name xxx.xxx.com;

    location / {
        proxy_pass http://localhost:端口;
        # 重点在此后的三行配置
        # 这个指令确保使用HTTP/1.1通信,WebSocket需要HTTP/1.1来进行升级请求。
        proxy_http_version 1.1;
        # 这个指令将客户端请求的Upgrade头信息传递给后端服务器。WebSocket协议升级请求需要这个头信息。
        proxy_set_header Upgrade $http_upgrade;
        # 这个指令用于修改Connection头信息,告诉后端服务器客户端想要升级连接。确保将proxy_pass后面的URL替换为你的Stable Diffusion服务的实际内网IP地址和端口。
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

修改后,reload一下nginx即可

zuilintan avatar Feb 29 '24 16:02 zuilintan