Files
DirtSimpleP2P/README.md
T
2026-06-23 22:42:23 -04:00

13 KiB

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:

mvn clean package

The plugin jar is created at:

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:

DirtSimpleP2P-0.1.0-SNAPSHOT.jar

Start the proxy once, then stop it.

DirtSimpleP2P creates:

plugins/DirtSimpleP2P/config.properties

2. Configure The Proxy

Use this on the BungeeCord/Waterfall side:

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:

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:

DirtSimpleP2P-0.1.0-SNAPSHOT.jar

Start the backend server once, then stop it.

DirtSimpleP2P creates:

plugins/DirtSimpleP2P/config.properties

5. Configure The Backend

Use this on the Paper/Spigot side:

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:

tunnel.tls.enabled=true
tunnel.tls.allowInsecure=false
tunnel.tls.autoGenerate=true

When TLS is enabled, the proxy can generate:

plugins/DirtSimpleP2P/certs/frontend.p12

On the backend:

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:

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:

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:

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:

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:

survival -> 127.0.0.1:25566
lobby    -> 127.0.0.1:25567

Survival backend config:

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:

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:

/dsp2p status

Shows role, node name, whether the tunnel is connected, connected tunnel count, active streams, TLS state, and the latest event.

/dsp2p doctor

Checks the config and prints setup/security hints.

/dsp2p webwizard

Toggles a temporary browser setup wizard.

When the wizard starts, the server console prints:

Please sign in with this key: <temporary-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:

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:

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:

24445/tcp

On the home router, you do not need to forward the backend Minecraft port:

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:

tunnel.heartbeatIntervalMillis=2000
tunnel.heartbeatTimeoutMillis=8000
tunnel.heartbeatMissesBeforeDisconnect=4
tunnel.reconnectInitialMillis=250
tunnel.reconnectMaxMillis=10000

If your network has frequent latency spikes, increase:

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:

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:

tunnel.tls.enabled=false
tunnel.tls.allowInsecure=true

For real deployments, enable TLS:

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.