Securing Redis Traffic in HCL Connections with SSH Tunnels

Created:
Author: Christoph Stoettner
Read in about 6 min · 1108 words

Street photography

Photo by HY ART | Unsplash

At the moment I’m working with a customer to secure all traffic in HCL Connections. The target is to have only encrypted network traffic between servers.

Today I started enabling encryption to Redis. This is a documented process , but the documentation is outdated and incomplete.

Overview of the Solution

This guide explains how to secure Redis traffic using SSH tunnels between:

  1. WebSphere nodes and the HAProxy server
  2. HAProxy server and Kubernetes nodes

Redis Network drawing

Setting Up SSH Tunnels from WebSphere to HAProxy

One important deviation from the official documentation: we’ll create and use a dedicated unprivileged user account for our SSH tunnels instead of the documented root user. This follows security best practices by adhering to the principle of least privilege.

Instead of RSA encrypted keys, I recommend the more secure and easier to handle ed25519 algorithm.

Creating an Unprivileged User for SSH Tunnels

Run this on all WebSphere Nodes, the server hosting HAProxy, and all Kubernetes Nodes. Set a password for the created user:

adduser redis-tunnel-user
passwd redis-tunnel-user

Generate SSH Keys on WebSphere Nodes

On each WebSphere application server node:

su - redis-tunnel-user
mkdir ~/.ssh
chmod 700 ~/.ssh
cd ~/.ssh
ssh-keygen -t ed25519 -f tunnel -P '' -C "${USER}:$(hostname -s)"

Create an SSH key for each WebSphere node.

Generate SSH Keys on HAProxy Server

Create an SSH key on your HAProxy server:

su - redis-tunnel-user
mkdir ~/.ssh
chmod 700 ~/.ssh
cd ~/.ssh
ssh-keygen -t ed25519 -f tunnel -P '' -C "${USER}:$(hostname -s)"

Copy WebSphere Keys to HAProxy Server

Get the content of /home/redis-tunnel-user/.ssh/tunnel.pub from each WebSphere Node and copy it to /home/redis-tunnel-user/.ssh/authorized_keys on the HAProxy server. Or use ssh-copy-id to add the local key to the server users authorized_keys.

On each WebSphere node as user redis-tunnel-user (cnx8.stoeps.home is my load balancing server that hosts haproxy):

ssh-copy-id -i ~/.ssh/tunnel cnx8.stoeps.home

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/redis-tunnel-user/.ssh/tunnel.pub"
The authenticity of host 'cnx8.stoeps.home (10.0.22.80)' can't be established.
ED25519 key fingerprint is SHA256:TVXyu05rngd3mPH5S+twnzDzYbAVDQCUFldSltqOG9I.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
redis-tunnel-user@cnx8.stoeps.home's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'cnx8.stoeps.home'"
and check to make sure that only the key(s) you wanted were added.

Create Systemd Service for WebSphere Nodes

Create a systemd service to start and stop the tunnel on each WebSphere node:

  • /etc/systemd/system/redis-tunnel.service
[Unit]
Description=SSH tunnel to REDIS
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/ssh -i /home/redis-tunnel-user/.ssh/tunnel cnx8.stoeps.home -L 30379:127.0.0.1:30379 -N &
ExecStop=/usr/bin/pkill -f 'ssh -i /home/redis-tunnel-user/.ssh/tunnel cnx8.stoeps.home -L 30379:127.0.0.1:30379 -N'
Restart=always
RestartSec=30

User=redis-tunnel-user

[Install]
WantedBy=multi-user.target

Enable and start the service:

systemctl daemon-reload
systemctl enable --now redis-tunnel.service

Now you can manage the service with:

systemctl start redis-tunnel.service
systemctl stop redis-tunnel.service
systemctl status redis-tunnel.service

Configure Connections to Use the Tunnel

Tell Connections to use the tunnel by opening https://cnx8.stoeps.home/connections/config/highway.main.settings.tiles and changing c2.export.redis.host to localhost.

redis hostname

Restrict HAProxy to Local Connections

To ensure only the encrypted tunnel is used, modify /etc/haproxy/haproxy.cfg:

Change from:

frontend haproxy_redis
    bind *:30379
    mode tcp
    option tcplog

To:

frontend haproxy_redis
    bind 127.0.0.1:30379
    mode tcp
    option tcplog

This change limits the port to localhost/127.0.0.1, preventing any connection from outside the server.

Restart HAProxy:

systemctl restart haproxy

Setting Up SSH Tunnels from HAProxy to Kubernetes Nodes

At this point, we’ve secured the traffic between WebSphere nodes and the HAProxy server, but there’s still a security gap: the traffic from the loadbalancer to the Kubernetes nodes remains unencrypted and vulnerable. Now we’ll close this gap by establishing SSH tunnels from the HAProxy server to each Kubernetes node in the cluster.

Generate SSH Keys on HAProxy Server

Create an SSH key on the HAProxy server (if not already done):

su - redis-tunnel-user
mkdir ~/.ssh
chmod 700 ~/.ssh
cd ~/.ssh
ssh-keygen -t ed25519 -f tunnel -P '' -C "${USER}:$(hostname -s)"

Copy the key to all Kubernetes nodes:

ssh-copy-id -i ~/.ssh/tunnel cnx8-k8s-master.stoeps.home
ssh-copy-id -i ~/.ssh/tunnel cnx8-k8s-worker1.stoeps.home
ssh-copy-id -i ~/.ssh/tunnel cnx8-k8s-worker2.stoeps.home

Create Systemd Service on HAProxy Server

Create a systemd service on the loadbalancer/HAProxy server:

/etc/systemd/system/redis-tunnel.service

[Unit]
Description=SSH tunnels for Redis servers
After=network.target

[Service]
Type=simple
User=root

ExecStart=/bin/bash -c '/usr/bin/ssh -i /home/redis-tunnel-user/.ssh/tunnel cnx8-k8s-master.stoeps.home -L 30379:cnx8-k8s-master.stoeps.home:30379 -N & \
                        /usr/bin/ssh -i /home/redis-tunnel-user/.ssh/tunnel cnx8-k8s-worker1.stoeps.home -L 30380:cnx8-k8s-worker1.stoeps.home:30379 -N & \
                        /usr/bin/ssh -i /home/redis-tunnel-user/.ssh/tunnel cnx8-k8s-worker2.stoeps.home -L 30381:cnx8-k8s-worker2.stoeps.home:30379 -N & \
                        wait'
ExecStop=/bin/bash -c '/usr/bin/pkill -f "ssh -i /redis-tunnel-user/.ssh/tunnel cnx8-k8s-master.stoeps.home  -L 30379" ; \
                       /usr/bin/pkill -f "ssh -i /redis-tunnel-user/.ssh/tunnel cnx8-k8s-worker1.stoeps.home -L 30380" ; \
                       /usr/bin/pkill -f "ssh -i /redis-tunnel-user/.ssh/tunnel cnx8-k8s-worker2.stoeps.home -L 30381"'
Restart=always
RestartSec=30

User=redis-tunnel-user

[Install]
WantedBy=multi-user.target

Note: This uses three different local ports on the HAProxy server to open tunnels to each Kubernetes node.

Update HAProxy Configuration

Modify haproxy.cfg to use the local tunneled ports:

backend masters_redis
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 1000 maxqueue 1024 weight 100
        # server cnx8-k8s-master.stoeps.home cnx8-k8s-master.stoeps.home:30379 check
        # server cnx8-k8s-worker1.stoeps.home cnx8-k8s-worker1.stoeps.home:30379 check
        # server cnx8-k8s-worker2.stoeps.home cnx8-k8s-worker2.stoeps.home:30379 check
        server cnx8-k8s-master.stoeps.home  127.0.0.1:30379 check
        server cnx8-k8s-worker1.stoeps.home 127.0.0.1:30380 check
        server cnx8-k8s-worker2.stoeps.home 127.0.0.1:30381 check

Restart HAProxy and ensure the SSH tunnels from the WebSphere nodes are running.

Testing the Redis Connection

SSH into one of your WebSphere nodes and use telnet or netcat to connect to Redis:

dnf install netcat telnet
nc 127.0.0.1 30379
auth password
+OK
subscribe connections.events
*3
$9
subscribe
$18
connections.events
:1
telnet 127.0.0.1 30379
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
auth password
+OK
subscribe connections.events
*3
$9
subscribe
$18
connections.events
:1

Verify Connection with Connections UI

Open your Connections URL Top Updates (e.g., https://cnx8.stoeps.home/homepage/web/updates/#topUpdates/topUpdates/all )

Top Updates

The easiest way to see a working connection is to use the “Share something” box. You should see JSON data in the open Redis connection:

*3
$7
message
$18
connections.events
$1103

{
  "id":"9e1072d4-05d3-4bbb-9c3b-a8cb6c36eb30",
  "name":"community.calendar.membership.synchronized",
  "startTime":"1746471047358",
  "type":"UPDATE",
  "actor":{
    "id":"admin",
    "name":"Community Events Admin",
    "email":"null"
  },
  "object":{
    "id":"null",
    "name":"null",
...

Summary

While Redis offers TLS support , it needs to be built into the container. Since the container isn’t prepared for TLS, we use SSH tunnels as described in the documentation to encrypt server traffic.

The official documentation doesn’t mention HAProxy configuration changes for high availability or how to handle multiple Kubernetes hosts. It also uses outdated commands like /etc/init.d instead of systemd. Using systemd services instead of commands in /etc/rc.local is more reliable.

This guide provides a clearer, more complete process for securing Redis traffic in an HCL Connections environment with modern best practices.

Comments
Error
There was an error sending your comment, please try again.
Thank you!
Your comment has been submitted and will be published once it has been approved.
Success!
Your comment has been posted successfully.

Comments

Loading comments...

Leave a Comment

Your email address will not be published. Required fields are marked with *

Suggested Reading
Card image cap

Today I read the article KB0118248 and remembered my blog post from 2018 . I also checked the attached aha idea where a comment states that you can use iframe for Youtube. Despite what KB0118248 incorrectly states, it is absolutely possible to embed videos in HCL Connections blogs and wikis using the HTML video tag as demonstrated in this post.

Created:
Last Update:
Read in about 2 min
Card image cap

The HCL Connections documentation describes the process for configuring Windows desktop single-sign-on in a somewhat complicated way. Here are the necessary steps for setting up with the highest possible encryption.

Created:
Last Update:
Read in about 6 min
Card image cap

I haven’t touched the Connections scripts for a long time, but I recently made some minor updates to fix compatibility issues with newer versions and added small scripts to speed up configuration. I also got the documentation script running from the menu.

Created:
Last Update:
Read in about 2 min