mirror of
https://github.com/amnezia-vpn/amneziawg-apple.git
synced 2026-10-13 21:34:11 +00:00
[PR #48] Support ExcludeIPs in wg-quick configs (excluded routes) #48
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
amnezia-vpn/amneziawg-apple#48
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/amnezia-vpn/amneziawg-apple/pull/48
Author: @SlavaLobozov
Created: 9/24/2026
Status: 🔄 Open
Base:
master← Head:feat/exclude-ips-config-key📝 Commits (1)
d36756eSupport ExcludeIPs in wg-quick configs (excluded routes)📊 Changes
11 files changed (+165 additions, -7 deletions)
View changed files
📝
README.md(+23 -0)📝
Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift(+17 -2)📝
Sources/WireGuardApp/Localizable.xcstrings(+48 -0)📝
Sources/WireGuardApp/UI/TunnelViewModel.swift(+17 -0)📝
Sources/WireGuardApp/UI/iOS/ViewController/TunnelDetailTableViewController.swift(+1 -1)📝
Sources/WireGuardApp/UI/iOS/ViewController/TunnelEditTableViewController.swift(+2 -2)📝
Sources/WireGuardApp/UI/macOS/ParseError+WireGuardAppError.swift(+2 -0)📝
Sources/WireGuardApp/UI/macOS/View/highlighter.c(+5 -1)📝
Sources/WireGuardApp/UI/macOS/ViewController/TunnelDetailTableViewController.swift(+1 -1)📝
Sources/WireGuardKit/PeerConfiguration.swift(+4 -0)➕
Tests/WireGuardKitTests/PeerConfigurationExcludeIPsTests.swift(+45 -0)📄 Description
Summary
Adds first-class support for the
ExcludeIPskey in the[Peer]section of wg-quick configs.PeerConfiguration.excludeIPsalready exists andPacketTunnelSettingsGeneratoralready installs it as excluded routes on the tunnel interface, but nothing populated it from a config file: the parser rejectedExcludeIPsas an unrecognized peer key, so the only way to use excluded routes was programmatic (as the AmneziaVPN client does). This PR wires the key through the whole app so a plain.confcan express "full tunnel, except these networks".Motivation
On iOS, a split tunnel expressed as a long complementary
AllowedIPslist (everything except a few networks, no0.0.0.0/0) leaves the default route on the physical interface.NWPathMonitorin the network extension then reports the path asunsatisfiedon some networks, and the adapter pauses the backend while the UI still shows "Connected" — see amnezia-vpn/amnezia-client#3207. A full-tunnel config never hits this, because the tunnel interface owns the default route.With
AllowedIPs = 0.0.0.0/0plusExcludeIPs, the tunnel keeps the default route and the listed destinations still bypass it viaNEIPv4Settings.excludedRoutes/NEIPv6Settings.excludedRoutes. In our deployment this replaces a 517-prefixAllowedIPslist with one route and 45 excluded routes, and the config fits in a QR code again.Changes
TunnelConfiguration+WgQuickConfig.swift): acceptExcludeIPsin[Peer]; comma-separated, multiple lines allowed (likeAllowedIPs); same validation viaIPAddressRange; newParseError.peerHasInvalidExcludeIP.ExcludeIPs = …when non-empty, so edit / export / zip round-trips keep it.PeerConfiguration: includeexcludeIPsin==andhash(into:), so a changed exclude list is detected and applied like any other peer change.highlighter.ctreatsExcludeIPsvalues likeAllowedIPs(IP / CIDR highlighting, multi-value).PeerConfigurationExcludeIPsTests): equality/hash sensitivity; generated network settings contain the excluded routes (IPv4 and IPv6) alongside the endpoint exclusion, and included routes stayinterface address + AllowedIPs.The key is local to the app: it never reaches the UAPI / the peer, and the on-wire cryptokey routing (
AllowedIPs) is unchanged.Notes for review
excludeIPsproperty.ExcludeIPsis also the spelling used by the AmneziaVPN client and by community forks, so configs are interchangeable.excludePrivateIPsinteraction: that checkbox still derives fromAllowedIPsonly.AllowedIPscode paths line by line; the tests targetWireGuardKit(SwiftPM) only. Happy to adjust anything.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.