Match this symptom
The correct Java world is joinable from localhost or the LAN, but an outside Java client waits and ends with a connection timeout.
The answer first
Use the successful LAN join as your baseline and leave the world alone. Java gameplay uses TCP 25565 by default: keep server-ip blank, verify the Java process is listening on the configured TCP port, allow that port in the host firewall, and forward it to the server PC’s reserved LAN address. Test with a matching Java client on another network; if the router itself lacks a public address, solve double NAT or CGNAT rather than enabling Query or RCON.

Classify timeout versus rejection
A timeout usually means the client cannot complete a TCP path. “Incompatible version,” “not whitelisted” and authentication failures prove the connection reached server logic and should not be chased with new router rules.
- Record the exact client and server versions before the test.
- Confirm localhost or LAN joins the intended world, not a second server on another port.
- Watch logs/latest.log or the console during the outside attempt.
- Do not disable online-mode to troubleshoot a silent network timeout.
Verify the Java listener and bind
- 1Open server.properties and record server-port; 25565 is the standard default.
- 2Leave server-ip empty for an ordinary home host. A public IP normally is not a local interface and can produce a bind failure.
- 3Confirm the intended Java process owns that TCP port after the world reports ready.
- 4If another process owns it, assign a unique port deliberately and update every later layer to match; do not terminate an unknown process without identifying it.
Use the server log to locate the break
Correlate one outside attempt with the console and logs/latest.log. A ready server with no new connection-related entry during a long client wait suggests that the TCP connection did not reach Minecraft. Continue through address resolution, Windows Firewall, router mapping and upstream NAT. Do not edit whitelist.json or the world for a packet path that never reached login handling.
An incompatible-version, authentication, whitelist or ban response proves more of the route than a timeout: Java accepted a socket far enough to apply server policy. Preserve the complete message and move to that policy branch. A startup ‘failed to bind to port’ message is earlier still—the Java process does not own a listener, so no router configuration can make that instance joinable.
- No ready message: solve startup/world loading before public reachability.
- Ready plus no log event on external attempt: inspect DNS/public address, TCP firewall and NAT.
- Login begins then rejects: investigate the explicit version, authentication or access-control reason.
- Address already in use or bind failure: identify the local owner/bind setting before changing the external port.
Match Windows Firewall and router NAT
- 1Create or inspect one inbound TCP rule for the selected gameplay port and the host’s active network profile.
- 2Reserve the server PC’s LAN IPv4 address so the router target survives reboot.
- 3Forward the selected external TCP port to that LAN address and internal server-port.
- 4Do not forward UDP Query, TCP RCON or the MSMP port unless a separate private use has been designed and secured.
Detect the boundary you do not control
- A modem-router plus another router may require bridging or a deliberate rule at both NAT layers.
- A router WAN address that differs from the public IPv4 address can indicate upstream NAT.
- Under CGNAT, ordinary forwarding on the home router cannot create an inbound public socket; ask the ISP for a public address or use an intentional supported relay/VPN design.
- IPv6 joining uses firewall policy and a reachable IPv6 address, not IPv4 port forwarding.
Run a controlled TCP test matrix
- 1Join through localhost on the server PC after readiness. Failure isolates the Java process, version or local bind; it does not justify a router change.
- 2Join from another LAN PC using the private LAN address and explicit port. Pass proves the host listener and local route, while failure keeps diagnosis inside the home network.
- 3Join from a separate internet connection using the current public address and explicit port. Note whether the console sees a login attempt or remains silent.
- 4If a hostname is advertised, resolve it and compare the returned address with the intended public endpoint. Test the direct address separately so stale DNS is not confused with a broken forward.
- 5When IPv6 is intentionally supported, create a separate IPv6 row with the chosen address and firewall policy. Do not count an IPv4 success as proof that IPv6 is configured, or vice versa.
Retest without risking server state
Keep the server running and test from mobile tethering or another independent network with the matching Java release. If a restart or address change is needed, warn players, run save-all flush and stop, wait for exit, and retain a complete recovery point before broader configuration edits.
Keep a known-good network baseline
Once an outside Java client joins the intended world, record the server-port, blank or deliberate server-ip value, Java process/JAR, reserved LAN address, firewall rule, router destination, public-address type and test timestamp. Redact addresses and player identities from public evidence. The record lets a later failure be compared with a proven state instead of rebuilding every layer from memory.
- Repeat the LAN/outside rows after router replacement, ISP change, network-adapter change or a new Windows firewall profile.
- Revalidate each additional Java instance on its own TCP port; never let two profiles claim the same listener accidentally.
- Check the current generated server properties after game updates before preserving an old setting as permanent truth.
- Leave Query, legacy RCON and MSMP private/off unless they have a separately tested operational requirement; none is needed for an ordinary player join.
