[PR #2821] fix: remove unused launchd socket listener on TCP port 5959 (macOS) #2962

Open
opened 2026-10-14 21:06:31 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/amnezia-vpn/amnezia-client/pull/2821
Author: @luckyevildev
Created: 7/9/2026
Status: 🔄 Open

Base: dev ← Head: fix/macos-remove-unused-launchd-socket


📝 Commits (1)

  • 38c9cd4 fix: remove unused launchd socket listener on TCP port 5959 (macOS)

📊 Changes

1 file changed (+0 additions, -12 deletions)

View changed files

📝 deploy/data/macos/AmneziaVPN.plist (+0 -12)

📄 Description

Problem

On macOS, after installing AmneziaVPN, TCP port 5959 is open as root on all interfaces (*:5959):

$ sudo lsof -iTCP:5959 -sTCP:LISTEN
COMMAND PID USER   TYPE NAME
launchd   1 root   IPv4 *:5959 (LISTEN)

The cause is the Sockets/Listeners section in deploy/data/macos/AmneziaVPN.plist (present since the original installer commit a2a5caf, Dec 2020). It tells launchd to open a TCP socket on port 5959 on behalf of AmneziaVPN-service. Since no SockNodeName is specified, launchd binds to the wildcard address — the port is reachable from the local network.

Why it is dead config

  • The service never takes ownership of the socket. There is no launch_activate_socket() / liblaunch check-in anywhere in the codebase (including vendored code), and no code references port 5959 at all.
  • All GUI ↔ service IPC uses local unix domain sockets, not TCP: QLocalServer on amnezia::getIpcServiceUrl() → /tmp/local:AmneziaVpnIpcInterface (ipc/ipc.h, service/server/localserver.cpp), client side via QtRemoteObjects local: URLs (client/core/utils/ipcClient.cpp). The QtService control channel (service/src/qtunixserversocket.cpp) is also an AF_UNIX socket despite subclassing QTcpServer.
  • Socket activation is not used even conceptually: the daemon has plain KeepAlive=true + RunAtLoad=true, so launchd starts it at boot and keeps it running regardless of the Sockets key.

Impact of the leftover

  • Unnecessary attack surface: a root-owned listening port exposed to the LAN (connections queue in launchd's accept backlog and are never serviced).
  • Trivial network fingerprinting of machines running AmneziaVPN — undesirable for a censorship-circumvention tool.

Fix

Remove the Sockets dict from the plist. Verified:

  • plutil -lint passes.
  • post_install.sh / post_uninstall.sh and cmake/CPack.cmake treat the plist as an opaque file (copy/launchctl bootstrap by label) and do not depend on the Sockets key.
  • With KeepAlive=true + RunAtLoad=true the daemon lifecycle is unchanged; only the dangling wildcard listener disappears.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/amnezia-vpn/amnezia-client/pull/2821 **Author:** [@luckyevildev](https://github.com/luckyevildev) **Created:** 7/9/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `fix/macos-remove-unused-launchd-socket` --- ### 📝 Commits (1) - [`38c9cd4`](https://github.com/amnezia-vpn/amnezia-client/commit/38c9cd4f7d4c297cc257680f11ef1a56e12132d4) fix: remove unused launchd socket listener on TCP port 5959 (macOS) ### 📊 Changes **1 file changed** (+0 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `deploy/data/macos/AmneziaVPN.plist` (+0 -12) </details> ### 📄 Description ## Problem On macOS, after installing AmneziaVPN, TCP port **5959** is open as **root on all interfaces** (`*:5959`): ``` $ sudo lsof -iTCP:5959 -sTCP:LISTEN COMMAND PID USER TYPE NAME launchd 1 root IPv4 *:5959 (LISTEN) ``` The cause is the `Sockets`/`Listeners` section in `deploy/data/macos/AmneziaVPN.plist` (present since the original installer commit a2a5caf, Dec 2020). It tells launchd to open a TCP socket on port 5959 on behalf of `AmneziaVPN-service`. Since no `SockNodeName` is specified, launchd binds to the wildcard address — the port is reachable from the local network. ## Why it is dead config - **The service never takes ownership of the socket.** There is no `launch_activate_socket()` / liblaunch check-in anywhere in the codebase (including vendored code), and no code references port 5959 at all. - **All GUI ↔ service IPC uses local unix domain sockets**, not TCP: `QLocalServer` on `amnezia::getIpcServiceUrl()` → `/tmp/local:AmneziaVpnIpcInterface` (`ipc/ipc.h`, `service/server/localserver.cpp`), client side via QtRemoteObjects `local:` URLs (`client/core/utils/ipcClient.cpp`). The QtService control channel (`service/src/qtunixserversocket.cpp`) is also an `AF_UNIX` socket despite subclassing `QTcpServer`. - **Socket activation is not used even conceptually**: the daemon has plain `KeepAlive=true` + `RunAtLoad=true`, so launchd starts it at boot and keeps it running regardless of the `Sockets` key. ## Impact of the leftover - Unnecessary attack surface: a root-owned listening port exposed to the LAN (connections queue in launchd's accept backlog and are never serviced). - Trivial network fingerprinting of machines running AmneziaVPN — undesirable for a censorship-circumvention tool. ## Fix Remove the `Sockets` dict from the plist. Verified: - `plutil -lint` passes. - `post_install.sh` / `post_uninstall.sh` and `cmake/CPack.cmake` treat the plist as an opaque file (copy/`launchctl bootstrap` by label) and do not depend on the `Sockets` key. - With `KeepAlive=true` + `RunAtLoad=true` the daemon lifecycle is unchanged; only the dangling wildcard listener disappears. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#2962
No description provided.