Skip to content

Commit da86b2d

Browse files
committed
0.8.1
1 parent a04c091 commit da86b2d

8 files changed

Lines changed: 624 additions & 495 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.8.1
2+
* Improved VPN peer IP detection (added WireGuard and Tailscale support)
3+
* Fixed memory leak in CLI version string
4+
* Refactored network detection for better reliability
5+
* Added comprehensive test script
6+
17
## 0.8.0
28
* Rewrite from Go to Rust
39
* VPN gateway detection via sysctl, netstat, scutil, and ifconfig fallbacks

Cargo.lock

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "vpn-kill-switch"
3-
version = "0.8.0"
3+
version = "0.8.1"
44
authors = ["Nicolas Embriz <nbari@tequila.io>"]
55
description = "VPN kill switch for macOS"
66
documentation = "https://killswitch.network"

src/cli/commands/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ use clap::{
22
Arg, ArgAction, ColorChoice, Command,
33
builder::styling::{AnsiColor, Effects, Styles},
44
};
5+
use std::sync::OnceLock;
56

67
pub mod built_info {
78
#![allow(clippy::doc_markdown)]
89
include!(concat!(env!("OUT_DIR"), "/built.rs"));
910
}
1011

12+
static LONG_VERSION: OnceLock<String> = OnceLock::new();
13+
1114
#[must_use]
1215
pub fn new() -> Command {
1316
let styles = Styles::styled()
@@ -16,9 +19,10 @@ pub fn new() -> Command {
1619
.literal(AnsiColor::Blue.on_default() | Effects::BOLD)
1720
.placeholder(AnsiColor::Green.on_default());
1821

19-
let git_hash = built_info::GIT_COMMIT_HASH.unwrap_or("unknown");
20-
let long_version: &'static str =
21-
Box::leak(format!("{} - {}", env!("CARGO_PKG_VERSION"), git_hash).into_boxed_str());
22+
let long_version: &str = LONG_VERSION.get_or_init(|| {
23+
let git_hash = built_info::GIT_COMMIT_HASH.unwrap_or("unknown");
24+
format!("{} - {git_hash}", env!("CARGO_PKG_VERSION"))
25+
});
2226

2327
Command::new(env!("CARGO_PKG_NAME"))
2428
.about(env!("CARGO_PKG_DESCRIPTION"))

src/killswitch/mod.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ mod rules;
55
use crate::cli::verbosity::Verbosity;
66
use anyhow::{Context, Result, bail};
77

8+
/// Check if an IP address is in a private/reserved range (RFC 1918, loopback, link-local)
9+
#[must_use]
10+
pub fn is_private_ip(ip: &std::net::Ipv4Addr) -> bool {
11+
let o = ip.octets();
12+
// 10.0.0.0/8
13+
o[0] == 10
14+
// 172.16.0.0/12
15+
|| (o[0] == 172 && (16..=31).contains(&o[1]))
16+
// 192.168.0.0/16
17+
|| (o[0] == 192 && o[1] == 168)
18+
// 127.0.0.0/8 (loopback)
19+
|| o[0] == 127
20+
// 169.254.0.0/16 (link-local)
21+
|| (o[0] == 169 && o[1] == 254)
22+
}
23+
824
fn check_root() -> Result<()> {
925
let euid = unsafe { libc::geteuid() };
1026
if euid != 0 {
@@ -19,13 +35,7 @@ fn validate_ipv4(ip: &str) -> Result<()> {
1935
let IpAddr::V4(v4) = addr else {
2036
bail!("IPv6 addresses are not supported: {ip}");
2137
};
22-
let o = v4.octets();
23-
if o[0] == 10
24-
|| (o[0] == 172 && (16..=31).contains(&o[1]))
25-
|| (o[0] == 192 && o[1] == 168)
26-
|| o[0] == 127
27-
|| (o[0] == 169 && o[1] == 254)
28-
{
38+
if is_private_ip(&v4) {
2939
bail!("{ip} is a private/reserved IP address. VPN peer must be a public IP");
3040
}
3141
Ok(())
@@ -91,6 +101,7 @@ pub fn disable(verbose: Verbosity) -> Result<()> {
91101
///
92102
/// # Errors
93103
/// Returns an error if the firewall status cannot be queried
104+
#[must_use = "status returns the current state which should be displayed or checked"]
94105
pub fn status() -> Result<String> {
95106
pf::status()
96107
}
@@ -129,10 +140,16 @@ pub fn show_interfaces(verbose: Verbosity) -> Result<String> {
129140
let mut out = String::new();
130141
let _ = writeln!(out, "Interface MAC address IP");
131142

132-
let has_vpn = interfaces.iter().any(|i| i.is_p2p);
143+
let has_vpn = interfaces.iter().any(network::InterfaceInfo::is_p2p);
133144

134145
for iface in &interfaces {
135-
let _ = writeln!(out, "{:<10} {:<19} {}", iface.name, iface.mac, iface.ip);
146+
let _ = writeln!(
147+
out,
148+
"{:<10} {:<19} {}",
149+
iface.name(),
150+
iface.mac(),
151+
iface.ip()
152+
);
136153
}
137154

138155
// Show public IP

0 commit comments

Comments
 (0)