# Handling web-Sockets in Apache, Nginx and Ha-proxy

WebSockets were introduced to open two-way interactive communication sessions, between a client and a server. This paved the way for event-driven responses, such as notifying a user of new content without refreshing the page.

## **Dealing with WebSockets - Apache**

Handling WebSockets in Apache Web Server 2.4 isn’t as straight forward as with other web servers. The Apache Config with a proxy pass will work most of the time

But when the web socket comes to picture, sometimes the site breaks in the browsers

In the below config we will assume you have already enabled proxy pass for a [website.](http://website.In) To enable WebSocket to reverse proxying, the Apache modules for handling such requests must be enabled.

### **Ubuntu**

If you are running Ubuntu 16.04 or higher, run the following commands to enable the modules.

```bash
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
```

it will ask you to restart apache2. do it.

```bash
systemctl restart apache2
```

### **CentOS 7**

The prerequisite modules are already enabled by default on a CentOS 7 install of httpd. Enabling and disabling these modules is done by editing a configuration file.

1. Open the module configuration file for proxies.  
    `sudo vi /etc/httpd/conf.modules.d/00-proxy.conf`
    
2. All modules related to proxying are listed in this configuration file. Verify that the following lines exist and are uncommented.  
    `LoadModule proxy_http_module modules/mod_proxy_http.so`  
    `LoadModule proxy_wstunnel modules/mod_proxy_wstunnel.so`
    
3. If you made any changes to the file, save them now.
    
4. Restart Apache Web Server to apply your changes.  
    `sudo systemctl restart httpd`
    

> *mod\_proxy = It provides support for the tunnelling of web socket connections to a backend websockets server. The connection is automatically upgraded to a websocket connection:*

Things to be considered

```plaintext
Upgrade: WebSocket

Connection: Upgrade
```

Proxying requests to a websockets server like [`echo.websocket.org`](http://echo.websocket.org) can be done using the [`ProxyPass`](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass) directive:

```plaintext
ProxyPass "/ws2/"  "ws://echo.websocket.org/"

ProxyPass "/wss2/" "wss://echo.websocket.org/"
```

Proxying both HTTP and websockets at the same time, with a specific set of URL's being websocket-only, can be done by specifying the websockets [`ProxyPass`](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypass) directive before the HTTP directive:

```plaintext
ProxyPassMatch  ^/(myApp/ws)$  ws://backend.example.com:9080/$1

ProxyPass / http://backend.example.com:9080/
```

Proxying both HTTP and websockets at the same time, where the websockets URL's are not websocket-only or not known in advance can be done by using the [`RewriteRule`](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule) directive to configure the websockets proxying:

```plaintext
ProxyPass / http://example.com:9080/

RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule  ^/?(.*) "ws://example.com:9080/$1" [P,L]
```

The web proxy port and host should be proper . add and save and restart httpd or Apache it should work properly

**Note** : if using proxy pass and websocket at same time  the rewrite directive should be below proxypass directive.

---

## **Dealing with Websockets - Nginx**

NGINX supports WebSocket by allowing a tunnel to be set up between a client and a backend server. For NGINX to send the Upgrade request from the client to the backend server, the `Upgrade` and `Connection` headers must be set explicitly, as in this example:-

```json
location /wsapp/ {
    proxy_pass http://wsbackend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}
```

You also need to enable Connection and http upgrade in http section

```json
http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
```

You may also need to configure a upstream as below

```json
upstream wsbackend {
        server 192.168.100.10:8010;
    }
```

8010 is port where ws is running

Reload nginx

```bash
systemctl reload nginx 
```

Once this is done, NGINX deals with this as a WebSocket connection.

Visit the [link](https://www.nginx.com/blog/websocket-nginx/) for more info on Nginx Document . It's pretty straight forward .

---

## **HAProxy & Websockets**

There are 2 protocols embedded in **websockets**:

1. HTTP: for the **websocket** setup
    
2. TCP: **websocket** data exchange
    

**HAProxy** must be able to support **websockets** on these two protocols without breaking the TCP connection at any time.  
There are 2 things to take care of:

1. being able to switch a connection from HTTP to TCP without breaking it
    
2. smartly manage timeouts for both protocols at the same time
    

Fortunately, **HAProxy** embeds all you need to load-balance properly **websockets** and can meet the 2 requirements above.  
It can even route regular HTTP traffic from **websocket** traffic to different backends and perform **websocket** aware health check (setup phase only).

![](https://blogs.q21.in/content/images/2023/01/Screenshot-from-2023-01-02-02-26-41.png align="left")

During the setup phase, **HAProxy** can work in HTTP mode, processing layer 7 information. It detects automatically the **Connection: Upgrade** exchange and is ready to switch to tunnel mode if the upgrade negotiation succeeds. During this phase, there are 3 timeouts involved:

1. **timeout client**: client inactivity
    
2. **timeout connect**: allowed TCP connection establishment time
    
3. **timeout server**: allowed time to the server to process the request
    

If everything goes well, the **websocket** is established, then **HAProxy** fails over to tunnel mode, no data is analyzed anymore (and anyway, **websocket** does not speak HTTP). There is a single timeout involved:

1. **timeout tunnel**: take precedence over client and server timeout
    
2. **timeout connect** is not used since the TCP connection is already established.
    

Just make sure You have a following section in ha proxy config.

```bash
  timeout client          25s
  timeout connect          5s
  timeout server          25s
  timeout tunnel        3600s
  timeout http-keep-alive  1s
  timeout http-request    15s
```

Happy Dealing with websockets .

If you find it usefull . Follow me on [github](https://github.com/yogeshgowdagr)
