Direct answer: when Minecraft port 25565 is not working, do not add random firewall rules. Work from the inside out: process and listener, server.properties, host firewall, Docker publishing or Pterodactyl allocation, provider firewall, DNS, and—only for a home server—NAT or CGNAT. Fix the first failed layer, then repeat the same test.
Minecraft Java uses TCP 25565 by default; Minecraft Bedrock uses UDP 19132 by default. They are different network paths, so expose only the one required by your edition. The official guides cover setting up a Java server and joining a Bedrock server. The commands below are documented procedures for Ubuntu 24.04 and Debian 12/13; they were not run on your VPS.
Let the symptom choose the first check
| Symptom | What it proves | First layer to inspect |
|---|---|---|
| Connection refused | The path reached a host that rejected the connection. | Stopped process, wrong bind address/port, missing mapping, or explicit reject. |
| Connection timed out | No response arrived before the deadline. | UFW, provider firewall, DNS/AAAA, NAT, CGNAT, or return route. |
| Incompatible version, Outdated client/server | The client already reached a Minecraft application. | Versions, proxy, mods, or compatibility; the port is not the primary fault. |
| Not whitelisted or an authentication error | The network and protocol reached the server. | Whitelist, account, online-mode, or proxy authentication. Do not open more ports. |
Exact wording varies by client, version, and proxy. Pair it with the attempt's log entry: a version or whitelist response is positive evidence that several network layers are already healthy.
Prerequisites and a restore point
- Ubuntu 24.04 or Debian 12/13,
sudoaccess, and a window to restart only the game service. - The real public IP, advertised port, and edition. Keep public, private, container, and allocation addresses distinct.
- The actual server path and service name. This guide uses
/srv/minecraftandminecraft.serviceas examples. - Console or log access plus a second Internet connection for the external test.
Copy server.properties before editing. Adjust the path to match your installation:
cd /srv/minecraft
sudo cp -a server.properties "server.properties.before-25565-$(date +%Y%m%d-%H%M%S)"
sudo grep -E '^(server-ip|server-port)=' server.properties
1. Identify the listener and its process
Inspect TCP for Java. Run the UDP branch only for Bedrock. ss should show the expected socket and, with sudo, the owning process.
sudo ss -lntp 'sport = :25565'
sudo ss -lnup 'sport = :19132'
No output means the firewall is not yet the first problem; read startup logs. A socket bound only to 127.0.0.1 cannot accept public traffic. If another PID owns the port, identify it before stopping anything—never kill an unknown process just to free the number.
2. Check server.properties and perform a controlled restart
For Java, keep server-ip= empty unless you deliberately need a specific local address and have confirmed that address exists on the host. Then confirm the port:
server-ip=
server-port=25565
Edit with sudoedit. If you have already confirmed that systemd owns this instance, restart only its unit and read the full startup:
sudoedit /srv/minecraft/server.properties
sudo systemctl restart minecraft.service
sudo systemctl --no-pager --full status minecraft.service
sudo journalctl -u minecraft.service --since '15 minutes ago' --no-pager
sudo ss -lntp 'sport = :25565'
For Pterodactyl, use the server's Stop/Start controls and console; do not manage its container process with this example unit. An Address already in use message, Java exception, or startup exit is an application problem. Another firewall rule cannot repair it.
3. Keep local and external tests separate
ss and the startup log are the initial local checks. For Java, test the public IP next from a device on another network, such as a phone on cellular data. nc -vz is used only for TCP here and must run from that external network:
nc -vz PUBLIC_IP 25565
A successful TCP connection does not validate the Minecraft version, whitelist, or login. For Bedrock/UDP, a scanner may report open|filtered or receive no response even when the path works. Join with an external Bedrock client while watching logs; use the packet-capture decision below if the result remains ambiguous.
4. Inspect UFW before allowing a port
Ubuntu documents UFW as a firewall interface over Netfilter. Record its current state, then add one rule for your edition. Disabling the firewall is not a permanent fix. For Java:
sudo ufw status verbose
sudo ufw status numbered
sudo ufw allow 25565/tcp comment 'Minecraft Java'
sudo ufw status numbered
Host your Minecraft server
Explore Minecraft hosting options and choose an environment that fits your community.


If you host Bedrock instead, use this rule—not the Java rule:
sudo ufw status verbose
sudo ufw status numbered
sudo ufw allow 19132/udp comment 'Minecraft Bedrock'
sudo ufw status numbered
Retest externally. If that rule was your only change and you must roll it back, remove the exact variant you created with sudo ufw delete allow 25565/tcp or sudo ufw delete allow 19132/udp, then run sudo ufw status numbered again. Do not remove a pre-existing shared rule.
sudo nft list ruleset is useful for low-level diagnosis. Do not add native nftables rules on a host managed by UFW: Ubuntu's nftables documentation warns that mixing management methods can cause unexpected interactions. See the official Ubuntu firewall overview as well.
5. Verify the provider firewall and public IP
A local rule does not modify a cloud firewall. In the VPS control panel or security group, confirm one inbound rule for TCP 25565 on Java or UDP 19132 on Bedrock, attached to the correct instance/destination and public IP. Include any provider load balancer or NAT in the check. Do not expose ranges or management ports “for testing.” Save the previous state and remove only the newly added rule if you roll back.
6. Follow the Docker or Pterodactyl branch
Docker
Inspect the effective mapping. An image's EXPOSE instruction is metadata; it does not publish a port. Docker needs -p or ports:, as described in the official port-publishing guide.
docker ps --format 'table {{.Names}}\t{{.Ports}}'
docker port CONTAINER
docker inspect --format '{{json .NetworkSettings.Ports}}' CONTAINER
Important: Docker can divert published-port traffic before UFW rules. Do not treat ufw status as proof that a container port is filtered: assume the publication is reachable on all host addresses, verify it externally, and enforce restrictions at the provider firewall or with a tested Docker-compatible policy—for example, a deliberately designed DOCKER-USER chain. Do not blindly disable Docker’s firewall management. See Docker’s official Docker and UFW warning.
For a Java server, the Compose fragment is:
services:
minecraft:
ports:
- '25565:25565/tcp'
For a Bedrock server, use this instead:
services:
bedrock:
ports:
- '19132:19132/udp'
Apply the edit through your normal deployment procedure, recreate only the affected service, and inspect docker port again. Do not restart the entire Docker daemon blindly; that can interrupt unrelated containers without proving the cause.
Pterodactyl
An allocation is the IP-and-port combination assigned to a server, according to the official Wings documentation. Confirm that the primary allocation and application port match and that the corresponding protocol/path is permitted externally. A UFW rule does not create an allocation. Do not use host networking as a shortcut. For node context, see the guide to installing Pterodactyl Panel and Wings.
7. Verify A, AAAA, and SRV records
dig +short A play.example.net
dig +short AAAA play.example.net
dig +short SRV _minecraft._tcp.play.example.net
The A record must return the correct public IPv4 address. If an AAAA record exists, the listener, server, and firewalls must support that IPv6 path. A broken AAAA can make some clients fail while IPv4 works. Do not delete it blindly: test both address families, then repair the IPv6 path or change the record intentionally.
Use _minecraft._tcp only for Minecraft Java on a custom port. The SRV target must be a canonical hostname with A/AAAA address records, not an IP address or a CNAME/alias; also confirm that the returned port field is the public port clients will use; RFC 2782 defines that format and requirement. Java SRV records do not repair a Bedrock connection. The DNS explainer provides more background.
8. For a home server, check NAT and CGNAT
Forward the router port to the server's stable LAN address: TCP 25565 for Java or UDP 19132 for Bedrock. The protocol must match, and the rule must translate the public port clients use to the internal port where the server actually listens. External and internal port numbers may differ; when they do, advertise the external port to clients and verify the internal listener with ss. RFC 4787 describes this translation behavior. Test from outside; some routers lack NAT loopback, so a same-Wi-Fi test can mislead you.
Compare the router's WAN address with your public IPv4. A WAN address inside 100.64.0.0/10—Shared Address Space reserved by RFC 6598—or a mismatch with the public address can indicate CGNAT or double NAT. Ask the ISP for a public IPv4/port-forwarding option, fix the second NAT, or move the server to hosting/VPS. A home-router rule cannot independently cross the carrier's CGNAT.
9. Use tcpdump as the final decision point
Run a short capture on the host while someone connects from another network. Choose only the filter for your edition:
sudo tcpdump -ni any 'tcp port 25565'
sudo tcpdump -ni any 'udp port 19132'
- No packets arrive: after confirming the filter and interface, investigate upstream—DNS, public IP, provider firewall, NAT, CGNAT, or allocation.
- A SYN arrives and RST/RST-ACK returns: the path reaches the host, but no TCP listener accepts that address/port or a rule actively rejects it; correlate the result with
ssand the log. - Repeated SYN packets arrive and no response leaves: investigate a local firewall drop, the return path, the provider firewall, or NAT. Do not infer a missing listener from silence alone.
- The TCP handshake completes and the client disconnects: the path works; correlate time and source with version, proxy, authentication, whitelist, and application logs.
- UDP arrives but receives no reply: validate the Bedrock listener, mapping, logs, and return rules. A standalone UDP scan is not conclusive.
The distinction between a reset and unanswered retransmissions follows the TCP behavior specified in RFC 9293.
The capture confirms packet metadata and sequence, but encryption and protocol details limit payload interpretation. Stop tcpdump after reproducing the issue and avoid retaining unnecessary traffic.
Final verification, rollback, and maintenance
ssshows the correct process and protocol on the intended address.- The startup log is clean and records the external attempt.
- The effective firewall for that path—including the Docker path—the provider firewall, and the mapping/allocation expose only the required game port.
- A and AAAA resolve to working paths; an SRV record, if used, belongs to Java and targets a valid hostname.
- A real client joins from another network. Then validate version, whitelist, and normal gameplay.
If the change makes service worse, restore the exact server.properties backup, revert the mapping or allocation, remove only the local and provider rules you added, and perform a controlled restart. Record the IP, port, protocol, time, and outcome of each test. Keep the OS and server updated, secure RCON/panel/SSH separately, and remove stale rules; never leave the firewall disabled.
If Java works but Bedrock does not, follow the GeyserMC and Floodgate guide. If players can join but gameplay stutters, the network path is no longer the first suspect; profile the server with the spark troubleshooting guide instead of changing the port.








