Backport Websockets to Apache 2.2 (x86!)
Hello all – today’s post is on backporting Websockets to an ancient PE2650 running CentOS 6.6. Yup…i686 in all its glory. Read on for our solution!
The problem? We have a Shiny app that uses Websockets. But we are proxying access to the Shiny app (via the R Server) from a front-end Apache. And – as we all know – on CentOS standard yum repositories only go up to Apache 2.2 (2.2.15 currently). And Websockets is supported – via mod_proxy_wstunnel – only in Apache 2.4.
Hmmm. So what to do? Backport the fix in, of course!
Here are our steps:
- See following resources; we modify them heavily to meet our CentOS 6.6 i686 environment:
- http://serverfault.com/questions/290121/configuring-apache2-to-proxy-websocket
- https://issues.apache.org/bugzilla/show_bug.cgi?id=49053
-
Install Apache for CentOS:
sudo yum install httpd chkconfig httpd24-httpd on service httpd24-httpd start
Continue to the next step.
-
Install necessary packages to base CentOS and setup firewall to permit HTTPS. Note that we are *not* running as
root
:sudo yum install -y patch autoconf libtool sudo yum install -y httpd mod_ssl mod_proxy_html sudo iptables -I INPUT 2 -p tcp -m state --state NEW -m tcp \ -m multiport --dports 80,443 -m comment --comment "HTTP/HTTPS" -j ACCEPT sudo service iptables reload sudo service iptables save
Note that
libtool
is version 2.0 while Apache source (specifically,apr-utils
) was built forlibtool
version 1. We will address that problem below.On the firewall: Be sure to do the same for the VM Security Group if running virtually.
Continue to the next step.
-
Create the dev tree to do your work. We’re running our builds locally:
mkdir -p ~/proj/websockets cd ~/proj/websockets
Continue to the next step.
-
Download packages and patches to build Apache 2.2.15 (which matches the CentOS Apache distro):
wget https://archive.apache.org/dist/httpd/httpd-2.2.15.tar.gz wget https://archive.apache.org/dist/apr/apr-util-1.5.4.tar.gz wget https://archive.apache.org/dist/apr/apr-1.5.1.tar.gz wget http://people.apache.org/~rjung/patches/expat-libtool2.patch wget https://gist.github.com/vitkin/6661683/raw/873dd8b4de4ad1ff69757ffe48fc574374aedc57/apache-2.2-wstunnel.patch
Continue to the next step.
-
Extract files and apply patches:
tar zxf httpd-2.2.15.tar.gz cd httpd-2.2.15 patch -p1 -i ../apache-2.2-wstunnel.patch cd srclib/apr tar xzf ../../../apr-1.5.1.tar.gz cd ../apr-util/ tar xzf ../../../apr-util-1.5.4.tar.gz patch -p1 -i ../../../expat-libtool2.patch cd ../../..
Continue to the next step.
-
Configure and build system. Note we build all the dependent modules as our production environment requires them.
./buildconf ./configure --enable-proxy=shared --enable-proxy_ajp=shared \ --enable-proxy_balancer=shared --enable-proxy_connect=shared \ --enable-proxy_ftp=shared --enable-proxy_http=shared \ --enable-proxy_wstunnel=shared make
Continue to the next step.
-
Install the compiled mod_proxy over the base (saving the original for the first run). You can run these commands as-is any number of times.
[ ! -d /usr/lib/httpd/modules/bak ] && sudo mkdir /usr/lib/httpd/modules/bak l_lib=/usr/lib/httpd/modules; l_lib_loc=modules/proxy/.libs l_sos=''; for i in $(ls $l_lib_loc/*.so); do l_sos="$l_sos $(basename $i)"; done for i in $l_sos; do [ ! -f $l_lib/bak/$i ] && sudo cp $l_lib/$i $l_lib/bak/; done for i in $l_sos; do yes | sudo cp $l_lib_loc/$i $l_lib/; sudo chmod 755 $l_lib/$i; done
service httpd restart
Continue to the next step. -
Modify your Apache config file; here we create a new file to hold our Websockets process:
# /etc/httpd/conf.d/z-websockets-demo.conf LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so <VirtualHost *:80> ServerName websockets-demo.hlsdev.com ProxyRequests Off ProxyPreserveHost Off <Proxy *> Order allow,deny Allow from all </Proxy> # websockets? ProxyPassMatch ^/(.*/__sockjs__/[0-9]+/.*) ws://backend.example.local:3838/$1 ProxyPass / http://backend.example.local:3838/ max=1 disablereuse=on keepalive=on ProxyPassReverse / http://backend.example.local:3838/ CustomLog /var/log/httpd/demo.log combined ErrorLog /var/log/httpd/demo_error.log </VirtualHost>
In the above: the Websockets support is provided by two additional lines. The first line loads the Websockets Tunneling code (which is an add-on to standard ws-proxy module):
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
The second line performs the check for the “websocketized” application using the ProxyPassMatch command. The regular expression checks for __socksjs__ followed by an all-numeric identifier. If found, then the proxy will send the request to the “ws://” destination, which automagically invokes the ws_tunnel code.
Continue to the next step.
That is all. The proxy now works.
Leave a Reply