Added multi server support
This commit is contained in:
@@ -1,75 +1,95 @@
|
||||
# DirtSimpleP2P
|
||||
|
||||
DirtSimpleP2P lets a public Bungee/Waterfall proxy reach a Paper/Spigot server that is running at home behind NAT.
|
||||
DirtSimpleP2P is a Minecraft networking plugin that lets a public BungeeCord or Waterfall proxy reach backend Paper/Spigot servers that are behind NAT.
|
||||
|
||||
You do not need to open the Minecraft port on your home router. The backend server connects outbound to your public proxy/VPS, then Minecraft traffic is carried through that tunnel.
|
||||
It is designed for server owners who want to host a backend Minecraft server at home or on a private network without opening the backend Minecraft port on their router.
|
||||
|
||||
## What You Get
|
||||
The backend server connects outbound to the public proxy. Bungee/Waterfall then connects to a local port on the proxy machine, and DirtSimpleP2P carries the Minecraft TCP connection through the tunnel.
|
||||
|
||||
- One jar file for both servers
|
||||
- No home router port forwarding
|
||||
- Works with a public Bungee/Waterfall proxy
|
||||
- Works with a backend Paper/Spigot server
|
||||
## Features
|
||||
|
||||
- One jar for both the proxy and backend server
|
||||
- No home router port forwarding for backend Minecraft servers
|
||||
- NAT-safe outbound tunnel from backend to proxy
|
||||
- Multiple simultaneous Minecraft player connections
|
||||
- Multiplexed framed TCP protocol
|
||||
- Secret-token authentication
|
||||
- Automatic secret-token generation
|
||||
- Optional TLS encryption with generated self-signed certificates
|
||||
- Multiple Minecraft player connections over one tunnel
|
||||
- Fast reconnect with heartbeat-based latency tolerance
|
||||
- Automatic token generation
|
||||
- Optional TLS encryption
|
||||
- Self-signed TLS certificate generation
|
||||
- TLS certificate pinning on backend servers
|
||||
- Fast reconnect with heartbeat checks
|
||||
- Multiple public proxies can connect to one backend
|
||||
- One proxy can expose multiple named backend servers
|
||||
- `/dsp2p status` and `/dsp2p doctor` commands
|
||||
- Simple properties config files
|
||||
- Simple `config.properties` setup
|
||||
|
||||
## Current Status
|
||||
## Requirements
|
||||
|
||||
This is still a development build, not a paid release build yet.
|
||||
- Java 21
|
||||
- Maven 3.8+
|
||||
- BungeeCord or Waterfall for the public proxy side
|
||||
- Paper or Spigot for the backend server side
|
||||
|
||||
The tunnel core exists and the plugin jar builds. TLS can now generate a self-signed certificate when enabled, but before paid release it should get more real-world testing on actual Bungee and Paper servers.
|
||||
## How It Works
|
||||
|
||||
## Build The Jar
|
||||
Normal Minecraft proxy setup expects Bungee/Waterfall to connect directly to a backend server.
|
||||
|
||||
From this project folder, run:
|
||||
That does not work well when the backend server is at home behind NAT, unless you forward ports on the home router.
|
||||
|
||||
DirtSimpleP2P avoids that:
|
||||
|
||||
1. The proxy server runs DirtSimpleP2P in `frontend` mode.
|
||||
2. The backend server runs DirtSimpleP2P in `backend` mode.
|
||||
3. The backend opens an outbound tunnel to the public proxy.
|
||||
4. The proxy exposes a local port such as `127.0.0.1:25566`.
|
||||
5. Bungee/Waterfall sends players to that local port.
|
||||
6. DirtSimpleP2P carries the TCP traffic through the tunnel to the backend server.
|
||||
|
||||
The public proxy needs an open tunnel port. The home/backend router does not need a Minecraft port forward.
|
||||
|
||||
## Build
|
||||
|
||||
From the project folder:
|
||||
|
||||
```bash
|
||||
mvn clean package
|
||||
```
|
||||
|
||||
The plugin jar will be here:
|
||||
The plugin jar is created at:
|
||||
|
||||
```bash
|
||||
plugin/target/DirtSimpleP2P-0.1.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Use this same jar on both servers.
|
||||
Use this same jar on both the proxy and backend server.
|
||||
|
||||
## Basic Setup
|
||||
|
||||
You need two Minecraft-side servers:
|
||||
You need:
|
||||
|
||||
- Public proxy server: BungeeCord, Waterfall, or another Bungee-compatible proxy
|
||||
- Backend server: Paper or Spigot
|
||||
- A public BungeeCord/Waterfall proxy, usually on a VPS
|
||||
- A backend Paper/Spigot server, which can be at home or on a private network
|
||||
|
||||
The public proxy is usually on a VPS. The backend server can be at home.
|
||||
### 1. Install On The Proxy
|
||||
|
||||
## Step 1: Install On Bungee
|
||||
Put the jar in your BungeeCord/Waterfall `plugins` folder:
|
||||
|
||||
Put this jar in your Bungee/Waterfall `plugins` folder:
|
||||
|
||||
```bash
|
||||
```text
|
||||
DirtSimpleP2P-0.1.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Start the proxy once, then stop it.
|
||||
|
||||
DirtSimpleP2P will create:
|
||||
DirtSimpleP2P creates:
|
||||
|
||||
```bash
|
||||
```text
|
||||
plugins/DirtSimpleP2P/config.properties
|
||||
```
|
||||
|
||||
Open that file.
|
||||
### 2. Configure The Proxy
|
||||
|
||||
## Step 2: Configure Bungee
|
||||
|
||||
On the Bungee/proxy server, use:
|
||||
Use this on the BungeeCord/Waterfall side:
|
||||
|
||||
```properties
|
||||
role=frontend
|
||||
@@ -96,70 +116,57 @@ tunnel.tls.requireClientAuth=false
|
||||
routes=minecraft
|
||||
route.minecraft.frontendBindHost=127.0.0.1
|
||||
route.minecraft.frontendBindPort=25566
|
||||
route.minecraft.backendNode=paper-backend
|
||||
```
|
||||
|
||||
Change:
|
||||
Notes:
|
||||
|
||||
- `tunnel.listenPort` only if port `24445` is already used
|
||||
- `tunnel.listenPort` is the public tunnel port that the backend connects to.
|
||||
- `tunnel.authToken` is generated automatically on first start.
|
||||
- Copy the generated token to the backend config.
|
||||
- `route.minecraft.frontendBindPort` is the local port Bungee/Waterfall should use for this backend.
|
||||
- `route.minecraft.backendNode` must match the backend server's `node.name`.
|
||||
|
||||
The plugin automatically generates `tunnel.authToken` on first start.
|
||||
### 3. Point Bungee/Waterfall At The Local Tunnel
|
||||
|
||||
Copy the generated Bungee token into the backend server config. The token must match on both sides.
|
||||
|
||||
To enable TLS on Bungee, change:
|
||||
|
||||
```properties
|
||||
tunnel.tls.enabled=true
|
||||
tunnel.tls.allowInsecure=false
|
||||
```
|
||||
|
||||
When Bungee starts, DirtSimpleP2P will generate:
|
||||
|
||||
```text
|
||||
plugins/DirtSimpleP2P/certs/frontend.p12
|
||||
```
|
||||
|
||||
It will also fill in `tunnel.tls.keyStorePassword` if that value is blank.
|
||||
|
||||
## Step 3: Point Bungee At The Local Tunnel
|
||||
|
||||
In your Bungee server config, set the backend server address to:
|
||||
In your BungeeCord/Waterfall server config, set the backend address to:
|
||||
|
||||
```text
|
||||
127.0.0.1:25566
|
||||
```
|
||||
|
||||
That is not your home server IP. DirtSimpleP2P listens there locally on the proxy server.
|
||||
Do not put your home server IP in the Bungee/Waterfall config. Bungee connects locally, and DirtSimpleP2P carries the traffic through the tunnel.
|
||||
|
||||
## Step 4: Install On Paper Or Spigot
|
||||
### 4. Install On The Backend
|
||||
|
||||
Put the same jar in your backend Minecraft server `plugins` folder:
|
||||
Put the same jar in your Paper/Spigot `plugins` folder:
|
||||
|
||||
```bash
|
||||
```text
|
||||
DirtSimpleP2P-0.1.0-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
Start the backend server once, then stop it.
|
||||
|
||||
DirtSimpleP2P will create:
|
||||
DirtSimpleP2P creates:
|
||||
|
||||
```bash
|
||||
```text
|
||||
plugins/DirtSimpleP2P/config.properties
|
||||
```
|
||||
|
||||
Open that file.
|
||||
### 5. Configure The Backend
|
||||
|
||||
## Step 5: Configure Paper Or Spigot
|
||||
|
||||
On the backend server, use:
|
||||
Use this on the Paper/Spigot side:
|
||||
|
||||
```properties
|
||||
role=backend
|
||||
node.name=paper-backend
|
||||
|
||||
tunnel.connectHost=YOUR_BUNGEE_OR_VPS_IP
|
||||
tunnel.connectPort=24445
|
||||
tunnel.authToken=PASTE_THE_BUNGEE_TOKEN_HERE
|
||||
frontends=proxy1
|
||||
frontend.proxy1.connectHost=YOUR_PROXY_IP_OR_DOMAIN
|
||||
frontend.proxy1.connectPort=24445
|
||||
frontend.proxy1.tls.pinnedCertificateSha256=
|
||||
|
||||
tunnel.authToken=PASTE_THE_PROXY_TOKEN_HERE
|
||||
|
||||
tunnel.connectTimeoutMillis=5000
|
||||
tunnel.heartbeatIntervalMillis=2000
|
||||
@@ -171,7 +178,6 @@ tunnel.reconnectMaxMillis=10000
|
||||
tunnel.tls.enabled=false
|
||||
tunnel.tls.allowInsecure=true
|
||||
tunnel.tls.trustOnFirstUse=true
|
||||
tunnel.tls.pinnedCertificateSha256=
|
||||
|
||||
routes=minecraft
|
||||
route.minecraft.backendTargetHost=127.0.0.1
|
||||
@@ -180,58 +186,167 @@ route.minecraft.backendTargetPort=25565
|
||||
|
||||
Change:
|
||||
|
||||
- `tunnel.connectHost` to your public proxy/VPS IP or domain name
|
||||
- `tunnel.authToken` to the same secret used on Bungee
|
||||
- `route.minecraft.backendTargetPort` if your backend Minecraft server is not on `25565`
|
||||
- `frontend.proxy1.connectHost` to your public proxy IP or domain
|
||||
- `frontend.proxy1.connectPort` to the proxy `tunnel.listenPort`
|
||||
- `tunnel.authToken` to the token from the proxy config
|
||||
- `route.minecraft.backendTargetPort` if your Paper/Spigot server is not listening on `25565`
|
||||
|
||||
Do not put your home IP in the Bungee config. The backend connects out to the proxy.
|
||||
### 6. Start Everything
|
||||
|
||||
To enable TLS on Paper/Spigot, change:
|
||||
Start the public proxy first.
|
||||
|
||||
Then start the backend Paper/Spigot server.
|
||||
|
||||
If the tunnel connects, the proxy log should show that a backend authenticated. Players connect to your normal public proxy address.
|
||||
|
||||
## TLS
|
||||
|
||||
TLS is optional, but recommended for real deployments.
|
||||
|
||||
On the proxy:
|
||||
|
||||
```properties
|
||||
tunnel.tls.enabled=true
|
||||
tunnel.tls.allowInsecure=false
|
||||
tunnel.tls.autoGenerate=true
|
||||
```
|
||||
|
||||
Leave this enabled for the easiest setup:
|
||||
When TLS is enabled, the proxy can generate:
|
||||
|
||||
```text
|
||||
plugins/DirtSimpleP2P/certs/frontend.p12
|
||||
```
|
||||
|
||||
On the backend:
|
||||
|
||||
```properties
|
||||
tunnel.tls.enabled=true
|
||||
tunnel.tls.allowInsecure=false
|
||||
tunnel.tls.trustOnFirstUse=true
|
||||
```
|
||||
|
||||
On the first successful TLS connection, the backend saves the Bungee certificate fingerprint here:
|
||||
On the first successful TLS connection, the backend saves the proxy certificate fingerprint:
|
||||
|
||||
```properties
|
||||
tunnel.tls.pinnedCertificateSha256=
|
||||
frontend.proxy1.tls.pinnedCertificateSha256=
|
||||
```
|
||||
|
||||
After that, the backend will only trust that same Bungee certificate.
|
||||
After that, the backend only trusts that same certificate.
|
||||
|
||||
## Step 6: Start Everything
|
||||
For stricter security, copy the certificate fingerprint from the proxy log and paste it into the backend config before the first connection.
|
||||
|
||||
Start the public Bungee/Waterfall proxy first.
|
||||
## Multi-Server Setups
|
||||
|
||||
Then start the backend Paper/Spigot server.
|
||||
### Two Public Proxies, One Backend
|
||||
|
||||
If it works, the Bungee logs should show that a backend tunnel authenticated.
|
||||
Use this when two public BungeeCord/Waterfall proxies should both reach the same backend server.
|
||||
|
||||
Players should connect to your normal public proxy address. Bungee sends them to `127.0.0.1:25566`, and DirtSimpleP2P carries the connection to the backend server.
|
||||
Backend config:
|
||||
|
||||
```properties
|
||||
role=backend
|
||||
node.name=survival-backend
|
||||
|
||||
frontends=proxy1,proxy2
|
||||
frontend.proxy1.connectHost=proxy1.example.com
|
||||
frontend.proxy1.connectPort=24445
|
||||
frontend.proxy1.tls.pinnedCertificateSha256=
|
||||
frontend.proxy2.connectHost=proxy2.example.com
|
||||
frontend.proxy2.connectPort=24445
|
||||
frontend.proxy2.tls.pinnedCertificateSha256=
|
||||
|
||||
routes=minecraft
|
||||
route.minecraft.backendTargetHost=127.0.0.1
|
||||
route.minecraft.backendTargetPort=25565
|
||||
```
|
||||
|
||||
Each proxy config:
|
||||
|
||||
```properties
|
||||
role=frontend
|
||||
node.name=proxy1
|
||||
|
||||
routes=minecraft
|
||||
route.minecraft.frontendBindHost=127.0.0.1
|
||||
route.minecraft.frontendBindPort=25566
|
||||
route.minecraft.backendNode=survival-backend
|
||||
```
|
||||
|
||||
Each proxy listens for tunnel connections. The backend connects outbound to both proxies.
|
||||
|
||||
### One Proxy, Multiple Backends
|
||||
|
||||
Use this when one proxy should expose more than one backend server.
|
||||
|
||||
Proxy config:
|
||||
|
||||
```properties
|
||||
role=frontend
|
||||
node.name=main-proxy
|
||||
|
||||
routes=survival,lobby
|
||||
route.survival.frontendBindHost=127.0.0.1
|
||||
route.survival.frontendBindPort=25566
|
||||
route.survival.backendNode=survival-backend
|
||||
route.lobby.frontendBindHost=127.0.0.1
|
||||
route.lobby.frontendBindPort=25567
|
||||
route.lobby.backendNode=lobby-backend
|
||||
```
|
||||
|
||||
Bungee/Waterfall server entries:
|
||||
|
||||
```text
|
||||
survival -> 127.0.0.1:25566
|
||||
lobby -> 127.0.0.1:25567
|
||||
```
|
||||
|
||||
Survival backend config:
|
||||
|
||||
```properties
|
||||
role=backend
|
||||
node.name=survival-backend
|
||||
|
||||
frontends=main
|
||||
frontend.main.connectHost=YOUR_PROXY_IP
|
||||
frontend.main.connectPort=24445
|
||||
|
||||
routes=survival
|
||||
route.survival.backendTargetHost=127.0.0.1
|
||||
route.survival.backendTargetPort=25565
|
||||
```
|
||||
|
||||
Lobby backend config:
|
||||
|
||||
```properties
|
||||
role=backend
|
||||
node.name=lobby-backend
|
||||
|
||||
frontends=main
|
||||
frontend.main.connectHost=YOUR_PROXY_IP
|
||||
frontend.main.connectPort=24445
|
||||
|
||||
routes=lobby
|
||||
route.lobby.backendTargetHost=127.0.0.1
|
||||
route.lobby.backendTargetPort=25565
|
||||
```
|
||||
|
||||
All nodes in the same private tunnel group must use the same `tunnel.authToken`.
|
||||
|
||||
## Commands
|
||||
|
||||
Run these commands in game or from the server console:
|
||||
Run from the server console or in game:
|
||||
|
||||
```text
|
||||
/dsp2p status
|
||||
```
|
||||
|
||||
Shows whether the agent is running, whether the tunnel is connected, active streams, TLS state, and the last important event.
|
||||
Shows role, node name, whether the tunnel is connected, connected tunnel count, active streams, TLS state, and the latest event.
|
||||
|
||||
```text
|
||||
/dsp2p doctor
|
||||
```
|
||||
|
||||
Checks the config and prints useful setup/security hints.
|
||||
Checks the config and prints setup/security hints.
|
||||
|
||||
Permission:
|
||||
|
||||
@@ -239,35 +354,35 @@ Permission:
|
||||
dirtsimplep2p.command
|
||||
```
|
||||
|
||||
On Paper/Spigot it defaults to server operators. On Bungee, give that permission to staff who should see tunnel diagnostics.
|
||||
On Paper/Spigot, the permission defaults to server operators. On BungeeCord/Waterfall, give this permission to staff who should see tunnel diagnostics.
|
||||
|
||||
## Firewall Notes
|
||||
|
||||
On the public proxy/VPS, allow:
|
||||
On the public proxy/VPS, allow the tunnel port:
|
||||
|
||||
```text
|
||||
24445/tcp
|
||||
```
|
||||
|
||||
On the home router, you do not need to forward:
|
||||
On the home router, you do not need to forward the backend Minecraft port:
|
||||
|
||||
```text
|
||||
25565/tcp
|
||||
```
|
||||
|
||||
Your backend server must be allowed to make outbound connections to the proxy/VPS.
|
||||
The backend server must be allowed to make outbound TCP connections to the proxy.
|
||||
|
||||
## Reconnect Behavior
|
||||
|
||||
DirtSimpleP2P is tuned to notice real drops quickly while still tolerating short latency spikes.
|
||||
DirtSimpleP2P is tuned to detect real drops quickly while still tolerating short latency spikes.
|
||||
|
||||
Default behavior:
|
||||
|
||||
- Heartbeat every `2` seconds
|
||||
- Warns in status if heartbeats are delayed
|
||||
- Disconnects after about `8` seconds of no tunnel traffic
|
||||
- Status warning if heartbeats are delayed
|
||||
- Disconnect after about `8` seconds without tunnel traffic
|
||||
- First reconnect retry after about `250ms`
|
||||
- Backoff grows up to `10` seconds if the proxy/VPS is still unreachable
|
||||
- Exponential backoff up to `10` seconds while the proxy is unreachable
|
||||
|
||||
Useful config values:
|
||||
|
||||
@@ -279,39 +394,43 @@ tunnel.reconnectInitialMillis=250
|
||||
tunnel.reconnectMaxMillis=10000
|
||||
```
|
||||
|
||||
If your users are very far from the VPS or your home internet has frequent latency spikes, increase `tunnel.heartbeatMissesBeforeDisconnect` to `5` or `6`.
|
||||
If your network has frequent latency spikes, increase:
|
||||
|
||||
## Common Problems
|
||||
```properties
|
||||
tunnel.heartbeatMissesBeforeDisconnect=5
|
||||
```
|
||||
|
||||
### Plugin says the token is still the default
|
||||
## Troubleshooting
|
||||
|
||||
Restart once on each side so DirtSimpleP2P can generate a token.
|
||||
### Token Problems
|
||||
|
||||
Then copy the generated Bungee token into the backend config. The token must be the same on both sides.
|
||||
The token must match on both sides.
|
||||
|
||||
### Backend says connection refused
|
||||
If the plugin generated a token on the proxy, copy that generated value into the backend config.
|
||||
|
||||
### Backend Says Connection Refused
|
||||
|
||||
Check that:
|
||||
|
||||
- Bungee/proxy server is running
|
||||
- DirtSimpleP2P started on Bungee
|
||||
- `tunnel.connectHost` points to the proxy/VPS
|
||||
- `tunnel.connectPort` matches the Bungee `tunnel.listenPort`
|
||||
- The VPS firewall allows that TCP port
|
||||
- The proxy server is running
|
||||
- DirtSimpleP2P started on the proxy
|
||||
- `frontend.proxy1.connectHost` points to the proxy IP or domain
|
||||
- `frontend.proxy1.connectPort` matches the proxy `tunnel.listenPort`
|
||||
- The proxy firewall allows the tunnel port
|
||||
|
||||
### Bungee cannot connect to backend server
|
||||
### Bungee Cannot Reach The Backend
|
||||
|
||||
Make sure your Bungee backend server entry points to:
|
||||
Make sure the Bungee/Waterfall backend server entry points to the local tunnel port:
|
||||
|
||||
```text
|
||||
127.0.0.1:25566
|
||||
```
|
||||
|
||||
Also make sure the backend Paper/Spigot server is running and connected to the tunnel.
|
||||
Also check that the backend Paper/Spigot server is running and the tunnel is connected.
|
||||
|
||||
### Players disconnect or freeze
|
||||
### Players Disconnect Or Freeze
|
||||
|
||||
Check both server logs. Look for:
|
||||
Check both server logs for:
|
||||
|
||||
- reconnect messages
|
||||
- heartbeat timeout messages
|
||||
@@ -320,23 +439,20 @@ Check both server logs. Look for:
|
||||
|
||||
## Security Notes
|
||||
|
||||
The secret token is important. Do not share it.
|
||||
Keep `tunnel.authToken` private. Anyone with the token can attempt to authenticate to the tunnel.
|
||||
|
||||
Local-test configs use:
|
||||
For local testing, insecure mode is available:
|
||||
|
||||
```properties
|
||||
tunnel.tls.enabled=false
|
||||
tunnel.tls.allowInsecure=true
|
||||
```
|
||||
|
||||
For a better setup, enable TLS on both sides:
|
||||
For real deployments, enable TLS:
|
||||
|
||||
```properties
|
||||
tunnel.tls.enabled=true
|
||||
tunnel.tls.allowInsecure=false
|
||||
```
|
||||
|
||||
The Bungee side generates a self-signed certificate. The Paper/Spigot side pins that certificate after the first successful connection.
|
||||
|
||||
Trust-on-first-use is convenient, but the very first TLS connection is still the sensitive moment. For a stricter setup, copy the fingerprint from the Bungee log and paste it into the backend config before the first connection.
|
||||
|
||||
Trust-on-first-use is convenient, but the first TLS connection is the sensitive moment. For the strictest setup, manually copy the proxy certificate fingerprint into the backend config before the first connection.
|
||||
|
||||
Reference in New Issue
Block a user