[GH-ISSUE #2985] Windows: CIDR prefixes are removed when exporting split-tunneling routes #1365

Open
opened 2026-10-13 20:41:00 +00:00 by bsakaguchi · 5 comments
Owner

Originally created by @lexer85-hub on GitHub (Aug 14, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2985

Title: Windows: CIDR prefixes are removed when exporting split-tunneling routes

Hello!

I found an issue in Amnezia VPN 5.0.0.5 for Windows.

Steps to reproduce:

  1. Open site-based split tunneling.
  2. Add 192.168.0.0/16 and 10.20.30.0/24.
  3. Export the list as JSON.

The exported JSON contains:

[
  {
    "hostname": "192.168.0.0",
    "ip": ""
  },
  {
    "hostname": "10.20.30.0",
    "ip": ""
  }
]

Expected result: the CIDR prefixes /16 and /24 are preserved.

Actual result: the prefixes are removed. As a result, the exported file loses the subnet sizes and cannot reliably restore the original routes when imported.

The same CIDR routes are exported correctly in the macOS version.

Please check CIDR export and import in the Windows client.

Originally created by @lexer85-hub on GitHub (Aug 14, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2985 Title: Windows: CIDR prefixes are removed when exporting split-tunneling routes Hello! I found an issue in Amnezia VPN 5.0.0.5 for Windows. Steps to reproduce: 1. Open site-based split tunneling. 2. Add `192.168.0.0/16` and `10.20.30.0/24`. 3. Export the list as JSON. The exported JSON contains: ```json [ { "hostname": "192.168.0.0", "ip": "" }, { "hostname": "10.20.30.0", "ip": "" } ] ``` Expected result: the CIDR prefixes `/16` and `/24` are preserved. Actual result: the prefixes are removed. As a result, the exported file loses the subnet sizes and cannot reliably restore the original routes when imported. The same CIDR routes are exported correctly in the macOS version. Please check CIDR export and import in the Windows client.
Author
Owner

@lexer85-hub commented on GitHub (Aug 14, 2026):

Title: Windows: CIDR prefixes are removed and local subnet exclusion is routed through VPN

Hello!

I found two related issues with site-based split tunneling in Amnezia VPN 5.0.0.5 for Windows.

Steps to reproduce:

  1. Open site-based split tunneling.
  2. Select “Addresses from the list should not be opened through VPN.”
  3. Add 192.168.0.0/16 and 10.20.30.0/24.
  4. Export the list as JSON.

The exported JSON contains:

[
  {
    "hostname": "192.168.0.0",
    "ip": ""
  },
  {
    "hostname": "10.20.30.0",
    "ip": ""
  }
]

Expected result: the CIDR prefixes /16 and /24 are preserved.

Actual result: the prefixes are removed. As a result, the exported file loses the subnet sizes and cannot reliably restore the original routes when imported.

There is also a routing issue with local network exclusions. I added my local subnet 192.168.1.0/24 because connecting to the VPN disconnects my RDP session.

After connecting, the Windows routing table contains two routes for the subnet:

192.168.1.0/24 via physical LAN interface 192.168.1.137 — metric 281
192.168.1.0/24 via VPN interface 10.8.1.114             — metric 5

Amnezia also creates this host route through the VPN interface:

192.168.1.137/32 via VPN interface 10.8.1.114 — metric 5

The VPN route has a higher priority, even though 192.168.1.0/24 is configured to bypass the VPN. As a result, local traffic is routed through the VPN and the RDP session is disconnected.

Expected result: the excluded local subnet should remain routed through the physical LAN interface.

The same CIDR routes are exported correctly in the macOS version.

Please check CIDR export and local subnet exclusion routing in the Windows client.

<!-- gh-comment-id:5287849812 --> @lexer85-hub commented on GitHub (Aug 14, 2026): Title: Windows: CIDR prefixes are removed and local subnet exclusion is routed through VPN Hello! I found two related issues with site-based split tunneling in Amnezia VPN 5.0.0.5 for Windows. Steps to reproduce: 1. Open site-based split tunneling. 2. Select “Addresses from the list should not be opened through VPN.” 3. Add `192.168.0.0/16` and `10.20.30.0/24`. 4. Export the list as JSON. The exported JSON contains: ```json [ { "hostname": "192.168.0.0", "ip": "" }, { "hostname": "10.20.30.0", "ip": "" } ] ``` Expected result: the CIDR prefixes `/16` and `/24` are preserved. Actual result: the prefixes are removed. As a result, the exported file loses the subnet sizes and cannot reliably restore the original routes when imported. There is also a routing issue with local network exclusions. I added my local subnet `192.168.1.0/24` because connecting to the VPN disconnects my RDP session. After connecting, the Windows routing table contains two routes for the subnet: ```text 192.168.1.0/24 via physical LAN interface 192.168.1.137 — metric 281 192.168.1.0/24 via VPN interface 10.8.1.114 — metric 5 ``` Amnezia also creates this host route through the VPN interface: ```text 192.168.1.137/32 via VPN interface 10.8.1.114 — metric 5 ``` The VPN route has a higher priority, even though `192.168.1.0/24` is configured to bypass the VPN. As a result, local traffic is routed through the VPN and the RDP session is disconnected. Expected result: the excluded local subnet should remain routed through the physical LAN interface. The same CIDR routes are exported correctly in the macOS version. Please check CIDR export and local subnet exclusion routing in the Windows client.
Author
Owner

@Kryss295 commented on GitHub (Aug 14, 2026):

same issue it does not matter if you add /24 manually or importing from JSON it always get deleted

<!-- gh-comment-id:5297369902 --> @Kryss295 commented on GitHub (Aug 14, 2026): same issue it does not matter if you add /24 manually or importing from JSON it always get deleted
Author
Owner

@Geskawary234 commented on GitHub (Aug 15, 2026):

I cant even add like 192.168.0.0/16 to my list, /16 just gets removed! So i guess CIDR split tunneling no longer works :(

<!-- gh-comment-id:5304108227 --> @Geskawary234 commented on GitHub (Aug 15, 2026): I cant even add like 192.168.0.0/16 to my list, /16 just gets removed! So i guess CIDR split tunneling no longer works :(
Author
Owner

@devindastries commented on GitHub (Aug 16, 2026):

Same issue confirmed here. I import a list of ~1400 RU CIDR subnets into site-based split tunneling (mode "VPN all except sites") on Windows 10. Every entry ends up as /32 in the Windows route table. Because of that, RU sites (e.g. Ozon) still exit through the VPN and get blocked with HTTP 403. Workaround: putting the subnet into the "ip" field ({"hostname":"dummy","ip":"185.73.192.0/24"}) preserves the mask, since only "hostname" goes through normalizeHostname(). Hoping for a fix in the next stable release.

<!-- gh-comment-id:5308124570 --> @devindastries commented on GitHub (Aug 16, 2026): Same issue confirmed here. I import a list of ~1400 RU CIDR subnets into site-based split tunneling (mode "VPN all except sites") on Windows 10. Every entry ends up as /32 in the Windows route table. Because of that, RU sites (e.g. Ozon) still exit through the VPN and get blocked with HTTP 403. Workaround: putting the subnet into the "ip" field ({"hostname":"dummy","ip":"185.73.192.0/24"}) preserves the mask, since only "hostname" goes through normalizeHostname(). Hoping for a fix in the next stable release.
Author
Owner

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

I rechecked this against current dev.

The original CIDR-prefix loss appears to be fixed already by PR #2973 / commit b575df05 (fix: fixed adding subnet to ip split tunnel).

Before that change, IpSplitTunnelingController::normalizeHostname() unconditionally did effectively:

normalized.split("/").first();

so:

192.168.0.0/16 -> 192.168.0.0
10.20.30.0/24  -> 10.20.30.0

That explains both the reported JSON export and the resulting /32 routes.

Current dev now explicitly preserves a value when it matches ipAddressWithSubnetRegExp():

if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(normalized)) {
    return normalized;
}

The rest of the current path also preserves the prefix:

CIDR hostname
-> stored unchanged
-> exported unchanged
-> imported unchanged
-> addSitesRoutes()
-> routeAddList()

and on Windows RouterWin::routeAddList() derives both the destination address and subnet mask from the CIDR before calling CreateIpForwardEntry().

So for the original title:

"CIDR prefixes are removed when exporting split-tunneling routes"

I would classify this as fixed on current dev.

A useful regression test would be a round-trip:

192.168.0.0/16
10.20.30.0/24

add
-> export
-> clear
-> import
-> connect

and assert that both the exported JSON and the effective Windows routing table still contain /16 and /24.


There is a second issue mentioned later in this thread:

excluded local subnet
-> duplicate lower-metric route through VPN
-> LAN/RDP breaks

That is a separate Windows routing problem rather than a remaining CIDR serialization problem.

Current Windows route-capture code can clone non-default connected routes onto the VPN interface with metric 0, which matches that symptom. I would track that separately (same root area as #2830) rather than keeping #2985 open for both problems.

<!-- gh-comment-id:5608307164 --> @HeisLuka commented on GitHub (Sep 9, 2026): I rechecked this against current `dev`. The original CIDR-prefix loss appears to be fixed already by PR #2973 / commit `b575df05` (`fix: fixed adding subnet to ip split tunnel`). Before that change, `IpSplitTunnelingController::normalizeHostname()` unconditionally did effectively: ```cpp normalized.split("/").first(); ``` so: ```text 192.168.0.0/16 -> 192.168.0.0 10.20.30.0/24 -> 10.20.30.0 ``` That explains both the reported JSON export and the resulting `/32` routes. Current `dev` now explicitly preserves a value when it matches `ipAddressWithSubnetRegExp()`: ```cpp if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(normalized)) { return normalized; } ``` The rest of the current path also preserves the prefix: ```text CIDR hostname -> stored unchanged -> exported unchanged -> imported unchanged -> addSitesRoutes() -> routeAddList() ``` and on Windows `RouterWin::routeAddList()` derives both the destination address and subnet mask from the CIDR before calling `CreateIpForwardEntry()`. So for the original title: **"CIDR prefixes are removed when exporting split-tunneling routes"** I would classify this as fixed on current `dev`. A useful regression test would be a round-trip: ```text 192.168.0.0/16 10.20.30.0/24 add -> export -> clear -> import -> connect ``` and assert that both the exported JSON and the effective Windows routing table still contain `/16` and `/24`. --- There is a second issue mentioned later in this thread: ```text excluded local subnet -> duplicate lower-metric route through VPN -> LAN/RDP breaks ``` That is a separate Windows routing problem rather than a remaining CIDR serialization problem. Current Windows route-capture code can clone non-default connected routes onto the VPN interface with metric 0, which matches that symptom. I would track that separately (same root area as #2830) rather than keeping #2985 open for both problems.
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#1365
No description provided.