Skip to content
Approvalens

Guides · 6 min read

Port 631 Open on Your Server? Remove CUPS or Bind It to Localhost

Why a VPS has CUPS and cups-browsed listening on port 631, what the 2024 cups-browsed vulnerabilities allowed, and how to remove it or keep it local and verify.

By the Approvalens team

Port 631 is IPP, the printing protocol. If something is listening on it, that's CUPS (cupsd, on TCP) or its helper cups-browsed (on UDP), the print system from desktop Linux. A web server has no printer. Unless you know why it's there, remove it. If you do need it, make sure it only listens on 127.0.0.1 and that cups-browsed is off.

Why a server has CUPS at all

A plain Ubuntu Server install doesn't need it; Ubuntu's server docs treat CUPS as something you install yourself with sudo apt install cups. When it shows up on a VPS, it usually came in with something else:

  • The server was installed from a desktop image, or the provider's template is a "desktop" or "with GUI" one.
  • Someone installed a desktop environment for remote desktop access. Ubuntu's desktop metapackages, such as ubuntu-desktop-minimal, depend on cups.
  • A package pulled printing support in as a dependency.

None of these is a problem in itself. The problem is a service listening on the network that nobody looks after.

The 2024 cups-browsed vulnerabilities

In September 2024, four CVEs were published together: CVE-2024-47076, CVE-2024-47175, CVE-2024-47176 and CVE-2024-47177. Ubuntu's write-up explains the chain: an attacker can "trick CUPS into generating an attacker-controlled PPD" file whose commands run as the lp user when a print job is sent. The entry point is cups-browsed. Ubuntu's CVE-2024-47176 page: "cups-browsed binds to INADDR_ANY:631, causing it to trust any packet from any source." OpenPrinting's advisory sums up the result: it "enables an attacker to execute arbitrary commands remotely on the target machine without authentication when a print job is started."

Ubuntu shipped fixes for "cups-browsed, cups-filters, libcupsfilters and libppd packages for all supported Ubuntu LTS releases" (same blog post, published 26 September 2024), and USN-7041-1 covers the cups package itself. So an updated server isn't wide open to that chain. But patched or not, a print discovery service answering the whole internet on a web server is exposure with no benefit.

Check what is listening

sudo ss -tulpn | grep ':631'

-t TCP, -u UDP, -l listening, -p the owning process, -n numbers instead of names (ss). A typical result on a server that got CUPS from a desktop install:

udp   UNCONN 0      0            0.0.0.0:631        0.0.0.0:*    users:(("cups-browsed",pid=1187,fd=7))
tcp   LISTEN 0      4096       127.0.0.1:631        0.0.0.0:*    users:(("cupsd",pid=1102,fd=7))
tcp   LISTEN 0      4096           [::1]:631           [::]:*    users:(("cupsd",pid=1102,fd=6))

How to read it:

  • 0.0.0.0:631 on UDP, cups-browsed. Listening on every interface. This is the CVE-2024-47176 entry point.
  • 127.0.0.1:631 and [::1]:631 on TCP, cupsd. Loopback only, reachable from the server itself, not from the internet. That matches Ubuntu's docs: "By default on Ubuntu, CUPS listens only on the loopback interface at IP address 127.0.0.1."
  • 0.0.0.0:631 or *:631 on TCP. Someone changed cupsd.conf (a Port 631 line means "Listen on port 631 on all interfaces"). The admin web interface is now facing the network.

Also check whether ufw would stop it: sudo ufw status verbose. With ufw active and a default of deny (incoming), outside packets to 631 are dropped even while the service listens. Without a firewall, every listening port is open. Treat the firewall as the second layer, not the fix.

Terminal output of ss -tulpn filtered to port 631 before and after: before, cups-browsed listens on UDP 0.0.0.0:631 marked public, and cupsd listens on TCP 127.0.0.1:631 and [::1]:631 marked local only; after removing the packages the same command prints nothing
Before: the UDP line on 0.0.0.0 is the public one. After: nothing listens on 631 at all.

Option 1: remove it (most servers)

Before you remove anything, see what depends on it:

apt-cache rdepends --installed cups cups-browsed

Then stop and remove the discovery service first, then the print server:

sudo systemctl disable --now cups-browsed
sudo apt purge cups-browsed
sudo apt purge cups cups-daemon

Read the list apt prints before you confirm. If it includes ubuntu-desktop-minimal or ubuntu-desktop, that's the metapackage that brought CUPS in. On a server you only reach over SSH, removing a metapackage is fine, but the next apt autoremove will then offer to remove a large part of the desktop it held in place. Read that list too; if you use the remote desktop, stop here and take option 2 instead.

Option 2: keep CUPS, but local only

If something on the server really prints (an app that sends invoices to an office printer, for example), keep cupsd and close the network side.

Turn off cups-browsed; you don't need printer discovery on a server:

sudo systemctl disable --now cups-browsed

Then check /etc/cups/cupsd.conf:

sudo grep -nE '^\s*(Port|Listen|Browsing)' /etc/cups/cupsd.conf

You want Listen localhost:631 (plus the socket line Listen /run/cups/cups.sock) and no Port 631. Replace any Port 631 or Listen *:631 with Listen localhost:631. Set Browsing No; the cupsd.conf reference says Browsing controls whether "shared printers are advertised". Then:

sudo systemctl restart cups.service

If you'd rather keep the packages installed but have nothing running, disable all of its units, including the socket and path units that can start it on demand:

sudo systemctl disable --now cups.service cups.socket cups.path cups-browsed.service

Verify

sudo ss -tulpn | grep ':631'

After option 1, this prints nothing. After option 2, you should see only 127.0.0.1:631 and [::1]:631 lines for cupsd, and no UDP line. Also confirm the packages you kept are current:

apt policy cups cups-browsed cups-filters

The Installed version should match Candidate. If not, sudo apt update && sudo apt upgrade.

Do the same check for every port

CUPS is just the most common surprise. Run sudo ss -tulpn without the grep and ask of every line on 0.0.0.0 or [::]: do I know what this is, and does the internet need it? Databases (3306, 5432, 6379, 27017) and admin panels are the ones that hurt. Docker-published ports also show up here and skip ufw entirely; the SSH and UFW guide explains how to bind them to 127.0.0.1. For the login side, see fail2ban for WordPress and SSH, and if you suspect the server was already used against you, the hacked site guide covers what to check.

Get told when a port opens

The Approvalens server agent lists every listening port, marks which are public, flags a public CUPS port as one to close, and e-mails you when a new port starts listening.

FAQ

Is port 631 open to the internet if ss shows 127.0.0.1:631?

No. 127.0.0.1 and [::1] are loopback addresses, reachable only from the server itself. 0.0.0.0, [::] or the server's public IP mean it listens on the network.

I patched in 2024. Do I still need to remove cups-browsed?

The patches fixed the known bugs. Removing it removes the whole category: a discovery service on a web server has no job to do. If you keep it, turn it off with systemctl disable --now cups-browsed.

Will removing CUPS break anything?

On a server that doesn't print, normally not. apt shows what it will remove before you confirm; that list is the answer. Desktop metapackages are the one thing to read carefully.

My firewall blocks 631. Is that enough?

It stops outside traffic as long as the firewall is on and the rule stays. But a service you don't use is one more thing to patch and one more way in if the firewall changes. Remove it or keep it on localhost, and keep the firewall as well.

Spotted something out of date or wrong? Tell us and we'll correct it.

Read this guide in Turkish →

Free scan

Check your own site

The free scan reads the first 50 pages and shows your score and every problem it finds.

First 50 pages free · no sign-up · no card

All guides