配置 Apache2 来代理 WebSocket?

配置 Apache2 来代理 WebSocket?

WebSocket 协议是 HTTP 协议的扩展。但是 Apache2 的代理模块似乎不知道它的存在,因此会丢弃关键的标头,将调用转换为标准 HTTP 调用。

有没有办法让 Apache2 (1) 理解 WebSocket 或 (2) 简单地盲目地传递它所得到的一切?

答案1

Apache trunk 中现在有一个名为 mod_proxy_wstunnel 的模块,它允许 mod_proxy (ProxyPass/ProxyPassReverse) 通过 WebSocket 流量。有人写了一篇博客文章将 mod_proxy_wstunnel 移植到 Apache 2.4/2.2并提供了补丁来实现此目的。

我搞清楚了混凝土在 Ubuntu 上设置 mod_proxy_wstunnel 的说明(使用 Ubuntu Server 11.10 和 Apache 2.2.20 进行测试)并将它们发布在我的博客上。我已将它们复制如下:

# Check apache version (should be 2.2.20 as of writing, if not adjust the next step)
dpkg -s apache2

# Checkout apache source
svn checkout http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.20/ httpd-2.2.20

# Get patch and apply it
wget http://cafarelli.fr/gentoo/apache-2.2.24-wstunnel.patch
cd httpd-2.2.20
patch -p1 < ../apache-2.2.24-wstunnel.patch

# Build Apache 
svn co http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x srclib/apr
svn co http://svn.apache.org/repos/asf/apr/apr-util/branches/1.3.x srclib/apr-util
./buildconf
./configure --enable-proxy=shared --enable-proxy_wstunnel=shared
make

# Copy the module and recompiled mod_proxy (for new symbols) to the ubuntu apache installation and update the permissions to match the other modules
sudo cp modules/proxy/.libs/mod_proxy{_wstunnel,}.so /usr/lib/apache2/modules/
sudo chmod 644 /usr/lib/apache2/modules/mod_proxy{_wstunnel,}.so
echo -e "# Depends: proxy\nLoadModule proxy_wstunnel_module /usr/lib/apache2/modules/mod_proxy_wstunnel.so" | sudo tee -a /etc/apache2/mods-available/proxy_wstunnel.load

# Enable the module (also make any configuration changes you need)
sudo a2enmod proxy_wstunnel
sudo service apache2 restart

答案2

没什么可表明的Apache httpd 将很快支持它们。

如果你必须通过 apache 运行 websockets,请尝试mod_pywebsocket。我试过了,确实有效。

以下是我更喜欢的几个替代方案:

答案3

看起来,通过结合断开连接插件和一些额外的代码,现在可以实现这一点:

http://blog.alex.org.uk/2012/02/16/using-apache-websocket-to-proxy-tcp-connection/

答案4

这添加到@安德鲁·莫斯' 回答如何正确配置VirtualHost以使用 socket.io 1.0!请随意跳过有关 CentOS 的部分!


如果你被困在 CentOS 6 上,请按以下步骤操作:

  1. mod_proxy_wstunnel下载模块的反向移植源代码这里(克隆 Gist 或单独下载文件)
  2. 安装构建所需的一切:yum install make gcc httpd-devel
  3. 设置RPM 构建环境(基本上是非特权用户和一些目录)
  4. .c文件复制到SOURCES环境的子文件夹中,并将.spec文件复制到子文件夹中SPECS
  5. 跑步rpmbuild -ba mod_proxy_wstunnel.spec
  6. 该包现在位于SRPMS子文件夹中
  7. 安装软件包:rpm -i /path/to/package.rpm
  8. 利润

这也会自动加载 Apache 中的模块,因此您只需使用 重新启动它即可service httpd restart


在 Apache 2.2 上设置一个VirtualHost来实际服务 Socket.io 服务器和客户端脚本(默认情况下在 下可用http://your.server/socket.io/socket.io.js)稍微复杂一些,因为mod_proxy模块中的错误

鉴于以下重写规则:

RewriteRule    ^/ws(.*)$  ws://localhost:9000/ws  [P]

mod_rewrite将其视为文件路径,因此访问日志显示:

[26/Sep/2013:09:46:07 -0400] "GET /ws://localhost:9000/ws HTTP/1.1" 400 317

那么你不能ws在重写规则中使用 -protocol,因为这将在内部转变​​为 HTTP GET 请求。

不过有一个解决方法:

<VirtualHost *:80>
        ServerName your.server

        # Proxy socket.io Websocket
        RewriteEngine On

        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:8081/$1 [P]

        ProxyRequests Off

        # Explicitly send the request for the client-script to HTTP:
        ProxyPass /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js
        ProxyPassReverse /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js

        # Anything else goes to the WebSocket protocol:
        ProxyPass /socket.io/ ws://localhost:8081/socket.io/
        ProxyPassReverse /socket.io/ ws://localhost:8081/socket.io/

        # Any additional stuff (the actual site) comes here
        ProxyPass / http://localhost:8081/
        ProxyPassReverse / http://localhost:8081/
</VirtualHost>

这确保发送到的所有内容都/socket.io转到ws://协议,除了长轮询请求(当 WebSockets 不可用时,这是一种后备机制)和客户端库的请求。

相关内容