6379
The port a Redis server listens on for RESP — the one your client says it cannot reach, and the one an exposed cache gets found on within hours.
Run the line for your platform. Each one names the process holding the port and the address it bound to, which is usually the whole answer.
sudo lsof -nP -iTCP:6379 -sTCP:LISTEN`-n` skips the reverse-DNS lookup and `-P` skips the port-name lookup, so addresses stay numeric; `-iTCP:6379` narrows to that port and `-sTCP:LISTEN` to the listening state — the exact combination lsof's own manual gives as an example. The columns are COMMAND, PID, USER, FD, TYPE, DEVICE, SIZE/OFF, NODE, NAME. The second is the process you would stop, and the last is the bind address, printed as `127.0.0.1:6379 (LISTEN)` or `*:6379 (LISTEN)`. Loopback means only this machine can ever connect, which is why a container or another host never will; `*` means every interface. No rows at all, and lsof exits 1, means the port is genuinely free. Without `sudo` you see only your own processes, so a `redis-server` started by a launch daemon or by Docker looks like nothing at all.
sudo ss -tlnp 'sport = :6379'The ss(8) manual defines each flag: `-t` displays TCP sockets, `-l` displays only listening sockets, `-n` does not resolve service names, `-p` shows the process using the socket, and `sport = :6379` is its documented `{dport|sport} [OP] [FAMILY:]:PORT` filter. Read the Local Address:Port column: `0.0.0.0:6379` is every IPv4 address, `127.0.0.1:6379` is loopback only, and `[::]:6379` is the IPv6 wildcard, which on a default Linux host also accepts IPv4 connections. The owner prints as `users:(("redis-server",pid=1234,fd=6))`. On a host without `ss`, the older `netstat -tlnp` gives the same three facts; netstat's manual warns that you need superuser privileges to see the program name for sockets you do not own, and the same applies to `ss`.
redis-cli -h 127.0.0.1 -p 6379 pingThe application-level version of the same question, and the one that separates 'a socket is open' from 'Redis is answering'. `PONG` is a healthy server. `NOAUTH Authentication required.` also means healthy — the port and the network are fine and only credentials are missing. `Could not connect to Redis at 127.0.0.1:6379: Connection refused` means nothing is listening there. Pin the address rather than writing `-h localhost`: on a dual-stack host that name can resolve to `::1` while the server bound only IPv4, and the failure then looks identical to a stopped server.
netstat -ano | findstr :6379Microsoft's reference for the flags: `-a` "displays all active TCP connections and the TCP and UDP ports on which the computer is listening", `-n` expresses addresses and port numbers numerically, and `-o` "includes the process ID (PID) for each connection". The columns are Proto, Local Address, Foreign Address, State and PID, so the second column is the bind address and the last is the process. Turn the PID into a name with `tasklist /fi "PID eq 1234"` — `PID` is a documented filter name and `eq` a documented operator for it. Watch the match, though: `findstr` looks for the substring anywhere on the line, so a row whose Foreign Address ends in `:6379` — an outbound client connection — matches as well. Check the State column says LISTENING before you stop anything.
Get-NetTCPConnection -LocalPort 6379 | Select-Object LocalAddress,LocalPort,State,OwningProcessThe PowerShell form matches the port as a number rather than as text, so no substring can fool it, and `-LocalPort` never picks up a connection where 6379 is the remote end. Pipe the `OwningProcess` value into `Get-Process -Id` for the image name. An empty result while a bind still fails is the reserved-range case: `netsh interface ipv4 show excludedportrange protocol=tcp` lists the dynamic-port blocks that Hyper-V, WSL2 and Docker Desktop claim at boot, and a bind inside one of them fails with no process to blame.
`nmap -Pn -p 6379 cache.example.com` answers the only question that matters from off the host. `-Pn` treats the host as online and skips discovery, so a machine that ignores pings still gets scanned, and `-p` limits the scan to the port you care about. `open` means the TCP handshake completed: something is listening and reachable. `closed` means the host replied with a reset, so it is up and routable but nothing holds the port. `filtered` means nothing came back at all — a firewall or a cloud security group is dropping the packet rather than refusing it, and the difference is the whole diagnosis. Add `--reason` to see which of the three actually happened; nmap prints `syn-ack` beside an open port and `conn-refused` beside a closed one. `-sV` goes further and probes the port to identify the service and version, which for Redis usually returns the version string — and is exactly how an internet-wide scanner finds an unprotected instance. Only scan hosts you are responsible for.
| What you see | What it means |
|---|---|
Could not connect to Redis at 127.0.0.1:6379: Connection refused | redis-cli's wording for `ECONNREFUSED`: the packet reached the host and the kernel answered with a reset, because no process holds the port. Redis is stopped, it died during startup, or it is bound to an address that does not include the one you dialled. Read its log before assuming it ever came up — a server that could not take the port logs `Failed listening on port 6379 (tcp), aborting.` and exits. |
Warning: Could not create server TCP listening socket 127.0.0.1:6379: bind: Address already in use | Redis's own startup line when the port is taken, followed by `Failed listening on port 6379 (tcp), aborting.` and an exit. Nine times out of ten it is an earlier `redis-server` that was detached rather than stopped, or a container still publishing the port. Run the probe for your platform and read the PID out of it rather than guessing. |
(error) DENIED Redis is running in protected mode because protected mode is enabled and no password is set for the default user. | The network is fine and Redis is running. It is refusing you because you arrived from a non-loopback address on a server that has no password and no explicit bind. The error text lists four ways out; take the one that sets a password or an ACL user. Turning protected mode off on a reachable server is how instances get emptied. |
(error) NOAUTH Authentication required. | Not a port problem at all — the connection succeeded, and `requirepass` or an ACL is in force. Send `AUTH <password>`, or `AUTH <user> <password>` for an ACL user, before anything else, or put the credentials in the connection URL. On a plain port that password crosses the network in clear text. |
The client blocks for tens of seconds and then reports a connect timeout | `ETIMEDOUT`: nothing replied. A packet filter is dropping the SYN silently instead of refusing it — a security group, an on-host firewall, or a network ACL between you and the cache. A refusal is instant and a drop is slow, so the delay itself tells you which one you are looking at. |
(error) MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. | Also nothing to do with 6379. The connection worked and Redis is refusing writes because a background save failed, usually a full disk or a directory it cannot write into. Reads keep working the whole time. Fix the disk, or change `stop-writes-on-bgsave-error` if you accept losing the snapshot. |
IANA registers 6379 to `redis` on TCP; the UDP row for the same number carries no service name and is marked Reserved, and nothing in Redis speaks UDP, so a page about 6379 is a page about TCP only. The number is the `port 6379` line in the `redis.conf` that ships with the server, and `redis-cli` uses the same value as its own default, which is why `redis-cli ping` needs no arguments on a local install. Three neighbouring numbers cause most of the confusion. Redis Sentinel ships a separate config file whose `port` is 26379, so a Sentinel is never the thing on 6379. A node in cluster mode opens a second listening socket for the cluster bus, and `redis.conf` documents that with `cluster-port` left at its default of 0 the bus binds to the command port plus 10000 — 16379 for a default node — so a cluster member holds two ports, not one. And TLS, added in Redis 6, is configured through a separate `tls-port`: the plain `port` keeps speaking unencrypted RESP alongside it until you deliberately set it to 0. That last detail is worth stating twice, because it is the one people get wrong: a connection to 6379 is plaintext unless somebody turned the plain port off.
Never let 6379 face the internet. Redis states the design assumption on its own security page — it 'is designed to be accessed by trusted clients inside trusted environments' — and spells out both consequences. A single `FLUSHALL` from anyone who can reach the port destroys the dataset. Worse, the `CONFIG` command lets a client change the working directory and the dump filename, which the same page calls a security issue that 'may lead to the ability to compromise the system and/or run untrusted code as the same user as Redis is running'. That is the mechanism behind every mass-exploited Redis: write a dump file into a path the operating system reads back later. Protected mode helps, but it is narrower than people assume. Since 3.2.0 Redis answers non-loopback clients with a `-DENIED` error, and the documentation is precise about when: only while the server is running the default configuration, binding all interfaces, with no password set. Adding an explicit `bind 0.0.0.0` to make the server reachable also removes that guard, which is exactly the edit an operator makes shortly before the incident. The shipped `redis.conf` binds `127.0.0.1 -::1`; keep it that way, put a password or an ACL user in front of it, reach remote instances over a VPN or an SSH tunnel, and remember that `AUTH` itself travels in clear text on a plain port.
All of these run in your browser — nothing is uploaded.
Ports people usually end up checking in the same session as 6379.
Almost always permissions. lsof and ss list the socket but hide the owning process when it belongs to another user, so a server started by a system account, by a container runtime or by launchd shows up as an anonymous listener until you re-run the command with sudo. On Windows the opposite happens: netstat shows nothing at all, yet a bind still fails, which means the port sits inside a range that Hyper-V, WSL2 or Docker Desktop reserved at boot.
Look at what it is first. An orphaned dev server is safe to kill; a database with a write in flight is not, and neither is a system service that something else depends on. If the owner is a container, stop the container instead — killing the process the host sees only makes the runtime restart it. When the process is something you need, moving your own service to another port is the faster fix.
The listener bound to 127.0.0.1 rather than 0.0.0.0. The probes on every page print the bound address next to the process for exactly this reason: a loopback bind is reachable from the machine itself and from nowhere else, no matter how the firewall is configured. Many frameworks made that the default deliberately, so it is usually a flag rather than a bug. If the address is already 0.0.0.0 and it still fails, the next suspect is a host firewall or a cloud security group.
Barely. Internet-wide scanners sweep the whole port range continuously, so an unusual number buys hours, not safety, and it costs you every colleague who now has to remember it. It does cut the noise in your logs from opportunistic scans of the default port, which is a real if modest benefit. Authentication, a firewall that restricts source addresses, and not exposing the service at all are the measures that actually change the outcome.
Still stuck on port 6379? browse every port in the reference — or go back to the failure message you actually got, above.