Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC for blocking TunnelVision #3413

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@
private let monitor = nw_path_monitor_create()
var directInterface: nw_interface_t?

var vpnPath: nw_interface_t?

private let bMonitor = NWPathMonitor()
var interface: NWInterface?
var vpnInterface: NWInterface?

private var cancellables = Set<AnyCancellable>()

Expand Down Expand Up @@ -287,7 +290,7 @@
return false
}

guard let interface else {
guard let interface, let vpnInterface else {

Check warning on line 293 in LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Provider/TransparentProxyProvider.swift

View workflow job for this annotation

GitHub Actions / Make Release Build

immutable value 'vpnInterface' was never used; consider replacing with '_' or removing it

Check warning on line 293 in LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Provider/TransparentProxyProvider.swift

View workflow job for this annotation

GitHub Actions / Make Release Build

immutable value 'vpnInterface' was never used; consider replacing with '_' or removing it

Check warning on line 293 in LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Provider/TransparentProxyProvider.swift

View workflow job for this annotation

GitHub Actions / Test (Sandbox)

immutable value 'vpnInterface' was never used; consider replacing with '_' or removing it

Check warning on line 293 in LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Provider/TransparentProxyProvider.swift

View workflow job for this annotation

GitHub Actions / Test (Sandbox)

immutable value 'vpnInterface' was never used; consider replacing with '_' or removing it

Check warning on line 293 in LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Provider/TransparentProxyProvider.swift

View workflow job for this annotation

GitHub Actions / Test (Non-Sandbox)

immutable value 'vpnInterface' was never used; consider replacing with '_' or removing it
logger.error("[TCP: \(String(describing: flow), privacy: .public)] Expected an interface to exclude traffic through")
return false
}
Expand All @@ -300,6 +303,7 @@
case .domainRule:
logger.debug("[TCP: \(String(describing: flow), privacy: .public)] Blocking traffic due to domain rule")
}
return true
case .excludeFromVPN(let reason):
switch reason {
case .appRule:
Expand All @@ -308,6 +312,15 @@
logger.debug("[TCP: \(String(describing: flow), privacy: .public)] Excluding traffic due to domain rule")
}
case .routeThroughVPN:
if ["34.160.111.145", "ifconfig.me"].contains(remoteEndpoint.hostname),
let flowInterface = flow.networkInterface,
let directInterface,
nw_interface_get_index(flowInterface) == nw_interface_get_index(directInterface) {

logger.debug("[UDP: \(String(describing: flow), privacy: .public)] 🔴 TUNNELVISION PREVENTED!")

return true
}
return false
}

Expand All @@ -326,6 +339,34 @@
return true
}

func getInterfaceName(from interface: nw_interface_t) -> String {
let interfaceName = nw_interface_get_name(interface)
return String(cString: interfaceName)
}
/*
func getInterfaceIPAddress(from endpoint: nw_endpoint_t) -> String? {
let address = nw_endpoint_get_address(endpoint)

// Convert sockaddr to a readable string
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))

let result = getnameinfo(
address,
socklen_t(address.pointee.sa_len),
&hostname,
socklen_t(hostname.count),
nil,
0,
NI_NUMERICHOST
)

if result == 0 {
return String(cString: hostname)
}

return nil
}*/

override public func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool {

guard let remoteEndpoint = remoteEndpoint as? NWHostEndpoint,
Expand Down Expand Up @@ -391,6 +432,10 @@
self?.interface = path.availableInterfaces.first { interface in
interface.type != .other
}

self?.vpnInterface = path.availableInterfaces.first { interface in
interface.name.hasPrefix("utun")
}
}
bMonitor.start(queue: .main)

Expand All @@ -401,13 +446,17 @@
let interfaces = SCNetworkInterfaceCopyAll()
logger.log("Available interfaces updated: \(String(reflecting: interfaces), privacy: .public)")

nw_path_enumerate_interfaces(path) { interface in
guard nw_interface_get_type(interface) != nw_interface_type_other else {
return true
nw_path_enumerate_interfaces(path) { [weak self] interface in
guard let self else {
return false
}

if nw_interface_get_type(interface) != nw_interface_type_other {
self.directInterface = interface
return false
}

self.directInterface = interface
return false
return true
}
}

Expand Down
Loading