A lightweight, high-performance multi-threaded TCP/UDP packet proxy written in Erlang with WebSocket support.
VeilLink is a simple yet powerful packet forwarding proxy that leverages Erlang's concurrency model to handle multiple simultaneous connections efficiently. Each proxy rule runs in its own process, and each client connection spawns dedicated forwarding processes for bidirectional data transfer.
- Multi-threaded Architecture: Each listening port and connection runs in separate Erlang processes
- TCP & UDP Support: Forward both TCP and UDP traffic with protocol-specific handling
- Bidirectional Forwarding: Full-duplex data transfer between client and destination
- CSV Configuration: Simple, human-readable configuration file
- WebSocket Compatible: Raw packet forwarding supports WebSocket and other TCP protocols
- Game Server Support: UDP forwarding works with game protocols (e.g., Minecraft Bedrock, voice chat)
- Concurrent Connections: Handle multiple clients per port simultaneously
- Low Latency: Direct packet forwarding with minimal overhead
- Erlang/OTP (any recent version)
- Clone the repository:
git clone https://github.com/bradyhodge/veilLink.git
cd veillink- Compile the module:
erlc main.erlCreate a config.csv file in the same directory as the executable with the following format:
<protocol>,<listen_port>,<forward_ip>,<forward_port>The protocol field accepts tcp or udp (case-insensitive).
tcp,8080,192.168.1.100,80
tcp,8443,example.com,443
udp,19132,10.0.0.5,19132
udp,5353,8.8.8.8,53This configuration will:
- Forward TCP traffic from local port 8080 to 192.168.1.100:80
- Forward TCP traffic from local port 8443 to example.com:443
- Forward UDP traffic from local port 19132 to 10.0.0.5:19132
- Forward UDP traffic from local port 5353 to 8.8.8.8:53
The legacy 3-column format is still supported and defaults to TCP:
8080,192.168.1.100,80erl -noshell -s main startOr from the Erlang shell:
c(main).
main:start().Press Ctrl+C twice or use:
init:stop().- Configuration Loading: Reads
config.csvand parses proxy rules - Listener Processes: Spawns a listener process for each configured port
- Connection Handling: When a client connects, spawns a new process to handle that connection
- Bidirectional Forwarding: Creates two processes per connection:
- One for client → server traffic
- One for server → client traffic
- Automatic Cleanup: Closes sockets when either end disconnects
- Listener Process: Opens a UDP socket and listens for datagrams
- Client Tracking: Uses ETS tables to track client addresses and their associated forward handlers
- Per-Client Handlers: Each unique client (IP:port) gets a dedicated handler process with its own forward socket
- Response Routing: Responses from the destination are automatically routed back to the correct client
- Idle Timeout: UDP handlers automatically clean up after 5 minutes of inactivity
- Reverse Proxy: Route traffic to backend services
- WebSocket Proxy: Forward WebSocket connections transparently
- Game Server Proxy: Forward Minecraft Bedrock, voice chat, and other UDP-based game traffic
- DNS Forwarding: Redirect DNS queries to custom resolvers
- Port Forwarding: Expose services on different ports
- Development: Test applications behind a proxy
- Load Distribution: Combine with DNS or external load balancers
VeilLink is built on Erlang's lightweight process model:
- Minimal memory footprint per connection
- Efficient message passing between processes
- Handles thousands of concurrent connections
- Non-blocking I/O operations
- UDP handlers automatically expire after idle timeout
- Invalid configuration entries are skipped
- Connection failures are logged to stdout
- Socket errors trigger automatic cleanup
- Failed listeners are reported but don't stop other ports
- UDP client mappings are cleaned up on handler exit
- No SSL/TLS termination (transparent proxy only)
- No load balancing between multiple backends
- No connection pooling or rate limiting
- Configuration requires restart to update
- UDP idle timeout is fixed at 5 minutes
Contributions are welcome! Please feel free to submit issues or pull requests.