# DirtSimpleP2P DirtSimpleP2P is a Minecraft networking plugin that lets a public BungeeCord or Waterfall proxy reach backend Paper/Spigot servers that are behind NAT. 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. 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. ## 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 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 - Temporary browser setup wizard with console-generated login key - Simple `config.properties` setup ## Requirements - Java 21 - Maven 3.8+ - BungeeCord or Waterfall for the public proxy side - Paper or Spigot for the backend server side ## How It Works Normal Minecraft proxy setup expects Bungee/Waterfall to connect directly to a backend server. 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 is created at: ```bash plugin/target/DirtSimpleP2P-0.1.0-SNAPSHOT.jar ``` Use this same jar on both the proxy and backend server. ## Basic Setup You need: - A public BungeeCord/Waterfall proxy, usually on a VPS - A backend Paper/Spigot server, which can be at home or on a private network ### 1. Install On The Proxy Put the jar in your BungeeCord/Waterfall `plugins` folder: ```text DirtSimpleP2P-0.1.0-SNAPSHOT.jar ``` Start the proxy once, then stop it. DirtSimpleP2P creates: ```text plugins/DirtSimpleP2P/config.properties ``` ### 2. Configure The Proxy Use this on the BungeeCord/Waterfall side: ```properties role=frontend node.name=bungee-frontend tunnel.listenHost=0.0.0.0 tunnel.listenPort=24445 tunnel.authToken=GENERATED_AUTOMATICALLY tunnel.connectTimeoutMillis=5000 tunnel.heartbeatIntervalMillis=2000 tunnel.heartbeatTimeoutMillis=8000 tunnel.heartbeatMissesBeforeDisconnect=4 tunnel.reconnectInitialMillis=250 tunnel.reconnectMaxMillis=10000 tunnel.tls.enabled=false tunnel.tls.allowInsecure=true tunnel.tls.autoGenerate=true tunnel.tls.keyStore=certs/frontend.p12 tunnel.tls.keyStorePassword= tunnel.tls.requireClientAuth=false webwizard.bindHost=127.0.0.1 webwizard.port=8765 routes=minecraft route.minecraft.frontendBindHost=127.0.0.1 route.minecraft.frontendBindPort=25566 route.minecraft.backendNode=paper-backend ``` Notes: - `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`. ### 3. Point Bungee/Waterfall At The Local Tunnel In your BungeeCord/Waterfall server config, set the backend address to: ```text 127.0.0.1:25566 ``` Do not put your home server IP in the Bungee/Waterfall config. Bungee connects locally, and DirtSimpleP2P carries the traffic through the tunnel. ### 4. Install On The Backend Put the same jar in your Paper/Spigot `plugins` folder: ```text DirtSimpleP2P-0.1.0-SNAPSHOT.jar ``` Start the backend server once, then stop it. DirtSimpleP2P creates: ```text plugins/DirtSimpleP2P/config.properties ``` ### 5. Configure The Backend Use this on the Paper/Spigot side: ```properties role=backend node.name=paper-backend 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 tunnel.heartbeatTimeoutMillis=8000 tunnel.heartbeatMissesBeforeDisconnect=4 tunnel.reconnectInitialMillis=250 tunnel.reconnectMaxMillis=10000 tunnel.tls.enabled=false tunnel.tls.allowInsecure=true tunnel.tls.trustOnFirstUse=true webwizard.bindHost=127.0.0.1 webwizard.port=8765 routes=minecraft route.minecraft.backendTargetHost=127.0.0.1 route.minecraft.backendTargetPort=25565 ``` Change: - `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` ### 6. Start Everything 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 ``` 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 proxy certificate fingerprint: ```properties frontend.proxy1.tls.pinnedCertificateSha256= ``` After that, the backend only trusts that same certificate. For stricter security, copy the certificate fingerprint from the proxy log and paste it into the backend config before the first connection. ## Multi-Server Setups ### Two Public Proxies, One Backend Use this when two public BungeeCord/Waterfall proxies should both reach the same 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 from the server console or in game: ```text /dsp2p status ``` 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 setup/security hints. ```text /dsp2p webwizard ``` Toggles a temporary browser setup wizard. When the wizard starts, the server console prints: ```text Please sign in with this key: ``` Open the printed URL in a browser and sign in with the temporary key. The wizard uses a dark control-center UI. It detects whether it is running on Paper/Spigot or BungeeCord/Waterfall and only shows the setup sections that apply to that server type. Depending on the server type, it provides guided sections for: - server mode and node name - proxy listener settings - backend proxy connections - Minecraft routes - tunnel token and TLS - heartbeat and reconnect settings - advanced raw config keys You can add or remove proxy endpoints, backend routes, and advanced config keys directly from the web UI. The web UI includes: - `Save Config` - `Save + Reload DirtSimpleP2P` - `Reload Current Config` - `Generate New Token` Reloading from the wizard restarts the DirtSimpleP2P tunnel agent with the latest config. It does not run a full Minecraft server reload. Run `/dsp2p webwizard` again to stop the wizard when setup is complete. By default, the wizard binds to: ```properties webwizard.bindHost=127.0.0.1 webwizard.port=8765 ``` Keep it on `127.0.0.1` unless you understand the risk of exposing a config editor over the network. Permission: ```text dirtsimplep2p.command ``` 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 the tunnel port: ```text 24445/tcp ``` On the home router, you do not need to forward the backend Minecraft port: ```text 25565/tcp ``` The backend server must be allowed to make outbound TCP connections to the proxy. ## Reconnect Behavior DirtSimpleP2P is tuned to detect real drops quickly while still tolerating short latency spikes. Default behavior: - Heartbeat every `2` seconds - Status warning if heartbeats are delayed - Disconnect after about `8` seconds without tunnel traffic - First reconnect retry after about `250ms` - Exponential backoff up to `10` seconds while the proxy is unreachable Useful config values: ```properties tunnel.heartbeatIntervalMillis=2000 tunnel.heartbeatTimeoutMillis=8000 tunnel.heartbeatMissesBeforeDisconnect=4 tunnel.reconnectInitialMillis=250 tunnel.reconnectMaxMillis=10000 ``` If your network has frequent latency spikes, increase: ```properties tunnel.heartbeatMissesBeforeDisconnect=5 ``` ## Troubleshooting ### Token Problems The token must match on both sides. If the plugin generated a token on the proxy, copy that generated value into the backend config. ### Backend Says Connection Refused Check that: - 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 Reach The Backend Make sure the Bungee/Waterfall backend server entry points to the local tunnel port: ```text 127.0.0.1:25566 ``` Also check that the backend Paper/Spigot server is running and the tunnel is connected. ### Players Disconnect Or Freeze Check both server logs for: - reconnect messages - heartbeat timeout messages - stream reset messages - backend target connection failed ## Security Notes Keep `tunnel.authToken` private. Anyone with the token can attempt to authenticate to the tunnel. For local testing, insecure mode is available: ```properties tunnel.tls.enabled=false tunnel.tls.allowInsecure=true ``` For real deployments, enable TLS: ```properties tunnel.tls.enabled=true tunnel.tls.allowInsecure=false ``` 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. The Web Wizard is intended as a temporary setup tool. It uses a random key printed to the server console and should be stopped when configuration is complete. The reload button reloads DirtSimpleP2P itself. It intentionally does not run Paper/Bukkit `/reload`, because full server reloads are risky on production Minecraft servers.