VNC Connection Refused? Check What’s Listening on the Port

Connection refused, error 10061 in a Windows viewer, means your viewer got through to the host and nothing there took the call on the port it dialed. That narrows things down fast: name resolution and routing are fine, and the problem sits on the server.

So go to the server and look at what's listening. The viewer dials 5900 plus the display number, which makes display :1 port 5901. Nothing on 5901 means the server isn't running. Something on 5902 instead means your viewer address is wrong. A listener on 127.0.0.1:5901 means the server only takes callers from its own machine, and every remote viewer gets refused.

How the viewer finds the server, and where it gets turned away

Three things have to line up: the port your viewer dials, a listener on that port, and a path between the two machines.

An engineer at a laptop whose viewer window reaches across to a server rack carrying a small shield marking the listener port.

The display number picks the port. The server listens on 5900 plus the display number, and the TigerVNC viewer reads a single-colon value under 100 as a display and adds 5900, while a double colon takes the port as written. So <server-host>:1 and <server-host>::5901 dial the same port.

The listener is the server's half. It takes callers either from anywhere or only from its own machine, and you choose which in the server's settings, not the viewer's.

Between the two sits the network, firewalls included. If you'd rather not put the listener on the network at all, tunnel through SSH: your viewer talks to a local port, SSH carries the traffic across, and the VNC port never leaves localhost.

What the refusal looks like in your viewer

The message changes with the viewer, but every version tells you the same thing: the host answered.

Two devices separated by a connector line with an exclamation mark, showing a client dialling a host where no server answers.

The TigerVNC viewer pops up Failed to connect to "<server-host>:1" followed by Unable to connect to socket: Connection refused (111). Windows viewers report the Winsock code, often as Connection refused (10061). RealVNC Viewer shows The connection was refused by the host computer, which means the server isn't running, or isn't listening on the port you dialed. On a Linux host, start the service with sudo systemctl start vncserver-x11-serviced.service and try again.

If SSH and SFTP to the same box work while the viewer gets 111 or 10061, you've already ruled out the network. The machine is reachable, and only the VNC port is turning you away.

The usual causes, and how each one shows up

Every cause produces the same viewer message, so the listener on the server is what tells them apart:

A flat comparison table listing five causes of a VNC server refusing connections, with distinct markers and port numbers down each row.

Cause What you see Check Fix
Server not running Refusal; nothing listed on 5901 ss -tlnp or tigervncserver -list on the server Start the server unit
Wrong display number or port in the viewer address Refusal; a listener runs on another port, such as 5902 Port equals 5900 plus the display Dial <server-host>:2 or <server-host>::5902
Server started with a custom -rfbport Refusal; listener on that port ss -tlnp Dial <server-host>::<port>
RealVNC Server stopped, or moved off 5900 The connection was refused by the host computer sudo systemctl status vncserver-x11-serviced, and its RfbPort value Start the service, or dial the RfbPort port
Listener restricted to the local computer Remote viewers refused; 127.0.0.1:5901 in ss; a viewer on the server connects ss -tlnp and the session log Set $localhost = "no";, or use an SSH tunnel

Find the cause in four checks

Start with what's cheap. The address costs nothing to read, the port test runs from your own machine, and only the last two checks need a shell on the server. Server commands are for TigerVNC as Debian trixie packages it; RHEL, Windows and Mac come later.

  1. Read the address you typed. A viewer pointed at <server-host>:2 while the session runs on :1 dials 5902, where nothing is listening. If the display is off, fix it and you're done.

  2. Test the port from your machine with the viewer out of the way. nc -vz prints succeeded! when something accepts and Connection refused when nothing does. That's OpenBSD netcat, Debian's default; on Fedora nc is nmap's ncat, which prints Connected to instead:

    find the cause in four checks
    nc -vz <server-host> 5901

    If nc gets through and the viewer is still refused, the viewer is dialing a different port than the one you just tested. Go back to step 1.

  3. On the server, list the listening TCP sockets and the process behind each:

    find the cause in four checks
    sudo ss -tlnp | grep ':59'

    The Local Address column tells you which cause you have. No line for 5901: the server is stopped, so start it (next section). A line on another port: fix the viewer address. 0.0.0.0:5901 or *:5901: the server listens on every interface, so look at the firewall next. The process column shows Xtigervnc for a TigerVNC session.

    127.0.0.1:5901 or [::1]:5901 is where a fresh Debian session lands, and it's the one that catches people out. The tigervncserver wrapper, which the service runs too, listens only on localhost unless the security types include a TLS or X509 type and no *None type, and its default security type is plain VncAuth. If a viewer on the server itself connects but every other machine is refused, this is your case.

  4. As the session owner, ask the wrapper what it has running:

    find the cause in four checks
    tigervncserver -list

    You get a TigerVNC server sessions: table with X DISPLAY # and RFB PORT # columns. An empty table means nothing is running for that user, so start the unit. A session on a different display means the server is fine and the viewer address needs fixing.

Bring a stopped server back

Debian trixie ships the unit as tigervncserver@.service and the password tool as tigervncpasswd. The display number goes in the unit name, so the number you pick is the number your viewer dials. Use display :1, port 5901.

  1. Give display :1 to a user with this line in /etc/tigervnc/vncserver.users:

    bring a stopped server back
    :1=<user>
  2. As that user, set the session's VNC password. It lands in ~/.config/tigervnc/passwd:

    bring a stopped server back
    tigervncpasswd
  3. Enable and start the unit in one go:

    bring a stopped server back
    sudo systemctl enable --now tigervncserver@:1.service
  4. Check it's up and holding the port:

    bring a stopped server back
    systemctl status tigervncserver@:1.service
    sudo ss -tlnp | grep ':5901'

    You want Active: active (running) in the status output and a 5901 line from ss. On a fresh install that line reads 127.0.0.1:5901, the localhost-only default from check 3, so remote viewers stay refused until you tunnel in or open it up.

If the unit doesn't stay up, its journal has the exit code. The log commands are at the end.

Get past a localhost-only listener

On a LAN you don't trust, leave the listener where it is and tunnel to it: the service isn't meant to face an untrusted network directly. ssh -L forwards a port on your machine through SSH to a host and port as the server sees them, so localhost:5901 on the far end is exactly the listener you found. Opening the listener up is the other route, for a LAN you trust.

  1. Forward local port 5901 to port 5901 on the server. The leading localhost keeps the forwarded port on your machine only:

    get past a localhost-only listener
    ssh -L localhost:5901:localhost:5901 <user>@<server-host>
  2. Leave that open and, in a second terminal, point the viewer at display 1 on your own loopback:

    get past a localhost-only listener
    xtigervncviewer localhost:1

    Or let the viewer build the tunnel itself. -via runs the same ssh -L for you:

    get past a localhost-only listener
    xtigervncviewer -via <user>@<server-host> localhost:1
  3. To take direct connections instead, add this line to ~/.config/tigervnc/config.pl for the session user, or to the system-wide /etc/tigervnc/vncserver-config-defaults, then restart the unit:

    get past a localhost-only listener
    $localhost = "no";
    get past a localhost-only listener
    sudo systemctl restart tigervncserver@:1.service

    For a session you start by hand, tigervncserver :1 -localhost no does the same. With localhost off and no $SecurityTypes line, the wrapper offers VncAuth,TLSVnc, and the viewer picks one type from that list, so any viewer can still take plain VncAuth and leave the session unencrypted. To require TLS, set $SecurityTypes to TLS or X509 types only. To bind to one address only, pass the Xtigervnc option -interface <ip-address>; without it the server listens on every interface.

After the restart, ss -tlnp shows 0.0.0.0:5901 or [::]:5901 where it used to say 127.0.0.1:5901, and the session log's listening line switches from local to all interfaces. If it still shows 127.0.0.1, look for a $localhost line in /etc/tigervnc/vncserver-config-mandatory, which is read last and beats yours. A remote viewer that still can't get in now has the firewall to deal with.

Timed out, or no route to host? Look at the firewall

A firewall that drops your packets, or rejects them with an ICMP error, doesn't produce Connection refused, and which error you get depends on which it does. One that drops them leaves the viewer waiting until it gives up, which Windows viewers report as error 10060, a timeout. If the host runs firewalld, as RHEL does, it rejects anything no rule matches by default and sends an error back, so a Linux viewer fails at once with Unable to connect to socket: No route to host (113). That reads like a routing fault, but it's how the Linux kernel reports a filtered port.

  1. Allow the vnc-server service:

    timed out, or no route to host? look at the firewall
    sudo firewall-cmd --permanent --add-service=vnc-server
  2. Reload so the permanent rule becomes the running one, then check that vnc-server now shows among the zone's services:

    timed out, or no route to host? look at the firewall
    sudo firewall-cmd --reload
    sudo firewall-cmd --list-all

The vnc-server service only opens ports 5900 through 5903, which covers displays :0 to :3. Display 4 and up need their own port rule, and the same reload afterwards:

timed out, or no route to host? look at the firewall
sudo firewall-cmd --permanent --add-port=5904/tcp

When the timeout or No route to host turns into Connection refused, your packets are getting through the firewall and the listener is the problem again.

What changes on RHEL, Windows and a Mac

RHEL

RHEL 8 uses the same /etc/tigervnc/vncserver.users mapping, but the password tool is vncpasswd and the unit is vncserver@:

rhel
sudo systemctl enable --now vncserver@:1

Upstream ships the localhost line commented out in /etc/tigervnc/vncserver-config-defaults, so a RHEL session listens on every interface until you uncomment it. So on RHEL, suspect the firewall before the bind address.

Windows

From a Windows client, Test-NetConnection does the job of nc -vz and answers TcpTestSucceeded : True or False:

windows
Test-NetConnection <server-host> -Port 5901

On a Windows server, open an elevated prompt and list the listening ports with the executable that owns each:

windows
netstat -abno

Each row reads Proto, Local Address, Foreign Address, State and PID, and -b prints the owning executable's name in square brackets under it, so you can see which VNC server holds the port. Look for the VNC port, 5900 by default, in the Local Address column. No row means the server isn't running, a row on another port means the viewer dials the wrong one, and 127.0.0.1 in front of the port means a localhost-only listener. The PID in the last column matches the Processes tab in Task Manager.

A Mac

With Screen Sharing off, nothing on the Mac takes VNC callers. Choose Apple menu > System Settings, click General, then Sharing, and turn on Screen Sharing.

For a non-Apple viewer, click the Info button next to Screen Sharing, turn on "VNC viewers may control screen with password" and set a VNC password. Dial the Mac as <mac-host>::5900, and run nc -vz <mac-host> 5900 from the client before you blame the viewer.

Logs to grab before you escalate

The service-managed session runs tigervncserver -fg, and the wrapper writes the session log to ~/.config/tigervnc/<host>:1.log in the session owner's home. The line that settles the bind question is the server's own listening message, which reads local for a localhost-only session and all for every interface:

logs to grab before you escalate
grep 'Listening for VNC connections' ~/.config/tigervnc/*:1.log

The unit's start and exit messages are in the journal. A session that died at start leaves a tigervncserver exited with status= line there with the exit code:

logs to grab before you escalate
sudo journalctl -u tigervncserver@:1.service -b

For a session you start by hand, tigervncserver passes options it doesn't know through to Xtigervnc, so you can raise the log level from its default of 30:

logs to grab before you escalate
tigervncserver :1 -Log '*:stderr:100'

Hand these over with the ticket:

  • the viewer's exact message, copied from its window on the client;
  • the nc -vz or Test-NetConnection result from the client;
  • the ss -tlnp or netstat -abno line from the server;
  • the session log and the unit's journal.

If the listener sits on a non-local address on the port you dial and the firewall allows that port, but you're still refused, that's the point to escalate.

If your listener turned out to be on 127.0.0.1, make one call before you change anything: is the network between you and the server one you trust? If not, leave the listener alone and tunnel in with ssh -L. Only on a LAN you trust is $localhost = "no"; the right fix.

FAQs

Which configuration files does a service-managed TigerVNC session read on Debian trixie?

Three, in this order: /etc/tigervnc/vncserver-config-defaults, the session user's $HOME/.config/tigervnc/config.pl, then /etc/tigervnc/vncserver-config-mandatory. A service-managed tigervncsession reads them in that order, so the mandatory file wins, and a $localhost line there overrides whatever the user set. To see which of the three exist on your host:

which configuration files does a service-managed tigervnc
ls -l /etc/tigervnc/vncserver-config-defaults $HOME/.config/tigervnc/config.pl /etc/tigervnc/vncserver-config-mandatory

Each file that exists prints with its permissions and size, and each missing one prints No such file or directory.

Does a wrong VNC password show up as connection refused?

No. A refusal comes before any VNC traffic, and a password check needs the connection to be up already. With a wrong password you get as far as the password prompt, and the TigerVNC viewer then reports Failed to authenticate with the server with the server's reason, Authentication failed, underneath. That message means the port, the listener and the firewall all work; set the password again with tigervncpasswd as the session user.