From 6c138385bd6632c4a88a8f9be6a55d1749167b23 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Mon, 20 Feb 2023 13:17:22 +0530 Subject: [PATCH 1/2] WireGuard Tunnel: Ensure AllowedIPs doesn't overlap with 0.0.0.0/8 When an AllowedIP overlaps with 0.0.0.0/8, the tunnel doesn't transfer any traffic. It's not clear why this happens. As a workaround, we rewrite the AllowedIPs so that there's no overlap with 0.0.0.0/8. --- .../WireGuard/WireGuardAdapterInterface.swift | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/TunnelExtension/WireGuard/WireGuardAdapterInterface.swift b/TunnelExtension/WireGuard/WireGuardAdapterInterface.swift index 0ecc7227..c247f074 100644 --- a/TunnelExtension/WireGuard/WireGuardAdapterInterface.swift +++ b/TunnelExtension/WireGuard/WireGuardAdapterInterface.swift @@ -23,7 +23,7 @@ class WireGuardAdapterInterface: TunnelAdapterInterface { } init(configuration: WireGuardKit.TunnelConfiguration, logger: Logger) { - self.configuration = configuration + self.configuration = configuration.badAllowedIPsRemoved(logger: logger) self.logger = logger } @@ -72,3 +72,85 @@ class WireGuardAdapterInterface: TunnelAdapterInterface { return configuration.interface.addresses.map { "\($0.address)" } } } + +private extension TunnelConfiguration { + + // badAllowedIPsRemoved(): + // When an IPv4 address in AllowedIPs overlaps with 0.0.0.0/8, the tunnel doesn't work. + // Not sure why. As a workaround, we replace those IPs such that there's no such overlap. + // It's anyway not valid to have a source / destination address in 0.0.0.0/8, so we + // exclude that range. + // For example, "0.0.0.0/6" shall be replaced with ["2.0.0.0/7", "1.0.0.0/8"]. + + func badAllowedIPsRemoved(logger: Logger) -> TunnelConfiguration { + guard hasBadAllowedIPs() else { + return self + } + + let replacementIPv4AddressRanges = [ + IPAddressRange(from: "64.0.0.0/2"), // 01XXXXXX.X.X.X + IPAddressRange(from: "32.0.0.0/3"), // 001XXXXX.X.X.X + IPAddressRange(from: "16.0.0.0/4"), // 0001XXXX.X.X.X + IPAddressRange(from: "8.0.0.0/5"), // 00001XXX.X.X.X + IPAddressRange(from: "4.0.0.0/6"), // 000001XX.X.X.X + IPAddressRange(from: "2.0.0.0/7"), // 0000001X.X.X.X + IPAddressRange(from: "1.0.0.0/8") // 00000001.X.X.X + ] + + let peers: [PeerConfiguration] = self.peers.map { originalPeer in + var allowedIPs: [IPAddressRange] = [] + for ipAddressRange in originalPeer.allowedIPs { + if let ipv4Address = ipAddressRange.address as? IPv4Address { + if ipv4Address == Self.allZeroIPv4Address && + ipAddressRange.networkPrefixLength > 0 { + + if ipAddressRange.networkPrefixLength < 8 { + let index = Int(ipAddressRange.networkPrefixLength - 1) + replacementIPv4AddressRanges[index...].forEach { replacementAddressRange in + if let replacementAddressRange = replacementAddressRange { + allowedIPs.append(replacementAddressRange) + } + } + } else { + // We ignore IPv4 ranges that are 0.0.0.0/N, where N >= 8 + // because they cannot be valid source or destination addresses + } + + } else { + allowedIPs.append(ipAddressRange) + } + } else { + allowedIPs.append(ipAddressRange) + } + } + + logger.log("Original AllowedIPs was: \(originalPeer.allowedIPs.map { $0.stringRepresentation }.joined(separator: ", "))") + logger.log("Rewriting AllowedIPs as: \(allowedIPs.map { $0.stringRepresentation }.joined(separator: ", "))") + + var peer = PeerConfiguration(publicKey: originalPeer.publicKey) + peer.preSharedKey = originalPeer.preSharedKey + peer.allowedIPs = allowedIPs + peer.endpoint = originalPeer.endpoint + peer.persistentKeepAlive = originalPeer.persistentKeepAlive + return peer + } + + return TunnelConfiguration(name: self.name, interface: self.interface, peers: peers) + } + + static let allZeroIPv4Address = IPv4Address("0.0.0.0") + + func hasBadAllowedIPs() -> Bool { + for peer in peers { + for ipAddressRange in peer.allowedIPs { + if let ipv4Address = ipAddressRange.address as? IPv4Address { + if ipv4Address == Self.allZeroIPv4Address && + ipAddressRange.networkPrefixLength > 0 { + return true + } + } + } + } + return false + } +} From 504361b5850a7e4ff50ebce3f682b5b2ff8241be Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Tue, 21 Feb 2023 11:49:18 +0530 Subject: [PATCH 2/2] Update changelog --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index dc820676..e2bc624d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ - Avoid using cached token endpoints from OIDAuthState #487 - macOS: Point the user to the OS' please-enable-notification prompt #474 - Improve error alerts #489 +- Fixes excluded routes usage with WireGuard #475 ## 3.0.6