Skip to content

Commit

Permalink
Refactor tunnel provider and TalpidVpnService
Browse files Browse the repository at this point in the history
This also fixes the issue of the VPN service being restarted
unnecessarily
  • Loading branch information
dlon committed Aug 13, 2024
1 parent 7928cf5 commit bb9597f
Show file tree
Hide file tree
Showing 23 changed files with 506 additions and 558 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ open class TalpidVpnService : LifecycleVpnService() {
}
}

private val tunIsOpen
get() = activeTunStatus?.isOpen ?: false

private var currentTunConfig = defaultTunConfig()
private var currentTunConfig: TunConfig? = null

// Used by JNI
val connectivityListener = ConnectivityListener()
Expand All @@ -46,36 +43,33 @@ open class TalpidVpnService : LifecycleVpnService() {
connectivityListener.unregister()
}

fun getTun(config: TunConfig): CreateTunResult {
fun openTun(config: TunConfig): CreateTunResult {
synchronized(this) {
val tunStatus = activeTunStatus

if (config == currentTunConfig && tunIsOpen) {
return tunStatus!!
if (config == currentTunConfig && tunStatus != null && tunStatus.isOpen) {
return tunStatus
} else {
val newTunStatus = createTun(config)

currentTunConfig = config
activeTunStatus = newTunStatus

return newTunStatus
return openTunImpl(config)
}
}
}

fun createTun() {
synchronized(this) { activeTunStatus = createTun(currentTunConfig) }
}

fun recreateTunIfOpen(config: TunConfig) {
fun openTunForced(config: TunConfig): CreateTunResult {
synchronized(this) {
if (tunIsOpen) {
currentTunConfig = config
activeTunStatus = createTun(config)
}
return openTunImpl(config)
}
}

private fun openTunImpl(config: TunConfig): CreateTunResult {
val newTunStatus = createTun(config)

currentTunConfig = config
activeTunStatus = newTunStatus

return newTunStatus
}

fun closeTun() {
synchronized(this) { activeTunStatus = null }
}
Expand Down Expand Up @@ -151,8 +145,6 @@ open class TalpidVpnService : LifecycleVpnService() {
}
}

private external fun defaultTunConfig(): TunConfig

private external fun waitForTunnelUp(tunFd: Int, isIpv6Enabled: Boolean)

companion object {
Expand Down
23 changes: 4 additions & 19 deletions mullvad-jni/src/talpid_vpn_service.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use ipnetwork::IpNetwork;
use jnix::{
jni::{
objects::JObject,
sys::{jboolean, jint, JNI_FALSE},
JNIEnv,
},
IntoJava, JnixEnv,
use jnix::jni::{
objects::JObject,
sys::{jboolean, jint, JNI_FALSE},
JNIEnv,
};
use nix::sys::{
select::{pselect, FdSet},
Expand All @@ -18,7 +15,6 @@ use std::{
os::unix::io::RawFd,
time::{Duration, Instant},
};
use talpid_tunnel::tun_provider::TunConfig;
use talpid_types::ErrorExt;

#[derive(Debug, thiserror::Error)]
Expand All @@ -33,17 +29,6 @@ enum Error {
TunnelDeviceTimeout,
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_talpid_TalpidVpnService_defaultTunConfig<'env>(
env: JNIEnv<'env>,
_this: JObject<'_>,
) -> JObject<'env> {
let env = JnixEnv::from(env);

TunConfig::default().into_java(&env).forget()
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_talpid_TalpidVpnService_waitForTunnelUp(
Expand Down
11 changes: 7 additions & 4 deletions talpid-core/src/firewall/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use std::{
fs, io,
net::{IpAddr, Ipv4Addr},
};
use talpid_types::net::{AllowedEndpoint, AllowedTunnelTraffic, Endpoint, TransportProtocol};
use talpid_types::net::{
AllowedEndpoint, AllowedTunnelTraffic, Endpoint, TransportProtocol, ALLOWED_LAN_MULTICAST_NETS,
ALLOWED_LAN_NETS,
};

/// Priority for rules that tag split tunneling packets. Equals NF_IP_PRI_MANGLE.
const MANGLE_CHAIN_PRIORITY: i32 = libc::NF_IP_PRI_MANGLE;
Expand Down Expand Up @@ -840,15 +843,15 @@ impl<'a> PolicyBatch<'a> {
// Output and forward chains
for chain in &[&self.out_chain, &self.forward_chain] {
// LAN -> LAN
for net in &*super::ALLOWED_LAN_NETS {
for net in &*ALLOWED_LAN_NETS {
let mut out_rule = Rule::new(chain);
check_net(&mut out_rule, End::Dst, *net);
add_verdict(&mut out_rule, &Verdict::Accept);
self.batch.add(&out_rule, nftnl::MsgType::Add);
}

// LAN -> Multicast
for net in &*super::ALLOWED_LAN_MULTICAST_NETS {
for net in &*ALLOWED_LAN_MULTICAST_NETS {
let mut rule = Rule::new(chain);
check_net(&mut rule, End::Dst, *net);
add_verdict(&mut rule, &Verdict::Accept);
Expand All @@ -858,7 +861,7 @@ impl<'a> PolicyBatch<'a> {

// Input chain
// LAN -> LAN
for net in &*super::ALLOWED_LAN_NETS {
for net in &*ALLOWED_LAN_NETS {
let mut in_rule = Rule::new(&self.in_chain);
check_net(&mut in_rule, End::Src, *net);
add_verdict(&mut in_rule, &Verdict::Accept);
Expand Down
8 changes: 5 additions & 3 deletions talpid-core/src/firewall/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use std::{
ptr,
};
use subslice::SubsliceExt;
use talpid_types::net::{self, AllowedEndpoint, AllowedTunnelTraffic};
use talpid_types::net::{
self, AllowedEndpoint, AllowedTunnelTraffic, ALLOWED_LAN_MULTICAST_NETS, ALLOWED_LAN_NETS,
};

pub use pfctl::Error;

Expand Down Expand Up @@ -494,7 +496,7 @@ impl Firewall {

fn get_allow_lan_rules(&self) -> Result<Vec<pfctl::FilterRule>> {
let mut rules = vec![];
for net in &*super::ALLOWED_LAN_NETS {
for net in &*ALLOWED_LAN_NETS {
let mut rule_builder = self.create_rule_builder(FilterRuleAction::Pass);
rule_builder.quick(true);
let allow_out = rule_builder
Expand All @@ -510,7 +512,7 @@ impl Firewall {
rules.push(allow_out);
rules.push(allow_in);
}
for multicast_net in &*super::ALLOWED_LAN_MULTICAST_NETS {
for multicast_net in &*ALLOWED_LAN_MULTICAST_NETS {
let allow_multicast_out = self
.create_rule_builder(FilterRuleAction::Pass)
.quick(true)
Expand Down
41 changes: 3 additions & 38 deletions talpid-core/src/firewall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
fmt,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
use talpid_types::net::{AllowedEndpoint, AllowedTunnelTraffic};
use talpid_types::net::{AllowedEndpoint, AllowedTunnelTraffic, ALLOWED_LAN_NETS};

#[cfg(target_os = "macos")]
#[path = "macos.rs"]
Expand All @@ -24,39 +24,6 @@ mod imp;

pub use self::imp::Error;

/// When "allow local network" is enabled the app will allow traffic to and from these networks.
pub(crate) static ALLOWED_LAN_NETS: Lazy<[IpNetwork; 6]> = Lazy::new(|| {
[
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 0), 8).unwrap()),
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(172, 16, 0, 0), 12).unwrap()),
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 16).unwrap()),
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(169, 254, 0, 0), 16).unwrap()),
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 10).unwrap()),
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 0), 7).unwrap()),
]
});
/// When "allow local network" is enabled the app will allow traffic to these networks.
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
pub(crate) static ALLOWED_LAN_MULTICAST_NETS: Lazy<[IpNetwork; 8]> = Lazy::new(|| {
[
// Local network broadcast. Not routable
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(255, 255, 255, 255), 32).unwrap()),
// Local subnetwork multicast. Not routable
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(224, 0, 0, 0), 24).unwrap()),
// Admin-local IPv4 multicast.
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(239, 0, 0, 0), 8).unwrap()),
// Interface-local IPv6 multicast.
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()),
// Link-local IPv6 multicast. IPv6 equivalent of 224.0.0.0/24
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()),
// Realm-local IPv6 multicast.
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff03, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()),
// Admin-local IPv6 multicast.
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff04, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()),
// Site-local IPv6 multicast.
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0xff05, 0, 0, 0, 0, 0, 0, 0), 16).unwrap()),
]
});
#[cfg(any(target_os = "linux", target_os = "macos"))]
static IPV6_LINK_LOCAL: Lazy<Ipv6Network> =
Lazy::new(|| Ipv6Network::new(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 10).unwrap());
Expand All @@ -76,10 +43,8 @@ static SOLICITED_NODE_MULTICAST: Lazy<Ipv6Network> =
Lazy::new(|| Ipv6Network::new(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 1, 0xFF00, 0), 104).unwrap());
static LOOPBACK_NETS: Lazy<[IpNetwork; 2]> = Lazy::new(|| {
[
IpNetwork::V4(ipnetwork::Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap()),
IpNetwork::V6(
ipnetwork::Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap(),
),
IpNetwork::V4(Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap()),
IpNetwork::V6(Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap()),
]
});

Expand Down
Loading

0 comments on commit bb9597f

Please sign in to comment.