[GH-ISSUE #3109] Endless connection on linux/arch (killswitch enabled by default fault) #1441

Open
opened 2026-10-13 20:42:33 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @DimitriiKorol on GitHub (Sep 1, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3109

Describe the bug
Trying to connect fresh installed client to private server cause infinite "connecting" message.

To Reproduce
Steps to reproduce the behavior:

  1. Install from https://github.com/amnezia-vpn/amnezia-client/releases/download/5.0.1.5/AmneziaVPN_5.0.1.5_linux_x64.run
  2. Run app and add private server via url or link
  3. Click "Connect"
  4. See infinite "Connecting" (Connection not working)

Expected behavior
See "Connected" and working connection

Log files
QSystemTrayIcon::setVisible: No Icon set
Logger::setServiceLogsEnabled(): Logs transitioned to be disabled
Updated website URL: "https://amnezia.org"
Started AmneziaVPN version 5.0.1.5 7d4f3e0
Arch Linux (x86_64)
QIODevice::read (QNetworkReplyHttpImpl): device not open
CryptoUtils::decryptAes256Cbc EVP_DecryptFinal_ex failed: "error:1C80006B:Provider routines::wrong final block length"
failed to decrypt the data
QIODevice::read (QNetworkReplyHttpImpl): device not open
CryptoUtils::decryptAes256Cbc EVP_DecryptFinal_ex failed: "error:1C80006B:Provider routines::wrong final block length"
QNetworkReply::TimeoutError
[2026-09-01 07:59:37.022Z] [ERROR] AmneziaVPN UpdateController : Gateway request failed, error code: 1103
"Trying to connect to VPN, server id is 1234567788990-whatever, container is amnezia-awg, route mode is" amnezia::route_mode_ns::VpnOnlyForwardSites
"Site split tunneling is disabled, route mode is 0"
"App split tunneling is disabled, route mode is 0"
[2026-09-01 08:00:26.008Z] [DEBUG] AmneziaVPN LocalSocketController : Initializing
[2026-09-01 08:00:26.008Z] [DEBUG] AmneziaVPN LocalSocketController : Connecting to: /var/run/amneziavpn/daemon.socket
[2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Daemon connected
[2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Check status
[2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Reading
[2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Parse command: status

Desktop (please complete the following information):

  • OS: Arch liniux x64 KDE Plasma latest
  • Client Version 5.0.1.5
  • Protocol AWG2.0

Additional context
Funny thing, I solved problem by disabling KillSwitch option. Seems like KillSwitch option starting to work before connection is established, preventing any connections to happen. Cause internet went down while i was trying to connect. Please disable by default this option in linux distro for better user experience.

Originally created by @DimitriiKorol on GitHub (Sep 1, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/3109 **Describe the bug** Trying to connect fresh installed client to private server cause infinite "connecting" message. **To Reproduce** Steps to reproduce the behavior: 1. Install from https://github.com/amnezia-vpn/amnezia-client/releases/download/5.0.1.5/AmneziaVPN_5.0.1.5_linux_x64.run 2. Run app and add private server via url or link 3. Click "Connect" 4. See infinite "Connecting" (Connection not working) **Expected behavior** See "Connected" and working connection **Log files** QSystemTrayIcon::setVisible: No Icon set Logger::setServiceLogsEnabled(): Logs transitioned to be disabled Updated website URL: "https://amnezia.org" Started AmneziaVPN version 5.0.1.5 7d4f3e0 Arch Linux (x86_64) QIODevice::read (QNetworkReplyHttpImpl): device not open CryptoUtils::decryptAes256Cbc EVP_DecryptFinal_ex failed: "error:1C80006B:Provider routines::wrong final block length" failed to decrypt the data QIODevice::read (QNetworkReplyHttpImpl): device not open CryptoUtils::decryptAes256Cbc EVP_DecryptFinal_ex failed: "error:1C80006B:Provider routines::wrong final block length" QNetworkReply::TimeoutError [2026-09-01 07:59:37.022Z] [ERROR] AmneziaVPN UpdateController : Gateway request failed, error code: 1103 "Trying to connect to VPN, server id is 1234567788990-whatever, container is amnezia-awg, route mode is" amnezia::route_mode_ns::VpnOnlyForwardSites "Site split tunneling is disabled, route mode is 0" "App split tunneling is disabled, route mode is 0" [2026-09-01 08:00:26.008Z] [DEBUG] AmneziaVPN LocalSocketController : Initializing [2026-09-01 08:00:26.008Z] [DEBUG] AmneziaVPN LocalSocketController : Connecting to: /var/run/amneziavpn/daemon.socket [2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Daemon connected [2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Check status [2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Reading [2026-09-01 08:00:26.009Z] [DEBUG] AmneziaVPN LocalSocketController : Parse command: status **Desktop (please complete the following information):** - OS: Arch liniux x64 KDE Plasma latest - Client Version 5.0.1.5 - Protocol AWG2.0 **Additional context** Funny thing, I solved problem by disabling KillSwitch option. Seems like KillSwitch option starting to work before connection is established, preventing any connections to happen. Cause internet went down while i was trying to connect. Please disable by default this option in linux distro for better user experience.
Author
Owner

@HeisLuka commented on GitHub (Sep 8, 2026):

I checked this against the exact 5.0.1.5 source and current dev.

There is indeed a Kill Switch lifecycle problem on Linux, but I don't think the strongest explanation is simply “the Kill Switch blocks the VPN server”.

First, one part of the report is confirmed: the regular Kill Switch is enabled by default on a fresh configuration:

return value("Conf/killSwitchEnabled", true).toBool();

(strictKillSwitchEnabled is a different mode and defaults to false.)

However, the WireGuard activation path does attempt to preserve access to the VPN endpoint.

Before activation the server hostname is resolved, and LocalSocketController puts the server IP into:

excludedAddresses

For a full-tunnel configuration, WireguardUtilsLinux::addInterface() then builds approximately:

blockAll = true
allowNets = true
allowAddrs = excludedAddresses

so the VPN server endpoint is intended to pass through 110.allowNets before the general block rule.

The more concerning part is when this firewall state is committed and what happens if activation subsequently fails.

Current activation ordering is approximately:

create WireGuard interface
set private/AWG interface parameters

ENABLE KILL SWITCH
|
| from WireguardUtilsLinux::addInterface()
v

assign interface IP
bring interface UP
create endpoint exclusion route
configure peer/endpoint
configure DNS
add tunnel routes
run platform UP stage
wait for handshake

So Kill Switch enforcement becomes active before most of the operations that are required for the tunnel to become usable.

This by itself can be valid if activation is transactional and failure rolls the firewall state back.

But I cannot find that rollback on Linux.

Daemon::activate() has many failure paths after addInterface():

if (!iputils()->addInterfaceIPs(config))
return false;

if (!iputils()->setMTUAndUp(config))
return false;

if (!wgutils()->updatePeer(config))
return false;

if (!maybeUpdateResolvers(config))
return false;

if (!wgutils()->updateRoutePrefix(ip))
return false;

and its failure guard only emits:

activationFailure();

On Windows there is an explicit rollback handler:

connect(this, &WindowsDaemon::activationFailure,
this {
m_firewallManager->disableKillSwitch();
});

but LinuxDaemon currently has no equivalent handler.

The Linux Kill Switch is disabled by WireguardUtilsLinux::deleteInterface(), but the early failure paths above do not call deleteInterface().

Therefore this deterministic countertest appears possible:

GIVEN
killSwitchEnabled = true
full tunnel

WHEN
addInterface() succeeds
-> blockAll firewall becomes active

AND
the next activation phase fails
e.g. addInterfaceIPs() returns false

THEN
activate() fails

CURRENT SUSPECTED POSTCONDITION
VPN not connected
AND Amnezia blockAll firewall still active

EXPECTED
activation failure rolls back all transient
normal-Kill-Switch state

This seems particularly relevant to the report because it naturally produces:

tunnel never becomes usable

  • ordinary Internet disappears
  • disabling Kill Switch restores connectivity

without requiring the VPN endpoint exception itself to be missing.

I would make activation an explicit transaction:

PREPARE
resolve endpoint
establish physical endpoint route/exclusion
prepare firewall candidate

ACTIVATE
create/configure interface
configure peer
configure routes/DNS

COMMIT
enable final Kill Switch policy
verify tunnel readiness

FAILURE before COMMIT
remove transient routes/interface
restore DNS
rollback normal Kill Switch

Or, if the product deliberately wants leak protection during the connection attempt, the firewall can become active earlier, but it still needs a transaction guard:

temporary CONNECTING policy
-> allow VPN endpoint + required bootstrap traffic

handshake/readiness succeeds
-> promote to CONNECTED Kill Switch policy

activation fails
-> rollback temporary policy

Strict Kill Switch should remain a separate case: by definition it may intentionally keep traffic blocked after a failed/disconnected tunnel. The regular Kill Switch should not accidentally acquire strict-mode semantics merely because activation failed halfway through.

Regression tests I would add:

  1. kill switch ON; addInterfaceIPs fails
    expected:
    activation failure
    no persistent normal blockAll state

  2. kill switch ON; updatePeer fails
    same rollback invariant

  3. kill switch ON; DNS setup fails
    same rollback invariant

  4. kill switch ON; route installation fails
    same rollback invariant

  5. successful activation
    endpoint remains reachable through physical underlay
    tunnel reaches readiness
    Kill Switch remains active

  6. strict Kill Switch ON + activation failure
    blocking persists according to strict-mode policy

I would also log the transaction boundary explicitly:

firewall_state=CONNECTING
endpoint_exception=
interface_created=yes/no
peer_configured=yes/no
routes_ready=yes/no
handshake_ready=yes/no
activation_result=<...>
firewall_rollback=<yes/no>

So I would not solve #3109 only by changing the default to OFF.

Changing the default may hide the symptom, but the stronger invariant should be:

NORMAL_KILL_SWITCH + ACTIVATION_FAILURE
=>
no leaked partial firewall transaction

while:

STRICT_KILL_SWITCH + ACTIVATION_FAILURE

can intentionally retain blocking semantics.

<!-- gh-comment-id:5588593113 --> @HeisLuka commented on GitHub (Sep 8, 2026): I checked this against the exact 5.0.1.5 source and current dev. There is indeed a Kill Switch lifecycle problem on Linux, but I don't think the strongest explanation is simply “the Kill Switch blocks the VPN server”. First, one part of the report is confirmed: the regular Kill Switch is enabled by default on a fresh configuration: return value("Conf/killSwitchEnabled", true).toBool(); (strictKillSwitchEnabled is a different mode and defaults to false.) However, the WireGuard activation path does attempt to preserve access to the VPN endpoint. Before activation the server hostname is resolved, and LocalSocketController puts the server IP into: excludedAddresses For a full-tunnel configuration, WireguardUtilsLinux::addInterface() then builds approximately: blockAll = true allowNets = true allowAddrs = excludedAddresses so the VPN server endpoint is intended to pass through 110.allowNets before the general block rule. The more concerning part is when this firewall state is committed and what happens if activation subsequently fails. Current activation ordering is approximately: create WireGuard interface set private/AWG interface parameters ENABLE KILL SWITCH | | from WireguardUtilsLinux::addInterface() v assign interface IP bring interface UP create endpoint exclusion route configure peer/endpoint configure DNS add tunnel routes run platform UP stage wait for handshake So Kill Switch enforcement becomes active before most of the operations that are required for the tunnel to become usable. This by itself can be valid if activation is transactional and failure rolls the firewall state back. But I cannot find that rollback on Linux. Daemon::activate() has many failure paths after addInterface(): if (!iputils()->addInterfaceIPs(config)) return false; if (!iputils()->setMTUAndUp(config)) return false; if (!wgutils()->updatePeer(config)) return false; if (!maybeUpdateResolvers(config)) return false; if (!wgutils()->updateRoutePrefix(ip)) return false; and its failure guard only emits: activationFailure(); On Windows there is an explicit rollback handler: connect(this, &WindowsDaemon::activationFailure, [this]() { m_firewallManager->disableKillSwitch(); }); but LinuxDaemon currently has no equivalent handler. The Linux Kill Switch is disabled by WireguardUtilsLinux::deleteInterface(), but the early failure paths above do not call deleteInterface(). Therefore this deterministic countertest appears possible: GIVEN killSwitchEnabled = true full tunnel WHEN addInterface() succeeds -> blockAll firewall becomes active AND the next activation phase fails e.g. addInterfaceIPs() returns false THEN activate() fails CURRENT SUSPECTED POSTCONDITION VPN not connected AND Amnezia blockAll firewall still active EXPECTED activation failure rolls back all transient normal-Kill-Switch state This seems particularly relevant to the report because it naturally produces: tunnel never becomes usable + ordinary Internet disappears + disabling Kill Switch restores connectivity without requiring the VPN endpoint exception itself to be missing. I would make activation an explicit transaction: PREPARE resolve endpoint establish physical endpoint route/exclusion prepare firewall candidate ACTIVATE create/configure interface configure peer configure routes/DNS COMMIT enable final Kill Switch policy verify tunnel readiness FAILURE before COMMIT remove transient routes/interface restore DNS rollback normal Kill Switch Or, if the product deliberately wants leak protection during the connection attempt, the firewall can become active earlier, but it still needs a transaction guard: temporary CONNECTING policy -> allow VPN endpoint + required bootstrap traffic handshake/readiness succeeds -> promote to CONNECTED Kill Switch policy activation fails -> rollback temporary policy Strict Kill Switch should remain a separate case: by definition it may intentionally keep traffic blocked after a failed/disconnected tunnel. The regular Kill Switch should not accidentally acquire strict-mode semantics merely because activation failed halfway through. Regression tests I would add: 1. kill switch ON; addInterfaceIPs fails expected: activation failure no persistent normal blockAll state 2. kill switch ON; updatePeer fails same rollback invariant 3. kill switch ON; DNS setup fails same rollback invariant 4. kill switch ON; route installation fails same rollback invariant 5. successful activation endpoint remains reachable through physical underlay tunnel reaches readiness Kill Switch remains active 6. strict Kill Switch ON + activation failure blocking persists according to strict-mode policy I would also log the transaction boundary explicitly: firewall_state=CONNECTING endpoint_exception=<ip> interface_created=yes/no peer_configured=yes/no routes_ready=yes/no handshake_ready=yes/no activation_result=<...> firewall_rollback=<yes/no> So I would not solve #3109 only by changing the default to OFF. Changing the default may hide the symptom, but the stronger invariant should be: NORMAL_KILL_SWITCH + ACTIVATION_FAILURE => no leaked partial firewall transaction while: STRICT_KILL_SWITCH + ACTIVATION_FAILURE can intentionally retain blocking semantics.
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#1441
No description provided.