summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2019-02-01 15:44:33 +0100
committerLinus Färnstrand <linus@mullvad.net>2019-02-01 15:44:33 +0100
commitf97c5621fad66ae9768dad8cc422bc3a61f76ef6 (patch)
tree78e77793349dc7ff325c08ece8b918d36a029b44 /talpid-core/src
parent2139dfb9c37f0d7d6b5e823631bac23b511b38f6 (diff)
parent7479f4e46724f7e32e9e34e6c20f32975d7c9dac (diff)
downloadmullvadvpn-f97c5621fad66ae9768dad8cc422bc3a61f76ef6.tar.xz
mullvadvpn-f97c5621fad66ae9768dad8cc422bc3a61f76ef6.zip
Merge branch 'separate-dns-and-firewall'
Diffstat (limited to 'talpid-core/src')
-rw-r--r--talpid-core/src/dns/linux/mod.rs (renamed from talpid-core/src/security/linux/dns/mod.rs)2
-rw-r--r--talpid-core/src/dns/linux/network_manager.rs (renamed from talpid-core/src/security/linux/dns/network_manager.rs)0
-rw-r--r--talpid-core/src/dns/linux/resolvconf.rs (renamed from talpid-core/src/security/linux/dns/resolvconf.rs)0
-rw-r--r--talpid-core/src/dns/linux/static_resolv_conf.rs (renamed from talpid-core/src/security/linux/dns/static_resolv_conf.rs)0
-rw-r--r--talpid-core/src/dns/linux/systemd_resolved.rs (renamed from talpid-core/src/security/linux/dns/systemd_resolved.rs)3
-rw-r--r--talpid-core/src/dns/macos.rs (renamed from talpid-core/src/security/macos/dns.rs)2
-rw-r--r--talpid-core/src/dns/mod.rs58
-rw-r--r--talpid-core/src/dns/windows/mod.rs (renamed from talpid-core/src/security/windows/dns.rs)6
-rw-r--r--talpid-core/src/dns/windows/system_state.rs (renamed from talpid-core/src/security/windows/system_state.rs)9
-rw-r--r--talpid-core/src/ffi.rs (renamed from talpid-core/src/security/windows/ffi.rs)0
-rw-r--r--talpid-core/src/firewall/linux.rs (renamed from talpid-core/src/security/linux/mod.rs)49
-rw-r--r--talpid-core/src/firewall/macos.rs (renamed from talpid-core/src/security/macos/mod.rs)30
-rw-r--r--talpid-core/src/firewall/mod.rs (renamed from talpid-core/src/security/mod.rs)100
-rw-r--r--talpid-core/src/firewall/windows.rs (renamed from talpid-core/src/security/windows/mod.rs)30
-rw-r--r--talpid-core/src/lib.rs16
-rw-r--r--talpid-core/src/linux.rs27
-rw-r--r--talpid-core/src/tunnel_state_machine/blocked_state.rs16
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs18
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs16
-rw-r--r--talpid-core/src/tunnel_state_machine/disconnected_state.rs20
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs16
21 files changed, 218 insertions, 200 deletions
diff --git a/talpid-core/src/security/linux/dns/mod.rs b/talpid-core/src/dns/linux/mod.rs
index 74267e2c19..17ec6b7e39 100644
--- a/talpid-core/src/security/linux/dns/mod.rs
+++ b/talpid-core/src/dns/linux/mod.rs
@@ -31,7 +31,7 @@ pub struct DnsMonitor {
inner: Option<DnsMonitorHolder>,
}
-impl super::super::DnsMonitorT for DnsMonitor {
+impl super::DnsMonitorT for DnsMonitor {
type Error = Error;
fn new(_cache_dir: impl AsRef<Path>) -> Result<Self> {
diff --git a/talpid-core/src/security/linux/dns/network_manager.rs b/talpid-core/src/dns/linux/network_manager.rs
index 73d49eb1a8..73d49eb1a8 100644
--- a/talpid-core/src/security/linux/dns/network_manager.rs
+++ b/talpid-core/src/dns/linux/network_manager.rs
diff --git a/talpid-core/src/security/linux/dns/resolvconf.rs b/talpid-core/src/dns/linux/resolvconf.rs
index 32b8fcd6b9..32b8fcd6b9 100644
--- a/talpid-core/src/security/linux/dns/resolvconf.rs
+++ b/talpid-core/src/dns/linux/resolvconf.rs
diff --git a/talpid-core/src/security/linux/dns/static_resolv_conf.rs b/talpid-core/src/dns/linux/static_resolv_conf.rs
index cea1b1ac2f..cea1b1ac2f 100644
--- a/talpid-core/src/security/linux/dns/static_resolv_conf.rs
+++ b/talpid-core/src/dns/linux/static_resolv_conf.rs
diff --git a/talpid-core/src/security/linux/dns/systemd_resolved.rs b/talpid-core/src/dns/linux/systemd_resolved.rs
index f4eac9e486..6734a1819c 100644
--- a/talpid-core/src/security/linux/dns/systemd_resolved.rs
+++ b/talpid-core/src/dns/linux/systemd_resolved.rs
@@ -1,4 +1,5 @@
-use super::{super::iface_index, RESOLV_CONF_PATH};
+use super::RESOLV_CONF_PATH;
+use crate::linux::iface_index;
use dbus::{
arg::RefArg, stdintf::*, BusType, Interface, Member, Message, MessageItem, MessageItemArray,
Signature,
diff --git a/talpid-core/src/security/macos/dns.rs b/talpid-core/src/dns/macos.rs
index a1fad021de..d65fdbf6c0 100644
--- a/talpid-core/src/security/macos/dns.rs
+++ b/talpid-core/src/dns/macos.rs
@@ -126,7 +126,7 @@ pub struct DnsMonitor {
state: Arc<Mutex<Option<State>>>,
}
-impl super::super::DnsMonitorT for DnsMonitor {
+impl super::DnsMonitorT for DnsMonitor {
type Error = Error;
/// Creates and returns a new `DnsMonitor`. This spawns a background thread that will monitor
diff --git a/talpid-core/src/dns/mod.rs b/talpid-core/src/dns/mod.rs
new file mode 100644
index 0000000000..5353167ea9
--- /dev/null
+++ b/talpid-core/src/dns/mod.rs
@@ -0,0 +1,58 @@
+use std::{net::IpAddr, path::Path};
+
+#[cfg(target_os = "macos")]
+#[path = "macos.rs"]
+mod imp;
+
+#[cfg(target_os = "linux")]
+#[path = "linux/mod.rs"]
+mod imp;
+
+#[cfg(windows)]
+#[path = "windows/mod.rs"]
+mod imp;
+
+pub use self::imp::Error;
+
+/// Sets and monitors system DNS settings. Makes sure the desired DNS servers are being used.
+pub struct DnsMonitor {
+ inner: imp::DnsMonitor,
+}
+
+impl DnsMonitor {
+ /// Returns a new `DnsMonitor` that can set and monitor the system DNS.
+ pub fn new(cache_dir: impl AsRef<Path>) -> Result<Self, Error> {
+ Ok(DnsMonitor {
+ inner: imp::DnsMonitor::new(cache_dir)?,
+ })
+ }
+
+ /// Set DNS to the given servers. And start monitoring the system for changes.
+ pub fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<(), Error> {
+ log::info!(
+ "Setting DNS servers to {}",
+ servers
+ .iter()
+ .map(|ip| ip.to_string())
+ .collect::<Vec<String>>()
+ .join(", ")
+ );
+ self.inner.set(interface, servers)
+ }
+
+ /// Reset system DNS settings to what it was before being set by this instance.
+ pub fn reset(&mut self) -> Result<(), Error> {
+ log::info!("Resetting DNS");
+ self.inner.reset()
+ }
+}
+
+trait DnsMonitorT: Sized {
+ type Error: ::std::error::Error;
+
+ fn new(cache_dir: impl AsRef<Path>) -> Result<Self, Self::Error>;
+
+ fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<(), Self::Error>;
+
+ fn reset(&mut self) -> Result<(), Self::Error>;
+}
diff --git a/talpid-core/src/security/windows/dns.rs b/talpid-core/src/dns/windows/mod.rs
index 6c04c03e57..dfa239cb81 100644
--- a/talpid-core/src/security/windows/dns.rs
+++ b/talpid-core/src/dns/windows/mod.rs
@@ -7,10 +7,12 @@ use std::{
ptr, slice,
};
+mod system_state;
+use self::system_state::SystemStateWriter;
+
use error_chain::ChainedError;
use widestring::WideCString;
-use super::system_state::SystemStateWriter;
const DNS_STATE_FILENAME: &'static str = "dns-state-backup";
@@ -47,7 +49,7 @@ pub struct DnsMonitor {
backup_writer: SystemStateWriter,
}
-impl super::super::DnsMonitorT for DnsMonitor {
+impl super::DnsMonitorT for DnsMonitor {
type Error = Error;
fn new(cache_dir: impl AsRef<Path>) -> Result<Self> {
diff --git a/talpid-core/src/security/windows/system_state.rs b/talpid-core/src/dns/windows/system_state.rs
index f5e1d073dd..f2557e7cf7 100644
--- a/talpid-core/src/security/windows/system_state.rs
+++ b/talpid-core/src/dns/windows/system_state.rs
@@ -8,7 +8,7 @@ use std::{
};
/// This struct is responsible for saving a binary blob to disk. The binary blob is intended to
-/// store system state that should be resotred when the security policy is reset.
+/// store system DNS settings that should be restored when the DNS settings are reset.
pub struct SystemStateWriter {
/// Full path to the system state backup file
pub backup_path: Box<Path>,
@@ -16,15 +16,15 @@ pub struct SystemStateWriter {
impl SystemStateWriter {
/// Creates a new SystemStateWriter which will use a file in the cache directory to store system
- /// state that has to be restored.
+ /// DNS state that has to be restored.
pub fn new<P: AsRef<Path>>(backup_path: P) -> Self {
Self {
backup_path: backup_path.as_ref().to_owned().into_boxed_path(),
}
}
- /// Writes a binary blob representing the system state to the backup location before any
- /// security policies are applied.
+ /// Writes a binary blob representing the system DNS settings to the backup location before any
+ /// DNS changes are applied.
pub fn write_backup(&self, data: &[u8]) -> io::Result<()> {
let mut backup_file = File::create(&self.backup_path)?;
backup_file.write_all(data)?;
@@ -41,7 +41,6 @@ impl SystemStateWriter {
}
}
-
/// Removes a previously created state backup if it exists.
pub fn remove_backup(&self) -> io::Result<()> {
match fs::remove_file(&self.backup_path) {
diff --git a/talpid-core/src/security/windows/ffi.rs b/talpid-core/src/ffi.rs
index 6c4d8381d4..6c4d8381d4 100644
--- a/talpid-core/src/security/windows/ffi.rs
+++ b/talpid-core/src/ffi.rs
diff --git a/talpid-core/src/security/linux/mod.rs b/talpid-core/src/firewall/linux.rs
index 76bfef07ac..2743b9d318 100644
--- a/talpid-core/src/security/linux/mod.rs
+++ b/talpid-core/src/firewall/linux.rs
@@ -1,4 +1,4 @@
-use super::{NetworkSecurityT, SecurityPolicy};
+use super::{FirewallPolicy, FirewallT};
use crate::tunnel;
use ipnetwork::IpNetwork;
use lazy_static::lazy_static;
@@ -11,15 +11,10 @@ use nftnl::{
use std::{
env,
ffi::{CStr, CString},
- io,
net::{IpAddr, Ipv4Addr},
};
use talpid_types::net::{Endpoint, TransportProtocol};
-
-mod dns;
-pub use self::dns::{DnsMonitor, Error as DnsError};
-
error_chain! {
errors {
/// Unable to open netlink socket to netfilter
@@ -33,15 +28,13 @@ error_chain! {
/// Failed to verify that our tables are set. Probably means that
/// it's the host does not support nftables properly.
NetfilterTableNotSetError{ description("Failed to set firewall rules") }
- /// The name is not a valid Linux network interface name
- InvalidInterfaceName(name: String) {
- description("Invalid network interface name")
- display("Invalid network interface name: {}", name)
- }
}
links {
Nftnl(nftnl::Error, nftnl::ErrorKind) #[doc = "Error in nftnl"];
}
+ foreign_links {
+ IfaceIndexLookupError(crate::linux::IfaceIndexLookupError);
+ }
}
lazy_static! {
@@ -71,20 +64,20 @@ enum End {
}
/// The Linux implementation for the firewall and DNS.
-pub struct NetworkSecurity {
+pub struct Firewall {
table_name: CString,
}
-impl NetworkSecurityT for NetworkSecurity {
+impl FirewallT for Firewall {
type Error = Error;
fn new() -> Result<Self> {
- Ok(NetworkSecurity {
+ Ok(Firewall {
table_name: TABLE_NAME.clone(),
})
}
- fn apply_policy(&mut self, policy: SecurityPolicy) -> Result<()> {
+ fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<()> {
let table = Table::new(&self.table_name, ProtoFamily::Inet)?;
let batch = PolicyBatch::new(&table)?.finalize(&policy)?;
self.send_and_process(&batch)?;
@@ -107,7 +100,7 @@ impl NetworkSecurityT for NetworkSecurity {
}
}
-impl NetworkSecurity {
+impl Firewall {
fn send_and_process(&self, batch: &FinalizedBatch) -> Result<()> {
let socket =
mnl::Socket::new(mnl::Bus::Netfilter).chain_err(|| ErrorKind::NetlinkOpenError)?;
@@ -213,7 +206,7 @@ impl<'a> PolicyBatch<'a> {
/// Finalize the nftnl message batch by adding every firewall rule needed to satisfy the given
/// policy.
- pub fn finalize(mut self, policy: &SecurityPolicy) -> Result<FinalizedBatch> {
+ pub fn finalize(mut self, policy: &FirewallPolicy) -> Result<FinalizedBatch> {
self.add_loopback_rules()?;
self.add_dhcp_rules()?;
self.add_policy_specific_rules(policy)?;
@@ -276,16 +269,16 @@ impl<'a> PolicyBatch<'a> {
Ok(())
}
- fn add_policy_specific_rules(&mut self, policy: &SecurityPolicy) -> Result<()> {
+ fn add_policy_specific_rules(&mut self, policy: &FirewallPolicy) -> Result<()> {
let allow_lan = match policy {
- SecurityPolicy::Connecting {
+ FirewallPolicy::Connecting {
peer_endpoint,
allow_lan,
} => {
self.add_allow_endpoint_rules(peer_endpoint)?;
*allow_lan
}
- SecurityPolicy::Connected {
+ FirewallPolicy::Connected {
peer_endpoint,
tunnel,
allow_lan,
@@ -296,7 +289,7 @@ impl<'a> PolicyBatch<'a> {
self.add_allow_tunnel_rules(tunnel)?;
*allow_lan
}
- SecurityPolicy::Blocked { allow_lan } => *allow_lan,
+ FirewallPolicy::Blocked { allow_lan } => *allow_lan,
};
if allow_lan {
@@ -420,7 +413,7 @@ fn allow_interface_rule<'a>(
}
fn check_iface(rule: &mut Rule, direction: Direction, iface: &str) -> Result<()> {
- let iface_index = iface_index(iface)?;
+ let iface_index = crate::linux::iface_index(iface)?;
rule.add_expr(&match direction {
Direction::In => nft_expr!(meta iif),
Direction::Out => nft_expr!(meta oif),
@@ -429,18 +422,6 @@ fn check_iface(rule: &mut Rule, direction: Direction, iface: &str) -> Result<()>
Ok(())
}
-fn iface_index(name: &str) -> Result<libc::c_uint> {
- let c_name =
- CString::new(name).chain_err(|| ErrorKind::InvalidInterfaceName(name.to_owned()))?;
- let index = unsafe { libc::if_nametoindex(c_name.as_ptr()) };
- if index == 0 {
- let error = io::Error::last_os_error();
- Err(error).chain_err(|| ErrorKind::InvalidInterfaceName(name.to_owned()))
- } else {
- Ok(index)
- }
-}
-
fn check_net(rule: &mut Rule, end: End, net: IpNetwork) -> Result<()> {
// Must check network layer protocol before loading network layer payload
check_l3proto(rule, net.ip())?;
diff --git a/talpid-core/src/security/macos/mod.rs b/talpid-core/src/firewall/macos.rs
index cc14fbfd6e..6662539dc9 100644
--- a/talpid-core/src/security/macos/mod.rs
+++ b/talpid-core/src/firewall/macos.rs
@@ -1,14 +1,8 @@
-use super::{NetworkSecurityT, SecurityPolicy};
+use super::{FirewallPolicy, FirewallT};
use pfctl::FilterRuleAction;
-use std::{
- env,
- net::{Ipv4Addr, SocketAddr},
-};
+use std::{env, net::Ipv4Addr};
use talpid_types::net;
-mod dns;
-pub use self::dns::{DnsMonitor, Error as DnsError};
-
pub use pfctl::Error;
type Result<T> = ::std::result::Result<T, Error>;
@@ -18,13 +12,13 @@ type Result<T> = ::std::result::Result<T, Error>;
const ANCHOR_NAME: &'static str = "mullvad";
/// The macOS firewall and DNS implementation.
-pub struct NetworkSecurity {
+pub struct Firewall {
pf: pfctl::PfCtl,
pf_was_enabled: Option<bool>,
rule_logging: RuleLogging,
}
-impl NetworkSecurityT for NetworkSecurity {
+impl FirewallT for Firewall {
type Error = Error;
fn new() -> Result<Self> {
@@ -39,14 +33,14 @@ impl NetworkSecurityT for NetworkSecurity {
};
log::trace!("Firewall debug log policy: {:?}", rule_logging);
- Ok(NetworkSecurity {
+ Ok(Firewall {
pf: pfctl::PfCtl::new()?,
pf_was_enabled: None,
rule_logging,
})
}
- fn apply_policy(&mut self, policy: SecurityPolicy) -> Result<()> {
+ fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<()> {
self.enable()?;
self.add_anchor()?;
self.set_rules(policy)
@@ -64,8 +58,8 @@ impl NetworkSecurityT for NetworkSecurity {
}
}
-impl NetworkSecurity {
- fn set_rules(&mut self, policy: SecurityPolicy) -> Result<()> {
+impl Firewall {
+ fn set_rules(&mut self, policy: FirewallPolicy) -> Result<()> {
let mut new_filter_rules = vec![];
new_filter_rules.append(&mut self.get_allow_loopback_rules()?);
@@ -85,10 +79,10 @@ impl NetworkSecurity {
fn get_policy_specific_rules(
&mut self,
- policy: SecurityPolicy,
+ policy: FirewallPolicy,
) -> Result<Vec<pfctl::FilterRule>> {
match policy {
- SecurityPolicy::Connecting {
+ FirewallPolicy::Connecting {
peer_endpoint,
allow_lan,
} => {
@@ -98,7 +92,7 @@ impl NetworkSecurity {
}
Ok(rules)
}
- SecurityPolicy::Connected {
+ FirewallPolicy::Connected {
peer_endpoint,
tunnel,
allow_lan,
@@ -148,7 +142,7 @@ impl NetworkSecurity {
}
Ok(rules)
}
- SecurityPolicy::Blocked { allow_lan } => {
+ FirewallPolicy::Blocked { allow_lan } => {
let mut rules = Vec::new();
if allow_lan {
rules.append(&mut self.get_allow_lan_rules()?);
diff --git a/talpid-core/src/security/mod.rs b/talpid-core/src/firewall/mod.rs
index 892041b363..b7977bc2cd 100644
--- a/talpid-core/src/security/mod.rs
+++ b/talpid-core/src/firewall/mod.rs
@@ -2,25 +2,25 @@
use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
#[cfg(unix)]
use lazy_static::lazy_static;
+use std::fmt;
#[cfg(unix)]
-use std::net::{Ipv4Addr, Ipv6Addr};
-use std::{fmt, net::IpAddr, path::Path};
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use talpid_types::net::Endpoint;
#[cfg(target_os = "macos")]
-#[path = "macos/mod.rs"]
+#[path = "macos.rs"]
mod imp;
#[cfg(target_os = "linux")]
-#[path = "linux/mod.rs"]
+#[path = "linux.rs"]
mod imp;
#[cfg(windows)]
-#[path = "windows/mod.rs"]
+#[path = "windows.rs"]
mod imp;
-pub use self::imp::{DnsError, Error};
+pub use self::imp::Error;
#[cfg(unix)]
@@ -46,7 +46,7 @@ lazy_static! {
/// A enum that describes network security strategy
#[derive(Debug, Clone, Eq, PartialEq)]
-pub enum SecurityPolicy {
+pub enum FirewallPolicy {
/// Allow traffic only to server
Connecting {
/// The peer endpoint that should be allowed.
@@ -72,10 +72,10 @@ pub enum SecurityPolicy {
},
}
-impl fmt::Display for SecurityPolicy {
+impl fmt::Display for FirewallPolicy {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self {
- SecurityPolicy::Connecting {
+ FirewallPolicy::Connecting {
peer_endpoint,
allow_lan,
} => write!(
@@ -84,7 +84,7 @@ impl fmt::Display for SecurityPolicy {
peer_endpoint,
if *allow_lan { "Allowing" } else { "Blocking" }
),
- SecurityPolicy::Connected {
+ FirewallPolicy::Connected {
peer_endpoint,
tunnel,
allow_lan,
@@ -102,7 +102,7 @@ impl fmt::Display for SecurityPolicy {
tunnel.gateway,
if *allow_lan { "Allowing" } else { "Blocking" }
),
- SecurityPolicy::Blocked { allow_lan } => write!(
+ FirewallPolicy::Blocked { allow_lan } => write!(
f,
"Blocked, {} LAN",
if *allow_lan { "Allowing" } else { "Blocking" }
@@ -111,91 +111,47 @@ impl fmt::Display for SecurityPolicy {
}
}
-/// Manages network security of the computer/device. Can apply and enforce security policies
+/// Manages network security of the computer/device. Can apply and enforce firewall policies
/// by manipulating the OS firewall and DNS settings.
-pub struct NetworkSecurity {
- inner: imp::NetworkSecurity,
+pub struct Firewall {
+ inner: imp::Firewall,
}
-impl NetworkSecurity {
- /// Returns a new `NetworkSecurity`, ready to apply policies.
+impl Firewall {
+ /// Returns a new `Firewall`, ready to apply policies.
pub fn new() -> Result<Self, Error> {
- Ok(NetworkSecurity {
- inner: imp::NetworkSecurity::new()?,
+ Ok(Firewall {
+ inner: imp::Firewall::new()?,
})
}
- /// Applies and starts enforcing the given `SecurityPolicy` Makes sure it is being kept in place
+ /// Applies and starts enforcing the given `FirewallPolicy` Makes sure it is being kept in place
/// until this method is called again with another policy, or until `reset_policy` is called.
- pub fn apply_policy(&mut self, policy: SecurityPolicy) -> Result<(), Error> {
- log::info!("Applying security policy: {}", policy);
+ pub fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<(), Error> {
+ log::info!("Applying firewall policy: {}", policy);
self.inner.apply_policy(policy)
}
- /// Resets/removes any currently enforced `SecurityPolicy`. Returns the system to the same state
- /// it had before any policy was applied through this `NetworkSecurity` instance.
+ /// Resets/removes any currently enforced `FirewallPolicy`. Returns the system to the same state
+ /// it had before any policy was applied through this `Firewall` instance.
pub fn reset_policy(&mut self) -> Result<(), Error> {
- log::info!("Resetting security policy");
+ log::info!("Resetting firewall policy");
self.inner.reset_policy()
}
}
-/// Sets and monitors system DNS settings. Makes sure the desired DNS servers are being used.
-pub struct DnsMonitor {
- inner: imp::DnsMonitor,
-}
-
-impl DnsMonitor {
- /// Returns a new `DnsMonitor` that can set and monitor the system DNS.
- pub fn new(cache_dir: impl AsRef<Path>) -> Result<Self, DnsError> {
- Ok(DnsMonitor {
- inner: imp::DnsMonitor::new(cache_dir)?,
- })
- }
-
- /// Set DNS to the given servers. And start monitoring the system for changes.
- pub fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<(), DnsError> {
- log::info!(
- "Setting DNS servers to {}",
- servers
- .iter()
- .map(|ip| ip.to_string())
- .collect::<Vec<String>>()
- .join(", ")
- );
- self.inner.set(interface, servers)
- }
-
- /// Reset system DNS settings to what it was before being set by this instance.
- pub fn reset(&mut self) -> Result<(), DnsError> {
- log::info!("Resetting DNS");
- self.inner.reset()
- }
-}
-
-
/// Abstract firewall interaction trait. Used by the OS specific implementations.
-trait NetworkSecurityT: Sized {
+trait FirewallT: Sized {
/// The error type thrown by the implementer of this trait
type Error: ::std::error::Error;
/// Create new instance
fn new() -> ::std::result::Result<Self, Self::Error>;
- /// Enable the given SecurityPolicy
- fn apply_policy(&mut self, policy: SecurityPolicy) -> ::std::result::Result<(), Self::Error>;
+ /// Enable the given FirewallPolicy
+ fn apply_policy(&mut self, policy: FirewallPolicy) -> ::std::result::Result<(), Self::Error>;
- /// Revert the system network security state to what it was before this instance started
+ /// Revert the system firewall state to what it was before this instance started
/// modifying the system.
fn reset_policy(&mut self) -> ::std::result::Result<(), Self::Error>;
}
-
-trait DnsMonitorT: Sized {
- type Error: ::std::error::Error;
-
- fn new(cache_dir: impl AsRef<Path>) -> Result<Self, Self::Error>;
-
- fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<(), Self::Error>;
-
- fn reset(&mut self) -> Result<(), Self::Error>;
-}
diff --git a/talpid-core/src/security/windows/mod.rs b/talpid-core/src/firewall/windows.rs
index 1a021d593a..d77a9a3dbd 100644
--- a/talpid-core/src/security/windows/mod.rs
+++ b/talpid-core/src/firewall/windows.rs
@@ -1,20 +1,12 @@
use std::{net::IpAddr, ptr};
use self::winfw::*;
-use super::{NetworkSecurityT, SecurityPolicy};
+use super::{FirewallPolicy, FirewallT};
use crate::winnet;
use log::{debug, error, trace};
use talpid_types::net::Endpoint;
use widestring::WideCString;
-#[macro_use]
-mod ffi;
-
-mod dns;
-pub use self::dns::{DnsMonitor, Error as DnsError};
-
-mod system_state;
-
error_chain! {
errors {
/// Failure to initialize windows firewall module
@@ -39,7 +31,7 @@ error_chain! {
/// Failure to apply firewall _blocked_ policy
ApplyingBlockedPolicy {
- description("Failed to apply blocked security policy")
+ description("Failed to apply blocked firewall policy")
}
/// Failure to reset firewall policies
@@ -57,9 +49,9 @@ error_chain! {
const WINFW_TIMEOUT_SECONDS: u32 = 2;
/// The Windows implementation for the firewall and DNS.
-pub struct NetworkSecurity(());
+pub struct Firewall(());
-impl NetworkSecurityT for NetworkSecurity {
+impl FirewallT for Firewall {
type Error = Error;
fn new() -> Result<Self> {
@@ -72,19 +64,19 @@ impl NetworkSecurityT for NetworkSecurity {
.into_result()?
};
trace!("Successfully initialized windows firewall module");
- Ok(NetworkSecurity(()))
+ Ok(Firewall(()))
}
- fn apply_policy(&mut self, policy: SecurityPolicy) -> Result<()> {
+ fn apply_policy(&mut self, policy: FirewallPolicy) -> Result<()> {
match policy {
- SecurityPolicy::Connecting {
+ FirewallPolicy::Connecting {
peer_endpoint,
allow_lan,
} => {
let cfg = &WinFwSettings::new(allow_lan);
self.set_connecting_state(&peer_endpoint, &cfg)
}
- SecurityPolicy::Connected {
+ FirewallPolicy::Connected {
peer_endpoint,
tunnel,
allow_lan,
@@ -92,7 +84,7 @@ impl NetworkSecurityT for NetworkSecurity {
let cfg = &WinFwSettings::new(allow_lan);
self.set_connected_state(&peer_endpoint, &cfg, &tunnel)
}
- SecurityPolicy::Blocked { allow_lan } => {
+ FirewallPolicy::Blocked { allow_lan } => {
let cfg = &WinFwSettings::new(allow_lan);
self.set_blocked_state(&cfg)
}
@@ -105,7 +97,7 @@ impl NetworkSecurityT for NetworkSecurity {
}
}
-impl Drop for NetworkSecurity {
+impl Drop for Firewall {
fn drop(&mut self) {
if unsafe { WinFw_Deinitialize().into_result().is_ok() } {
trace!("Successfully deinitialized windows firewall module");
@@ -115,7 +107,7 @@ impl Drop for NetworkSecurity {
}
}
-impl NetworkSecurity {
+impl Firewall {
fn set_connecting_state(
&mut self,
endpoint: &Endpoint,
diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs
index 437fb2ff6f..8e63d2bfa8 100644
--- a/talpid-core/src/lib.rs
+++ b/talpid-core/src/lib.rs
@@ -13,6 +13,11 @@
#[macro_use]
extern crate error_chain;
+/// Misc FFI utilities.
+#[cfg(windows)]
+#[macro_use]
+mod ffi;
+
#[cfg(windows)]
mod winnet;
@@ -37,10 +42,17 @@ pub mod logging;
/// Abstractions and extra features on `std::mpsc`
pub mod mpsc;
-/// Abstractions over operating system network security settings.
-pub mod security;
+/// Abstractions over operating system firewalls.
+pub mod firewall;
+
+/// Abstractions over operating system DNS settings.
+pub mod dns;
/// State machine to handle tunnel configuration.
pub mod tunnel_state_machine;
mod mktemp;
+
+/// Misc utilities for the Linux platform.
+#[cfg(target_os = "linux")]
+mod linux;
diff --git a/talpid-core/src/linux.rs b/talpid-core/src/linux.rs
new file mode 100644
index 0000000000..c1e3a97e07
--- /dev/null
+++ b/talpid-core/src/linux.rs
@@ -0,0 +1,27 @@
+use std::{
+ ffi::{self, CString},
+ io,
+};
+
+/// Converts an interface name into the corresponding index.
+pub fn iface_index(name: &str) -> Result<libc::c_uint, IfaceIndexLookupError> {
+ let c_name = CString::new(name)
+ .map_err(|e| IfaceIndexLookupError::InvalidInterfaceName(name.to_owned(), e))?;
+ let index = unsafe { libc::if_nametoindex(c_name.as_ptr()) };
+ if index == 0 {
+ Err(IfaceIndexLookupError::InterfaceLookupError(
+ name.to_owned(),
+ io::Error::last_os_error(),
+ ))
+ } else {
+ Ok(index)
+ }
+}
+
+#[derive(Debug, err_derive::Error)]
+pub enum IfaceIndexLookupError {
+ #[error(display = "Invalid network interface name: {}", _0)]
+ InvalidInterfaceName(String, #[error(cause)] ffi::NulError),
+ #[error(display = "Failed to get index for interface {}", _0)]
+ InterfaceLookupError(String, #[error(cause)] io::Error),
+}
diff --git a/talpid-core/src/tunnel_state_machine/blocked_state.rs b/talpid-core/src/tunnel_state_machine/blocked_state.rs
index abc782cd24..4fd992dd4d 100644
--- a/talpid-core/src/tunnel_state_machine/blocked_state.rs
+++ b/talpid-core/src/tunnel_state_machine/blocked_state.rs
@@ -6,7 +6,7 @@ use super::{
ConnectingState, DisconnectedState, EventConsequence, ResultExt, SharedTunnelStateValues,
TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper,
};
-use crate::security::SecurityPolicy;
+use crate::firewall::FirewallPolicy;
/// No tunnel is running and all network connections are blocked.
pub struct BlockedState {
@@ -14,20 +14,20 @@ pub struct BlockedState {
}
impl BlockedState {
- fn set_security_policy(shared_values: &mut SharedTunnelStateValues) -> Option<BlockReason> {
- let policy = SecurityPolicy::Blocked {
+ fn set_firewall_policy(shared_values: &mut SharedTunnelStateValues) -> Option<BlockReason> {
+ let policy = FirewallPolicy::Blocked {
allow_lan: shared_values.allow_lan,
};
match shared_values
- .security
+ .firewall
.apply_policy(policy)
- .chain_err(|| "Failed to apply security policy for blocked state")
+ .chain_err(|| "Failed to apply firewall policy for blocked state")
{
Ok(()) => None,
Err(error) => {
log::error!("{}", error.display_chain());
- Some(BlockReason::SetSecurityPolicyError)
+ Some(BlockReason::SetFirewallPolicyError)
}
}
}
@@ -40,7 +40,7 @@ impl TunnelState for BlockedState {
shared_values: &mut SharedTunnelStateValues,
block_reason: Self::Bootstrap,
) -> (TunnelStateWrapper, TunnelStateTransition) {
- let block_reason = Self::set_security_policy(shared_values).unwrap_or_else(|| block_reason);
+ let block_reason = Self::set_firewall_policy(shared_values).unwrap_or_else(|| block_reason);
(
TunnelStateWrapper::from(BlockedState {
@@ -60,7 +60,7 @@ impl TunnelState for BlockedState {
match try_handle_event!(self, commands.poll()) {
Ok(TunnelCommand::AllowLan(allow_lan)) => {
shared_values.allow_lan = allow_lan;
- Self::set_security_policy(shared_values);
+ Self::set_firewall_policy(shared_values);
SameState(self)
}
Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index b5a88c7181..1a979476e7 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -14,7 +14,7 @@ use super::{
TunnelStateWrapper,
};
use crate::{
- security::SecurityPolicy,
+ firewall::FirewallPolicy,
tunnel::{CloseHandle, TunnelEvent, TunnelMetadata},
};
@@ -46,19 +46,19 @@ impl ConnectedState {
}
}
- fn set_security_policy(&self, shared_values: &mut SharedTunnelStateValues) -> Result<()> {
+ fn set_firewall_policy(&self, shared_values: &mut SharedTunnelStateValues) -> Result<()> {
// If a proxy is specified we need to pass it on as the peer endpoint.
let peer_endpoint = self.get_endpoint_from_params();
- let policy = SecurityPolicy::Connected {
+ let policy = FirewallPolicy::Connected {
peer_endpoint,
tunnel: self.metadata.clone(),
allow_lan: shared_values.allow_lan,
};
shared_values
- .security
+ .firewall
.apply_policy(policy)
- .chain_err(|| "Failed to apply security policy for connected state")
+ .chain_err(|| "Failed to apply firewall policy for connected state")
}
fn get_endpoint_from_params(&self) -> Endpoint {
@@ -111,13 +111,13 @@ impl ConnectedState {
Ok(TunnelCommand::AllowLan(allow_lan)) => {
shared_values.allow_lan = allow_lan;
- match self.set_security_policy(shared_values) {
+ match self.set_firewall_policy(shared_values) {
Ok(()) => SameState(self),
Err(error) => {
log::error!("{}", error.display_chain());
self.disconnect(
shared_values,
- AfterDisconnect::Block(BlockReason::SetSecurityPolicyError),
+ AfterDisconnect::Block(BlockReason::SetFirewallPolicyError),
)
}
}
@@ -195,14 +195,14 @@ impl TunnelState for ConnectedState {
let connected_state = ConnectedState::from(bootstrap);
let tunnel_endpoint = connected_state.tunnel_parameters.get_tunnel_endpoint();
- if let Err(error) = connected_state.set_security_policy(shared_values) {
+ if let Err(error) = connected_state.set_firewall_policy(shared_values) {
log::error!("{}", error.display_chain());
DisconnectingState::enter(
shared_values,
(
connected_state.close_handle,
connected_state.tunnel_close_event,
- AfterDisconnect::Block(BlockReason::SetSecurityPolicyError),
+ AfterDisconnect::Block(BlockReason::SetFirewallPolicyError),
),
)
} else if let Err(error) = connected_state.set_dns(shared_values) {
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index ad3712144a..0896fd18cf 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -22,8 +22,8 @@ use super::{
TunnelStateWrapper,
};
use crate::{
+ firewall::FirewallPolicy,
logging,
- security::SecurityPolicy,
tunnel::{self, CloseHandle, TunnelEvent, TunnelMetadata, TunnelMonitor},
};
@@ -60,7 +60,7 @@ pub struct ConnectingState {
}
impl ConnectingState {
- fn set_security_policy(
+ fn set_firewall_policy(
shared_values: &mut SharedTunnelStateValues,
proxy: &Option<openvpn::ProxySettings>,
endpoint: Endpoint,
@@ -71,14 +71,14 @@ impl ConnectingState {
None => endpoint,
};
- let policy = SecurityPolicy::Connecting {
+ let policy = FirewallPolicy::Connecting {
peer_endpoint,
allow_lan: shared_values.allow_lan,
};
shared_values
- .security
+ .firewall
.apply_policy(policy)
- .chain_err(|| "Failed to apply security policy for connecting state")
+ .chain_err(|| "Failed to apply firewall policy for connecting state")
}
fn start_tunnel(
@@ -217,7 +217,7 @@ impl ConnectingState {
match try_handle_event!(self, commands.poll()) {
Ok(TunnelCommand::AllowLan(allow_lan)) => {
shared_values.allow_lan = allow_lan;
- match Self::set_security_policy(
+ match Self::set_firewall_policy(
shared_values,
&get_openvpn_proxy_settings(&self.tunnel_parameters),
self.tunnel_parameters.get_tunnel_endpoint().endpoint,
@@ -231,7 +231,7 @@ impl ConnectingState {
(
self.close_handle,
self.tunnel_close_event,
- AfterDisconnect::Block(BlockReason::SetSecurityPolicyError),
+ AfterDisconnect::Block(BlockReason::SetFirewallPolicyError),
),
))
}
@@ -369,7 +369,7 @@ impl TunnelState for ConnectingState {
None => BlockedState::enter(shared_values, BlockReason::NoMatchingRelay),
Some(tunnel_parameters) => {
let endpoint = tunnel_parameters.get_tunnel_endpoint().endpoint;
- if let Err(error) = Self::set_security_policy(
+ if let Err(error) = Self::set_firewall_policy(
shared_values,
&get_openvpn_proxy_settings(&tunnel_parameters),
endpoint,
diff --git a/talpid-core/src/tunnel_state_machine/disconnected_state.rs b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
index 0634c75da4..299d00d303 100644
--- a/talpid-core/src/tunnel_state_machine/disconnected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/disconnected_state.rs
@@ -2,7 +2,7 @@ use super::{
BlockedState, ConnectingState, EventConsequence, ResultExt, SharedTunnelStateValues,
TunnelCommand, TunnelState, TunnelStateTransition, TunnelStateWrapper,
};
-use crate::security::SecurityPolicy;
+use crate::firewall::FirewallPolicy;
use error_chain::ChainedError;
use futures::{sync::mpsc, Stream};
@@ -10,20 +10,20 @@ use futures::{sync::mpsc, Stream};
pub struct DisconnectedState;
impl DisconnectedState {
- fn set_security_policy(shared_values: &mut SharedTunnelStateValues) {
+ fn set_firewall_policy(shared_values: &mut SharedTunnelStateValues) {
let result = if shared_values.block_when_disconnected {
- let policy = SecurityPolicy::Blocked {
+ let policy = FirewallPolicy::Blocked {
allow_lan: shared_values.allow_lan,
};
shared_values
- .security
+ .firewall
.apply_policy(policy)
- .chain_err(|| "Failed to apply blocking security policy for disconnected state")
+ .chain_err(|| "Failed to apply blocking firewall policy for disconnected state")
} else {
shared_values
- .security
+ .firewall
.reset_policy()
- .chain_err(|| "Failed to reset security policy")
+ .chain_err(|| "Failed to reset firewall policy")
};
if let Err(error) = result {
log::error!("{}", error.display_chain());
@@ -38,7 +38,7 @@ impl TunnelState for DisconnectedState {
shared_values: &mut SharedTunnelStateValues,
_: Self::Bootstrap,
) -> (TunnelStateWrapper, TunnelStateTransition) {
- Self::set_security_policy(shared_values);
+ Self::set_firewall_policy(shared_values);
(
TunnelStateWrapper::from(DisconnectedState),
TunnelStateTransition::Disconnected,
@@ -56,14 +56,14 @@ impl TunnelState for DisconnectedState {
Ok(TunnelCommand::AllowLan(allow_lan)) => {
if shared_values.allow_lan != allow_lan {
shared_values.allow_lan = allow_lan;
- Self::set_security_policy(shared_values);
+ Self::set_firewall_policy(shared_values);
}
SameState(self)
}
Ok(TunnelCommand::BlockWhenDisconnected(block_when_disconnected)) => {
if shared_values.block_when_disconnected != block_when_disconnected {
shared_values.block_when_disconnected = block_when_disconnected;
- Self::set_security_policy(shared_values);
+ Self::set_firewall_policy(shared_values);
}
SameState(self)
}
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 8e20e3a159..4e85e9a0be 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -29,17 +29,13 @@ use self::{
disconnected_state::DisconnectedState,
disconnecting_state::{AfterDisconnect, DisconnectingState},
};
-use crate::{
- mpsc::IntoSender,
- offline,
- security::{DnsMonitor, NetworkSecurity},
-};
+use crate::{dns::DnsMonitor, firewall::Firewall, mpsc::IntoSender, offline};
error_chain! {
errors {
/// An error occurred while setting up the network security.
- NetworkSecurityError {
- description("Network security error")
+ FirewallError {
+ description("Firewall error")
}
/// Unable to start the DNS settings monitor and enforcer.
DnsMonitorError {
@@ -185,10 +181,10 @@ impl TunnelStateMachine {
cache_dir: impl AsRef<Path>,
commands: mpsc::UnboundedReceiver<TunnelCommand>,
) -> Result<Self> {
- let security = NetworkSecurity::new().chain_err(|| ErrorKind::NetworkSecurityError)?;
+ let firewall = Firewall::new().chain_err(|| ErrorKind::FirewallError)?;
let dns_monitor = DnsMonitor::new(cache_dir).chain_err(|| ErrorKind::DnsMonitorError)?;
let mut shared_values = SharedTunnelStateValues {
- security,
+ firewall,
dns_monitor,
allow_lan,
block_when_disconnected,
@@ -266,7 +262,7 @@ pub trait TunnelParametersGenerator: Send + 'static {
/// Values that are common to all tunnel states.
struct SharedTunnelStateValues {
- security: NetworkSecurity,
+ firewall: Firewall,
dns_monitor: DnsMonitor,
/// Should LAN access be allowed outside the tunnel.
allow_lan: bool,