[Docker image] | [About project]
Event proxy system receiving events from a fake SMTP server (on the local network), parsing them and sending them via real-time communication channels (SSE). It also includes a simple REST client with CRUD operations and desktop application receiving these events from multiple proxy servers.
Build with Lightweight embed Jetty servlet container, Java raw TCP sockets and Electron with React (client app).
- Basic concept
- Demo (desktop app)
- In-transit envelope encryption
- JVM memory footprint
- Clone, and run server
- Run client in development environment
- Package client (create executables)
- Disclaimer
- Tech stack
- Author
- License
The core concept involves a fully isolated local network (e.g., 192.168.X.X) containing a mock SMTP proxy server that receives events from internal devices, such as a DVR. Data from this server is stored in a database and delivered to clients via a secure Cloudflare tunnel, which removes the need for risky port forwarding. Furthermore, messages are End-to-End encrypted, ensuring that no one, not even Cloudflare's edge servers, can decrypt the content.
Server does not contain complex and heavyweight frameworks (like Spring, Spring Boot) and is built on a pure Jetty server to achieve the smallest possible memory footprint.
event-proxy-client-demo.mp4
Main features:
- connecting to multiple event proxy servers simultaneously
- real-time event streaming (SSE) from all servers at once
- fetching historical data and managing event archives
- advanced event management via an intuitive data table with full keyboard shortcut and arrow-key support
- automatic reconnection logic (optimized for Zero Trust tunnels and connection drops)
- comprehensive notification system including system tray integration and audio alerts
The key principle of this architecture is strict isolation: the Renderer (UI) process is completely separate from the Main process, which solely manages cryptography. It implements envelope encryption, which is a strategy of encrypting data with a symmetric key (AES) that is then encrypted with an asymmetric key (RSA).
- The Main process sends an RSA public key to the proxy server during authentication.
- The trusted server verifies the credentials, creates an AES session key, persists it, and sends it back encrypted with the client's public key.
- When data is requested, the server uses the persisted AES key in AES-GCM mode. This mode, in addition to the ciphertext, generates a unique nonce and an Authentication Tag (tag), which mitigates the risk of data tampering (like bit-flipping attacks) by intermediaries, ensuring payload integrity.
- The client's Main process receives the packet (ciphertext, nonce, tag), decrypts the AES key, and then uses it to decrypt the data while simultaneously verifying its authenticity using the tag.
- Finally, the plaintext (decrypted) data is sent to the Renderer via the IPC tunnel.
The following comparison was conducted with both applications in an idle state, without any active SSE connections or incoming requests. The benchmark baseline is a standard Spring Boot installation including the spring-boot-starter-web and spring-boot-starter-jdbc dependency.
Heap size: 256MB
| Event proxy server | Blank Spring Boot application |
|---|---|
| Peak (min): ~8MB, (max): ~60MB | Peak (min): ~16MB, (max): ~140MB |
![]() |
![]() |
- Clone repository on your local machine via:
$ git clone https://github.com/milosz08/event-proxy-system- Build server:
$ ./mvnw clean package -pl event-proxy-server- Run server in your local network area (on Raspberry Pi or other device with JVM 21):
$ java -Xms=128m -Xmx=128m -jar event-proxy-server.jar- Alternatively, get server from DockerHub repository and run it using
docker-compose.ymlfile (check docker README) or build and run with docker locally:
$ docker compose up -d- Make sure you have the latest LTS Node and yarn (if you do not have yarn, you can install it via
npm i -g yarn). - Go to
event-desktop-clientand install dependencies via:
$ cd event-desktop-client
$ yarn install --frozen-lockfile- To run client in development mode (with hot-reload), type:
$ yarn run dev:watchAlternatively you can use prepared Intellij run configuration (in .run directory).
Note
To build an executable package for a specific operating system, you must run the build process on that exact system:
- building
.dmg(macOS): You must runyarn run build:macon a computer running macOS, - building
.msi(Windows): You must runyarn run build:winon a computer running Windows, - building
.AppImage(Linux): You must runyarn run build:linuxon a Linux distribution.
Run platform dependent build via:
$ ./mvnw clean package -pl event-desktop-clientoutput binary files you will find in event-desktop-client/dist
This software is provided "as is", without any warranty. You use it at your own risk, and the author is not responsible for any damages resulting from its use.
- Java 17, Jakarta EE (servlets),
- JCA, JCE (crypto),
- Eclipse Jetty embeddable server,
- JDBC, SQLite JDBC, SQLite database,
- Jakarta Mail,
- BCrypt,
- Electron with React (Vite), BlueprintJS, styled components.
Created by Miłosz Gilga. If you have any questions about this software, send message: miloszgilga@gmail.com.
This project is licensed under the Apache 2.0 License.

