summaryrefslogtreecommitdiffhomepage
path: root/talpid-core
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-02-25 17:15:09 +0000
committerEmīls Piņķis <emils@mullvad.net>2019-02-28 10:54:38 +0000
commit44ef97148d2d0717237409de963d244cea0c3adf (patch)
treed56a2ab8b9e6c933a2ab94d9c2aa4f2fc422a361 /talpid-core
parent94efa3bd621ede90485a5e5a9e8da933495ca2af (diff)
downloadmullvadvpn-44ef97148d2d0717237409de963d244cea0c3adf.tar.xz
mullvadvpn-44ef97148d2d0717237409de963d244cea0c3adf.zip
Add {v4,v6}_gateway fields to TunnelMetadata
Diffstat (limited to 'talpid-core')
-rw-r--r--talpid-core/build.rs2
-rw-r--r--talpid-core/src/dns/windows/mod.rs25
-rw-r--r--talpid-core/src/firewall/linux.rs38
-rw-r--r--talpid-core/src/firewall/macos.rs42
-rw-r--r--talpid-core/src/firewall/mod.rs5
-rw-r--r--talpid-core/src/firewall/windows.rs2
-rw-r--r--talpid-core/src/tunnel/mod.rs16
-rw-r--r--talpid-core/src/tunnel/wireguard/config.rs21
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs9
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs7
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs8
11 files changed, 120 insertions, 55 deletions
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 5441062edc..a733cfccbc 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -45,7 +45,7 @@ mod win {
#[cfg(windows)]
fn main() {
- use win::*;
+ use crate::win::*;
const WINFW_DIR_VAR: &str = "WINFW_LIB_DIR";
const WINDNS_DIR_VAR: &str = "WINDNS_LIB_DIR";
diff --git a/talpid-core/src/dns/windows/mod.rs b/talpid-core/src/dns/windows/mod.rs
index dfa239cb81..9d2a8245b2 100644
--- a/talpid-core/src/dns/windows/mod.rs
+++ b/talpid-core/src/dns/windows/mod.rs
@@ -75,29 +75,26 @@ impl super::DnsMonitorT for DnsMonitor {
let ipv4 = servers
.iter()
.filter(|ip| ip.is_ipv4())
- .cloned()
+ .map(ip_to_widestring)
.collect::<Vec<_>>();
let ipv6 = servers
.iter()
- .map(|ip| match ip {
- IpAddr::V4(ip) => IpAddr::V6(ip.to_ipv6_compatible()),
- any => any.clone(),
- })
+ .filter(|ip| ip.is_ipv6())
+ .map(ip_to_widestring)
.collect::<Vec<_>>();
- let ipv4_addresses = ip_to_string(ipv4.iter());
- let ipv6_addresses = ip_to_string(ipv6.iter());
- let mut ipv4_address_ptrs = ipv4_addresses
+
+ let mut ipv4_address_ptrs = ipv4
.iter()
.map(|ip_cstr| ip_cstr.as_ptr())
.collect::<Vec<_>>();
- let mut ipv6_address_ptrs = ipv6_addresses
+ let mut ipv6_address_ptrs = ipv6
.iter()
.map(|ip_cstr| ip_cstr.as_ptr())
.collect::<Vec<_>>();
- trace!("ipv4 ips - {:?} - {}", ipv4_addresses, ipv4_addresses.len());
- trace!("ipv6 ips - {:?} - {}", ipv6_addresses, ipv6_addresses.len());
+ trace!("ipv4 ips - {:?} - {}", ipv4, ipv4.len());
+ trace!("ipv6 ips - {:?} - {}", ipv6, ipv6.len());
unsafe {
WinDns_Set(
@@ -150,10 +147,8 @@ impl DnsMonitor {
}
}
-fn ip_to_string<'a>(ips: impl Iterator<Item = &'a IpAddr>) -> Vec<WideCString> {
- ips.map(|ip| ip.to_string().encode_utf16().collect::<Vec<_>>())
- .map(|ip| WideCString::new(ip).unwrap())
- .collect::<Vec<_>>()
+fn ip_to_widestring(ip: &IpAddr) -> WideCString {
+ WideCString::new(ip.to_string().encode_utf16().collect::<Vec<_>>()).unwrap()
}
// typedef void (WINDNS_API *WinDnsErrorSink)(const char *errorMessage, const char **details,
diff --git a/talpid-core/src/firewall/linux.rs b/talpid-core/src/firewall/linux.rs
index ffec0bc1fd..d073853ad0 100644
--- a/talpid-core/src/firewall/linux.rs
+++ b/talpid-core/src/firewall/linux.rs
@@ -353,23 +353,39 @@ impl<'a> PolicyBatch<'a> {
protocol: TransportProtocol,
) -> Result<()> {
// allow DNS traffic to the tunnel gateway
+ self.add_allow_dns_rule(&tunnel.interface, protocol, tunnel.ipv4_gateway.into())?;
+ if let Some(ipv6_gateway) = tunnel.ipv6_gateway {
+ self.add_allow_dns_rule(&tunnel.interface, protocol, ipv6_gateway.into())?;
+ };
+ let mut block_rule = Rule::new(&self.out_chain)?;
+ check_port(&mut block_rule, protocol, End::Dst, 53)?;
+ add_verdict(&mut block_rule, &Verdict::Drop)?;
+ self.batch.add(&block_rule, nftnl::MsgType::Add)?;
+
+ Ok(())
+ }
+
+ fn add_allow_dns_rule(
+ &mut self,
+ interface: &str,
+ protocol: TransportProtocol,
+ host: IpAddr,
+ ) -> Result<()> {
let mut allow_rule = Rule::new(&self.out_chain)?;
+ let daddr = match host {
+ IpAddr::V4(_) => nft_expr!(payload ipv4 daddr),
+ IpAddr::V6(_) => nft_expr!(payload ipv6 daddr),
+ };
- check_iface(&mut allow_rule, Direction::Out, &tunnel.interface[..])?;
+ check_iface(&mut allow_rule, Direction::Out, interface)?;
check_port(&mut allow_rule, protocol, End::Dst, 53)?;
- check_l3proto(&mut allow_rule, tunnel.gateway)?;
-
- allow_rule.add_expr(&nft_expr!(payload ipv4 daddr))?;
- allow_rule.add_expr(&nft_expr!(cmp == tunnel.gateway))?;
+ check_l3proto(&mut allow_rule, host)?;
+ allow_rule.add_expr(&daddr)?;
+ allow_rule.add_expr(&nft_expr!(cmp == host))?;
add_verdict(&mut allow_rule, &Verdict::Accept)?;
- self.batch.add(&allow_rule, nftnl::MsgType::Add)?;
-
- let mut block_rule = Rule::new(&self.out_chain)?;
- check_port(&mut block_rule, protocol, End::Dst, 53)?;
- add_verdict(&mut block_rule, &Verdict::Drop)?;
- self.batch.add(&block_rule, nftnl::MsgType::Add)?;
+ self.batch.add(&allow_rule, nftnl::MsgType::Add)?;
Ok(())
}
diff --git a/talpid-core/src/firewall/macos.rs b/talpid-core/src/firewall/macos.rs
index b411c58a9a..673f834d85 100644
--- a/talpid-core/src/firewall/macos.rs
+++ b/talpid-core/src/firewall/macos.rs
@@ -102,22 +102,47 @@ impl Firewall {
tunnel,
allow_lan,
} => {
+ let mut rules = vec![];
let allow_tcp_dns_to_relay_rule = self
.create_rule_builder(FilterRuleAction::Pass)
.direction(pfctl::Direction::Out)
.quick(true)
.interface(&tunnel.interface)
.proto(pfctl::Proto::Tcp)
- .to(pfctl::Endpoint::new(tunnel.gateway, 53))
+ .to(pfctl::Endpoint::new(tunnel.ipv4_gateway, 53))
.build()?;
+ rules.push(allow_tcp_dns_to_relay_rule);
let allow_udp_dns_to_relay_rule = self
.create_rule_builder(FilterRuleAction::Pass)
.direction(pfctl::Direction::Out)
.quick(true)
.interface(&tunnel.interface)
.proto(pfctl::Proto::Udp)
- .to(pfctl::Endpoint::new(tunnel.gateway, 53))
+ .to(pfctl::Endpoint::new(tunnel.ipv4_gateway, 53))
.build()?;
+ rules.push(allow_udp_dns_to_relay_rule);
+
+ if let Some(ipv6_gateway) = tunnel.ipv6_gateway {
+ let v6_dns_rule_tcp = self
+ .create_rule_builder(FilterRuleAction::Pass)
+ .direction(pfctl::Direction::Out)
+ .quick(true)
+ .interface(&tunnel.interface)
+ .proto(pfctl::Proto::Tcp)
+ .to(pfctl::Endpoint::new(ipv6_gateway, 53))
+ .build()?;
+ rules.push(v6_dns_rule_tcp);
+ let v6_dns_rule_udp = self
+ .create_rule_builder(FilterRuleAction::Pass)
+ .direction(pfctl::Direction::Out)
+ .quick(true)
+ .interface(&tunnel.interface)
+ .proto(pfctl::Proto::Udp)
+ .to(pfctl::Endpoint::new(ipv6_gateway, 53))
+ .build()?;
+ rules.push(v6_dns_rule_udp);
+ }
+
let block_tcp_dns_rule = self
.create_rule_builder(FilterRuleAction::Drop)
.direction(pfctl::Direction::Out)
@@ -125,6 +150,7 @@ impl Firewall {
.proto(pfctl::Proto::Tcp)
.to(pfctl::Port::from(53))
.build()?;
+ rules.push(block_tcp_dns_rule);
let block_udp_dns_rule = self
.create_rule_builder(FilterRuleAction::Drop)
.direction(pfctl::Direction::Out)
@@ -133,18 +159,14 @@ impl Firewall {
.to(pfctl::Port::from(53))
.build()?;
- let mut rules = vec![
- allow_tcp_dns_to_relay_rule,
- allow_udp_dns_to_relay_rule,
- block_tcp_dns_rule,
- block_udp_dns_rule,
- self.get_allow_relay_rule(peer_endpoint)?,
- self.get_allow_tunnel_rule(tunnel.interface.as_str())?,
- ];
+ rules.push(block_udp_dns_rule);
+ rules.push(self.get_allow_relay_rule(peer_endpoint)?);
+ rules.push(self.get_allow_tunnel_rule(tunnel.interface.as_str())?);
if allow_lan {
rules.append(&mut self.get_allow_lan_rules()?);
}
+
Ok(rules)
}
FirewallPolicy::Blocked { allow_lan } => {
diff --git a/talpid-core/src/firewall/mod.rs b/talpid-core/src/firewall/mod.rs
index 059a49e326..865226ae4d 100644
--- a/talpid-core/src/firewall/mod.rs
+++ b/talpid-core/src/firewall/mod.rs
@@ -100,7 +100,7 @@ impl fmt::Display for FirewallPolicy {
allow_lan,
} => write!(
f,
- "Connected to {} over \"{}\" (ip: {}, gw: {}), {} LAN",
+ "Connected to {} over \"{}\" (ip: {}, v4 gw: {}, v6 gw; {:?}), {} LAN",
peer_endpoint,
tunnel.interface,
tunnel
@@ -109,7 +109,8 @@ impl fmt::Display for FirewallPolicy {
.map(|ip| ip.to_string())
.collect::<Vec<_>>()
.join(","),
- tunnel.gateway,
+ tunnel.ipv4_gateway,
+ tunnel.ipv6_gateway,
if *allow_lan { "Allowing" } else { "Blocking" }
),
FirewallPolicy::Blocked { allow_lan } => write!(
diff --git a/talpid-core/src/firewall/windows.rs b/talpid-core/src/firewall/windows.rs
index 16702b62f9..d9f8c19fbe 100644
--- a/talpid-core/src/firewall/windows.rs
+++ b/talpid-core/src/firewall/windows.rs
@@ -141,7 +141,7 @@ impl Firewall {
) -> Result<()> {
trace!("Applying 'connected' firewall policy");
let ip_str = Self::widestring_ip(&endpoint.address.ip());
- let gateway_str = Self::widestring_ip(&tunnel_metadata.gateway.into());
+ let gateway_str = Self::widestring_ip(&tunnel_metadata.ipv4_gateway.into());
let tunnel_alias =
WideCString::new(tunnel_metadata.interface.encode_utf16().collect::<Vec<_>>()).unwrap();
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index d7506b3b7c..d386fd641c 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -3,7 +3,7 @@ use std::{
collections::HashMap,
ffi::OsString,
io,
- net::IpAddr,
+ net::{IpAddr, Ipv4Addr, Ipv6Addr},
path::{Path, PathBuf},
};
#[cfg(unix)]
@@ -71,7 +71,9 @@ pub struct TunnelMetadata {
/// The local IPs on the tunnel interface.
pub ips: Vec<IpAddr>,
/// The IP to the default gateway on the tunnel interface.
- pub gateway: IpAddr,
+ pub ipv4_gateway: Ipv4Addr,
+ /// The IP to the IPv6 default gateway on the tunnel interface.
+ pub ipv6_gateway: Option<Ipv6Addr>,
}
impl TunnelEvent {
@@ -96,15 +98,21 @@ impl TunnelEvent {
.expect("No \"ifconfig_local\" in tunnel up event")
.parse()
.expect("Tunnel IP not in valid format")];
- let gateway = env
+ let ipv4_gateway = env
.get("route_vpn_gateway")
.expect("No \"route_vpn_gateway\" in tunnel up event")
.parse()
.expect("Tunnel gateway IP not in valid format");
+ let ipv6_gateway = env.get("route_ipv6_gateway_1").map(|v6_str| {
+ v6_str
+ .parse()
+ .expect("V6 Tunnel gateway IP not in valid format")
+ });
Some(TunnelEvent::Up(TunnelMetadata {
interface,
ips,
- gateway,
+ ipv4_gateway,
+ ipv6_gateway,
}))
}
openvpn_plugin::EventType::RoutePredown => Some(TunnelEvent::Down),
diff --git a/talpid-core/src/tunnel/wireguard/config.rs b/talpid-core/src/tunnel/wireguard/config.rs
index ff167edb7c..e04a45618d 100644
--- a/talpid-core/src/tunnel/wireguard/config.rs
+++ b/talpid-core/src/tunnel/wireguard/config.rs
@@ -1,10 +1,15 @@
-use std::{borrow::Cow, ffi::CString, net::IpAddr};
+use std::{
+ borrow::Cow,
+ ffi::CString,
+ net::{Ipv4Addr, Ipv6Addr},
+};
use talpid_types::net::{wireguard, GenericTunnelOptions};
pub struct Config {
pub tunnel: wireguard::TunnelConfig,
pub peers: Vec<wireguard::PeerConfig>,
- pub gateway: IpAddr,
+ pub ipv4_gateway: Ipv4Addr,
+ pub ipv6_gateway: Option<Ipv6Addr>,
pub mtu: u16,
#[cfg(target_os = "linux")]
pub fwmark: i32,
@@ -37,7 +42,7 @@ impl Config {
Self::new(
tunnel,
peer,
- params.connection.gateway,
+ &params.connection,
&params.options,
&params.generic_options,
)
@@ -46,7 +51,7 @@ impl Config {
pub fn new(
mut tunnel: wireguard::TunnelConfig,
mut peers: Vec<wireguard::PeerConfig>,
- gateway: IpAddr,
+ connection_config: &wireguard::ConnectionConfig,
wg_options: &wireguard::TunnelOptions,
generic_options: &GenericTunnelOptions,
) -> Result<Config> {
@@ -77,7 +82,13 @@ impl Config {
Ok(Config {
tunnel,
peers,
- gateway,
+ ipv4_gateway: connection_config.ipv4_gateway,
+ // Only set the v6 gateway if setting a v6 gateway makes sense
+ ipv6_gateway: if is_ipv6_enabled {
+ connection_config.ipv6_gateway
+ } else {
+ None
+ },
mtu,
#[cfg(target_os = "linux")]
fwmark: wg_options.fwmark,
diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs
index 71ccee1b44..925552ad5f 100644
--- a/talpid-core/src/tunnel/wireguard/mod.rs
+++ b/talpid-core/src/tunnel/wireguard/mod.rs
@@ -1,7 +1,7 @@
use self::config::Config;
use super::{TunnelEvent, TunnelMetadata};
use crate::routing;
-use std::{path::Path, sync::mpsc};
+use std::{net::IpAddr, path::Path, sync::mpsc};
pub mod config;
mod ping_monitor;
@@ -79,7 +79,7 @@ impl WireguardMonitor {
monitor.tunnel_up(&config);
ping_monitor::ping(
- config.gateway,
+ config.ipv4_gateway.into(),
PING_TIMEOUT,
&monitor.tunnel.get_interface_name().to_string(),
)
@@ -152,7 +152,7 @@ impl WireguardMonitor {
let close_sender = self.close_msg_sender.clone();
ping_monitor::spawn_ping_monitor(
- config.gateway,
+ IpAddr::from(config.ipv4_gateway),
PING_TIMEOUT,
self.tunnel.get_interface_name().to_string(),
move || {
@@ -166,7 +166,8 @@ impl WireguardMonitor {
let metadata = TunnelMetadata {
interface: interface_name.to_string(),
ips: config.tunnel.addresses.clone(),
- gateway: config.gateway,
+ ipv4_gateway: config.ipv4_gateway,
+ ipv6_gateway: config.ipv6_gateway,
};
(self.event_callback)(TunnelEvent::Up(metadata));
}
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index 1a979476e7..ffca534565 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -72,9 +72,14 @@ impl ConnectedState {
}
fn set_dns(&self, shared_values: &mut SharedTunnelStateValues) -> Result<()> {
+ let mut dns_ips = vec![self.metadata.ipv4_gateway.into()];
+ if let Some(ipv6_gateway) = self.metadata.ipv6_gateway {
+ dns_ips.push(ipv6_gateway.into());
+ };
+
shared_values
.dns_monitor
- .set(&self.metadata.interface, &[self.metadata.gateway.into()])
+ .set(&self.metadata.interface, &dns_ips)
.chain_err(|| "Failed to set system DNS settings")
}
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index 10c693f5ef..b073ade768 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -372,7 +372,13 @@ impl TunnelState for ConnectingState {
fn gateway_list_from_params(params: &TunnelParameters) -> Vec<IpAddr> {
match params {
- TunnelParameters::Wireguard(params) => vec![params.connection.gateway],
+ TunnelParameters::Wireguard(params) => {
+ let mut gateways = vec![params.connection.ipv4_gateway.into()];
+ if let Some(ipv6_gateway) = params.connection.ipv6_gateway {
+ gateways.push(ipv6_gateway.into())
+ };
+ gateways
+ }
// No gateway list required when connecting to openvpn
TunnelParameters::OpenVpn(_) => vec![],
}