Skip to content
Closed
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
49 changes: 41 additions & 8 deletions src/killswitch/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use crate::cli::verbosity::Verbosity;
use crate::killswitch::is_private_ip;
use anyhow::{Context, Result, bail};
use std::net::IpAddr;
use std::net::{IpAddr, ToSocketAddrs};
use std::process::Command;

// ============================================================================
Expand Down Expand Up @@ -228,18 +228,51 @@ fn detect_peer_from_scutil(verbose: Verbosity) -> Result<String> {

let detail = String::from_utf8_lossy(&show_output.stdout);

// Look for "RemoteAddress : <ip>"
// Look for "RemoteAddress : <host>[:<port>]"
for detail_line in detail.lines() {
let trimmed = detail_line.trim();
if let Some(ip) = trimmed.strip_prefix("RemoteAddress : ") {
let ip = ip.trim();
if is_valid_vpn_peer(ip) {
if let Some(raw) = trimmed.strip_prefix("RemoteAddress : ") {
let raw = raw.trim();
// Strip optional port suffix (host:port or [ipv6]:port)
let host = if raw.starts_with('[') {
raw.trim_start_matches('[').split(']').next().unwrap_or(raw)
} else {
raw.splitn(2, ':').next().unwrap_or(raw)
};

// Resolve hostname to IP if needed
let resolved = if host.parse::<IpAddr>().is_ok() {
host.to_string()
} else {
if verbose.is_debug() {
eprintln!(" Resolving hostname: {host}");
}
match format!("{host}:0").to_socket_addrs() {
Ok(mut addrs) => match addrs.find(|a| a.is_ipv4()) {
Some(addr) => addr.ip().to_string(),
None => {
if verbose.is_debug() {
eprintln!(" No IPv4 address for: {host}");
}
continue;
}
},
Err(e) => {
if verbose.is_debug() {
eprintln!(" DNS resolution failed for {host}: {e}");
}
continue;
}
}
};

if is_valid_vpn_peer(&resolved) {
if verbose.is_verbose() {
eprintln!(" Detected VPN peer via scutil: {ip}");
eprintln!(" Detected VPN peer via scutil: {resolved}");
}
return Ok(ip.to_string());
return Ok(resolved);
} else if verbose.is_debug() {
eprintln!(" Skipping non-public RemoteAddress: {ip}");
eprintln!(" Skipping non-public RemoteAddress: {resolved}");
}
}
}
Expand Down
Loading