Running Pixelflut in a restricted network

13.05.2023 Infrastructure Pixelflut Network Firewall SSH

The last week, our company organized their annual internal education conference where we reside at a conference hotel and learn from each other with talks, workshops, and so on. For entertainment, I wanted to set up Pixelflut (English: Pixelflood), an application where participants can send single pixels via a network to a publicly viewable projector. Here is how I bypassed some restrictions of the hotel network.

The Pixelflut protocol

First of all - what is Pixelflut? It is a quite simple protocol to send single pixels to a projector. It was nice to see how participants figured out a lot of ways to send whole images to Pixelflut - someone even managed to animate a DVD logo bouncing off the edges of the screen!

You can learn the basic protocol by sending HELP to Pixelflut:

$ echo "HELP" | nc domain.tld 1337
HELP Commands:
HELP  SIZE
HELP  PX <x> <y>
HELP  PX <x> <y> <rrggbb[aa]>

The problem

Just plugging a computer running Pixelflut into a power outlet and connecting it to the projector and the hotel network would have been simple. But inside this network, there are no static IP addresses. And I did not want to bother hotel staff with a request for a static hostname. So - how to make Pixelflut accessible by a unique hostname in the hotel network?

The tunnel solution

With my personal server setup, I am already using SSH tunnels. SSH is a quite powerful, yet simple, protocol to securely connect machines in the internet.

DNS configuration

The first part - the name - is quite simple. I already operate a few servers with some domains. So I created a DNS entry like pixelflut.domain.tld and pointed a CNAME record to one of my servers.

SSH configuration

But how to get traffic from my server to the local Pixelflut installation? I mean - the hotel surely has a firewall in place? Luckily, SSH offers the benefit of TCP port forwarding. With remote port forwarding, a local SSH client can offer one of its local ports to a remote server. And as a bonus, it can even expose the remote port on the server publicly.

To protect this setup in terms of security - I didn’t want to leave an SSH private key to my server on an unlocked and unattended notebook - I created a new user on the server:

$ sudo useradd pixelflut

I created a new SSH keypair, of which I added the public key to the new user’s home directory. In the server’s /etc/ssh/sshd_config, I added the following lines to restrict the SSH user to only allow forwarding of the TCP port 1337:

Match User pixelflut
   ClientAliveInterval 60
   ClientAliveCountMax 10
   AllowTcpForwarding yes
   GatewayPorts yes
   X11Forwarding no
   AllowAgentForwarding no
   PermitOpen localhost:1337
   ForceCommand echo 'This account can only be used for pixelflut.'

A little modification is also needed on the client side SSH config in order to keep the tunnel open reliably:

ServerAliveInterval 60
ServerAliveCountMax 10

Of course, we would need to open port 1337 in the server’s UFW firewall:

$ sudo ufw allow 1337/tcp  

Start Pixelflut

Now I can start Pixelflut on the notebook connected to the projector:

$ java -jar pixelwar-0.0.1-SNAPSHOT-jar-with-dependencies.jar

I am actually using the Pixelwar application here, as it served the best compatibility for current systems. Pixelwar will listen on the local TCP port 8080.

After that, I open the SSH tunnel from the Pixelflut notebook:

$ ssh -N -R 1337:localhost:8080 -i id_ed25519_pixelflut pixelflut@domain.tld

Overview

pixelflut-network.png

And that’s it! Pixelflut was available via pixelflut.domain.tld the entire two and a half days at the hotel. And it was very well received! The article image at the top is one of the created images.