我正在设置我的第一个 HAProxy 反向代理服务器。它将成为从不同服务器在 tomcat 上运行的 HTML5 应用程序的代理。我能够让它通过 HTTP 代理出去,将所有请求重定向到 HTTPS,并实现 HSTS。但是,这样做之后我意识到它也尝试加载 websocket 连接。问题是它加载的 websocket 连接是不安全的 (ws://) 和不安全的 (wss://)。当然,Chrome(可能还有多个浏览器)会抱怨通过安全连接加载不安全的脚本。这是我得到的错误:
Connecting via WebSocket using url ws://website.domain.com:9091/webclient/
Mixed Content: The page at 'https://website.domain.com/webclient/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://website.domain.com:9091/webclient/'. This request has been blocked; this endpoint must be available over WSS.
Caught WebSocket error: SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
Run Code Online (Sandbox Code Playgroud)
所有这些都由 /webclient/script/ajaxclient.js:210 …
对于目标100K并发 websocket 连接,建议使用什么nginx或haproxy设置?我认为,单个 nginx 将无法承受这样的流量以及并发连接。应该如何拆分到 nginx/haproxy 的流量(DNS lvl 或任何可用的 Amazon/Google 选项)?单个 nginx 能够处理多少并发 websocket?
尝试从谷歌搜索和 SO 帖子中收集相关信息。
基于我在 nginx 网站 https://www.nginx.com/blog/websocket-nginx/上读到的内容
他们给出的示例将关闭与后端的所有连接。这并不是我们真正想要的代理设置,强制在每个新客户端上重新打开与后端的连接。
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 192.168.100.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是升级到websocket后是否需要关闭连接呢?
我们不能更改地图以使其保持与后端的“保持活动”连接吗?(对于所有非 websocket 请求)
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 192.168.100.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; …Run Code Online (Sandbox Code Playgroud) 无法让 wss:// (或 ws://) 在我的 Digital Ocean、使用 nginx 的 Ubuntu 服务器上工作,不断收到 301 重定向并且没有连接。
Websocket服务器:node + express + uws在http://localhost:3000/chat上提供服务(我已经通过在ufw中打开3000并直接与ws://连接进行了测试,工作正常。)
操作系统:Ubuntu 16.04.3 x64
这是我的 nginx 配置(我尝试了很多变体和选项,这是最简单的,老实说这似乎并不重要)
server {
listen 443 ssl; # client_wss_port
server_name www.example.org;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
location /chat/ {
add_header locationischat 1; # this is a dummy header for debugging
proxy_pass http://localhost:3000/chat/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的 nginx 版本
nginx -v
nginx version: nginx/1.10.3 (Ubuntu)
Run Code Online (Sandbox Code Playgroud)
这是我的防火墙状态
ufw status
Status: …Run Code Online (Sandbox Code Playgroud) 我的机器上设置了两个 nginx 代理,一个用于解包 SSL,另一个用于执行特定于应用程序的代理(只有第二个是版本控制的)。当我只有一个代理时,我能够成功建立 Websocket 连接,但在转移到两个代理后,所有 Websocket 升级请求都会响应 502 Bad Gateway 错误。我可以确认正常的 http/https 请求适用于我的双代理设置。这是我当前的配置。
代理1
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf; …Run Code Online (Sandbox Code Playgroud) 在 CentOS 7 Linux 上,我在通过 FastCGI 为 Wordpress 站点提供服务的Jetty 9前面成功使用了 HAProxy 1.5.14 。
它工作得非常好,但是对于同一网站上的 HTML5/WebSocket 游戏,WebSocket 连接到/ws/URL 的客户端和服务器超时需要更高的时间。
所以我将/etc/haproxy/haproxy.cfg文件修改为以下内容:
global
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
tune.ssl.default-dh-param 2048
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m # HOW TO INCREASE FOR /ws/ ?
timeout …Run Code Online (Sandbox Code Playgroud) 我在 Ubuntu 14.04 LTS 上运行 Apache 2.4.7 作为反向代理。这个 Apache 服务器充当许多不同后端应用程序的入口点,这些应用程序通过<Location>块中不同的 mod_proxy 配置进行访问
我需要提供对使用 WebSocket 的应用程序的反向代理访问。该应用程序是一个 Java Spring 应用程序,它通过 HTTP 提供 HTML 和其他静态文件,然后在页面加载后使用 WebSocket 获取动态数据。
我已经Nginx使用以下配置运行了应用程序:
location /newapp/ {
proxy_pass http://newapp.example.com:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于需要一个在 Nginx 上不可用的 Apache 身份验证模块,我无法在生产中使用它。
我想要做的是,在伪 Apache-config 中:
<Location /newapp/>
if not WebSockets:
ProxyPass http://newapp.example.com:8080/
ProxyPassReverse /
else
ProxyPass ws://newapp.example.com:8080/
ProxyPassReverse /
</Location>
Run Code Online (Sandbox Code Playgroud)
Apachemod_proxy_wstunnel模块让我觉得这应该是可能的。WebSocket 是在 URL 上访问的/api/socket/...,因此我尝试将ProxyPass使用单独<Location>块的两种类型分开:
<Location /newapp/> …Run Code Online (Sandbox Code Playgroud) 尝试使用 apache2 设置 websocket 代理,出现以下错误:
没有协议处理程序对 URL /(方案“ws”)有效。如果您使用的是 mod_proxy 的 DSO 版本,请确保使用 LoadModule 将代理子模块包含在配置中
apache服务器的wstunnel模块已加载。以下是结果apache2ctl -M
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
unixd_module (static)
access_compat_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_core_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
filter_module (shared)
headers_module (shared)
mime_module (shared)
mpm_prefork_module (shared)
negotiation_module (shared)
php7_module (shared)
proxy_module (shared)
proxy_connect_module (shared)
proxy_fcgi_module (shared)
proxy_html_module (shared)
proxy_http_module …Run Code Online (Sandbox Code Playgroud) 我有一个在端口 3000 上的 HTTP 服务器上运行的 Web 应用程序。该应用程序连接到端口 9001 上的 websocket 服务器。WS 和 HTTP 服务器都位于同一虚拟机内。
在本地测试应用程序(在虚拟机内)时,一切正常。Web 应用程序和 WS 服务器都可以相互通信。应用程序和服务器都侦听本地主机上的连接,如下所示:
网络应用程序(ReactJS):const sock = new WebSocket('ws://localhost:9001/');
WS 服务器(Python):ws = WebsocketServer(host='127.0.0.1', port=9001)
当将此设置为允许外部连接时,Web 应用程序和 WS 服务器无法再进行通信。服务器仍在侦听 上的连接host='127.0.0.1'。Web 应用程序前端代码已更改为连接到运行 VM 的计算机(假设123.45.67.890):
网络应用程序(ReactJS):const sock = new WebSocket('ws://123.45.67.890:9001/');
我为端口 3000 和 9001 启用了端口转发,并从虚拟机内部禁用了这两个端口上的防火墙。主机上的两个端口均已打开。
我可以使用从外部访问 Web 应用程序123.45.67.890:3000,因此我非常确定与虚拟机的连接已打开。但是,Web 应用程序无法在端口 9001 上与 WS 服务器进行通信。您知道这可能是什么原因吗?
以防万一操作系统信息有帮助:
虚拟主机:Microsoft Windows 7 Enterprise (6.1.7601 Service Pack 1 Build 7601)
虚拟机访客:CentOS Linux release 7.4.1708 …
windows-server-2008 firewall virtual-machines port-forwarding websocket
我目前有一个 Apache2 监听端口 80,还有一个自制的游戏服务器在更高的未注册端口 (50214) 上运行。我用 Javascript 重写了游戏,并计划通过端口 80 上的 websockets 发送网络通信,以绕过许多公司和大学设置的防火墙。
我将如何配置 websocket 服务器以侦听 80 上的 websocket 连接,并将它们解包并将它们转发到侦听 50214 的游戏服务器,而不会干扰 apache?
我应该使用什么 websocket 服务器实现?这通常是如何完成的?
我知道有一个 ALB 和 NLB 选项可与 websocket 一起使用。我不明白为什么带有 HTTP 协议的经典 ELB 不适用于 websocket 连接,尽管在实例中 Nginx 配置为添加连接和升级标头。一旦我将其切换到 TCP 协议,它就可以工作了。你能解释一下当中间有 HTTP 代理时这个协议到底是如何工作的吗?
它仍然使用相同的 TCP,一旦客户端到达服务器并且 Nginx 添加了升级标头,带有切换协议消息的服务器响应应该到达客户端,然后它们只使用已建立的 HTTP 连接的 TCP。它丢弃 ELB 上的此连接、响应缓冲或只是丢弃所有非 HTTP 流量的原因是什么?
所以Nginx发送到ELB
HTTP/1.1 101 Switching Protocols
Server: nginx/1.13.1
Date: Sat, 21 Mar 2020 07:53:38 GMT
Connection: upgrade
Upgrade: websocket
Sec-WebSocket-Accept: PozdkhgL/Zdkgh3kwu0KkACFCt0=
Run Code Online (Sandbox Code Playgroud)
但是ELB从来没有将其返回给客户端,并且请求超时。
proxy load-balancing amazon-web-services amazon-elb websocket
websocket ×11
nginx ×4
haproxy ×3
apache-2.4 ×2
mod-proxy ×2
wss ×2
amazon-elb ×1
apache-2.2 ×1
firewall ×1
proxy ×1
ssl ×1
timeout ×1