summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--mullvad-cli/src/cmds/relay.rs28
-rw-r--r--mullvad-daemon/src/lib.rs9
-rw-r--r--mullvad-daemon/src/relays.rs3
-rw-r--r--mullvad-types/src/endpoint.rs14
-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.rs22
-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
-rw-r--r--talpid-types/src/net/wireguard.rs5
-rw-r--r--windows/windns/src/windns/windns.cpp2
-rw-r--r--windows/winfw/src/winfw/fwcontext.cpp6
-rw-r--r--windows/winfw/src/winfw/fwcontext.h2
-rw-r--r--windows/winfw/src/winfw/rules/restrictdns.cpp68
-rw-r--r--windows/winfw/src/winfw/rules/restrictdns.h6
-rw-r--r--windows/winfw/src/winfw/winfw.cpp5
-rw-r--r--windows/winfw/src/winfw/winfw.h3
24 files changed, 212 insertions, 135 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86b20c7df1..8986bc1516 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,7 @@ Line wrap the file at 100 chars. Th
- Fix the bug which caused the account token history to remain stale after logout.
- Fix some notifications not appearing depending on how the window is shown and hidden while the
tunnel state changes.
+- Fix DNS when using IPv6.
#### Linux
- Fix startup failure when network device with a hardware address that's not a MAC address is
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index d2948ec315..0d2c5c3bca 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -2,7 +2,7 @@ use crate::{new_rpc_client, Command, Result, ResultExt};
use clap::{value_t, values_t};
use std::{
io::{self, BufRead},
- net::{IpAddr, Ipv4Addr, SocketAddr},
+ net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
str::FromStr,
};
@@ -55,11 +55,17 @@ impl Command for Relay {
.required(false),
)
.arg(
- clap::Arg::with_name("gateway")
- .help("Gateway address")
- .long("gateway")
+ clap::Arg::with_name("v4-gateway")
+ .help("IPv4 gateway address")
+ .long("v4-gateway")
.index(4)
.required(false),
+ ).arg(
+ clap::Arg::with_name("v6-gateway")
+ .help("IPv6 gateway address")
+ .long("v6-gateway")
+ .takes_value(true)
+ .required(false),
)
.arg(
clap::Arg::with_name("addr")
@@ -224,10 +230,17 @@ impl Relay {
let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit());
let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit());
let addresses = values_t!(matches.values_of("addr"), IpAddr).unwrap_or_else(|e| e.exit());
- println!("addresses - {:?}", addresses);
let peer_key_str =
value_t!(matches.value_of("peer-key"), String).unwrap_or_else(|e| e.exit());
- let gateway = value_t!(matches.value_of("gateway"), IpAddr).unwrap_or_else(|e| e.exit());
+ let ipv4_gateway =
+ value_t!(matches.value_of("v4-gateway"), Ipv4Addr).unwrap_or_else(|e| e.exit());
+ let ipv6_gateway = match value_t!(matches.value_of("v6-gateway"), Ipv6Addr) {
+ Ok(gateway) => Some(gateway),
+ Err(e) => match e.kind {
+ clap::ErrorKind::ArgumentNotFound => None,
+ _ => e.exit(),
+ },
+ };
let mut private_key_str = String::new();
println!("Reading private key from standard input");
let _ = io::stdin().lock().read_line(&mut private_key_str);
@@ -250,7 +263,8 @@ impl Relay {
allowed_ips: all_of_the_internet(),
endpoint: SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), port),
},
- gateway,
+ ipv4_gateway,
+ ipv6_gateway,
}),
)
}
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 07d7cd3e4f..6e2bdd4a79 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -391,7 +391,11 @@ impl Daemon {
generic_options: tunnel_options.generic,
}
.into()),
- MullvadEndpoint::Wireguard { peer, gateway } => {
+ MullvadEndpoint::Wireguard {
+ peer,
+ ipv4_gateway,
+ ipv6_gateway,
+ } => {
let wg_data = self
.account_history
.get(&account_token)?
@@ -408,7 +412,8 @@ impl Daemon {
connection: wireguard::ConnectionConfig {
tunnel,
peer,
- gateway,
+ ipv4_gateway,
+ ipv6_gateway: Some(ipv6_gateway),
},
options: tunnel_options.wireguard,
generic_options: tunnel_options.generic,
diff --git a/mullvad-daemon/src/relays.rs b/mullvad-daemon/src/relays.rs
index 68c7c4bb11..b38ba42cfc 100644
--- a/mullvad-daemon/src/relays.rs
+++ b/mullvad-daemon/src/relays.rs
@@ -423,7 +423,8 @@ impl RelaySelector {
};
Some(MullvadEndpoint::Wireguard {
peer: peer_config,
- gateway: data.ipv4_gateway.into(),
+ ipv4_gateway: data.ipv4_gateway,
+ ipv6_gateway: data.ipv6_gateway,
})
}
diff --git a/mullvad-types/src/endpoint.rs b/mullvad-types/src/endpoint.rs
index f6818a8854..4a2371472e 100644
--- a/mullvad-types/src/endpoint.rs
+++ b/mullvad-types/src/endpoint.rs
@@ -1,5 +1,8 @@
use serde::{Deserialize, Serialize};
-use std::{fmt, net::IpAddr};
+use std::{
+ fmt,
+ net::{Ipv4Addr, Ipv6Addr},
+};
use talpid_types::net::{wireguard, Endpoint, TransportProtocol};
use crate::relay_list::{OpenVpnEndpointData, WireguardEndpointData};
@@ -11,7 +14,8 @@ pub enum MullvadEndpoint {
OpenVpn(Endpoint),
Wireguard {
peer: wireguard::PeerConfig,
- gateway: IpAddr,
+ ipv4_gateway: Ipv4Addr,
+ ipv6_gateway: Ipv6Addr,
},
}
@@ -20,7 +24,11 @@ impl MullvadEndpoint {
pub fn to_endpoint(&self) -> Endpoint {
match self {
MullvadEndpoint::OpenVpn(endpoint) => *endpoint,
- MullvadEndpoint::Wireguard { peer, gateway: _ } => Endpoint::new(
+ MullvadEndpoint::Wireguard {
+ peer,
+ ipv4_gateway: _,
+ ipv6_gateway: _,
+ } => Endpoint::new(
peer.endpoint.ip(),
peer.endpoint.port(),
TransportProtocol::Udp,
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..143dd1cd4e 100644
--- a/talpid-core/src/firewall/windows.rs
+++ b/talpid-core/src/firewall/windows.rs
@@ -116,7 +116,7 @@ impl Firewall {
winfw_settings: &WinFwSettings,
) -> Result<()> {
trace!("Applying 'connecting' firewall policy");
- let ip_str = Self::widestring_ip(&endpoint.address.ip());
+ let ip_str = Self::widestring_ip(endpoint.address.ip());
// ip_str has to outlive winfw_relay
let winfw_relay = WinFwRelay {
@@ -128,7 +128,7 @@ impl Firewall {
unsafe { WinFw_ApplyPolicyConnecting(winfw_settings, &winfw_relay).into_result() }
}
- fn widestring_ip(ip: &IpAddr) -> WideCString {
+ fn widestring_ip(ip: IpAddr) -> WideCString {
let buf = ip.to_string().encode_utf16().collect::<Vec<_>>();
WideCString::new(buf).unwrap()
}
@@ -140,8 +140,11 @@ impl Firewall {
tunnel_metadata: &crate::tunnel::TunnelMetadata,
) -> 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 ip_str = Self::widestring_ip(endpoint.address.ip());
+ let v4_gateway = Self::widestring_ip(tunnel_metadata.ipv4_gateway.into());
+ let v6_gateway = tunnel_metadata
+ .ipv6_gateway
+ .map(|v6_ip| Self::widestring_ip(v6_ip.into()));
let tunnel_alias =
WideCString::new(tunnel_metadata.interface.encode_utf16().collect::<Vec<_>>()).unwrap();
@@ -162,12 +165,18 @@ impl Firewall {
debug!("Network interface metrics were not changed");
}
+ let v6_gateway_ptr = match &v6_gateway {
+ Some(v6_ip) => v6_ip.as_ptr(),
+ None => ptr::null(),
+ };
+
unsafe {
WinFw_ApplyPolicyConnected(
winfw_settings,
&winfw_relay,
tunnel_alias.as_wide_c_str().as_ptr(),
- gateway_str.as_wide_c_str().as_ptr(),
+ v4_gateway.as_ptr(),
+ v6_gateway_ptr,
)
.into_result()
}
@@ -260,7 +269,8 @@ mod winfw {
settings: &WinFwSettings,
relay: &WinFwRelay,
tunnelIfaceAlias: *const libc::wchar_t,
- primaryDns: *const libc::wchar_t,
+ v4Gateway: *const libc::wchar_t,
+ v6Gateway: *const libc::wchar_t,
) -> ApplyConnectedResult;
#[link_name = "WinFw_ApplyPolicyBlocked"]
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![],
}
diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs
index fe596fe475..4b8f1084cd 100644
--- a/talpid-types/src/net/wireguard.rs
+++ b/talpid-types/src/net/wireguard.rs
@@ -3,7 +3,7 @@ use ipnetwork::IpNetwork;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt,
- net::{IpAddr, SocketAddr},
+ net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
};
use rand::RngCore;
@@ -21,7 +21,8 @@ pub struct TunnelParameters {
pub struct ConnectionConfig {
pub tunnel: TunnelConfig,
pub peer: PeerConfig,
- pub gateway: IpAddr,
+ pub ipv4_gateway: Ipv4Addr,
+ pub ipv6_gateway: Option<Ipv6Addr>,
}
impl ConnectionConfig {
diff --git a/windows/windns/src/windns/windns.cpp b/windows/windns/src/windns/windns.cpp
index fe674723e2..e082f0826e 100644
--- a/windows/windns/src/windns/windns.cpp
+++ b/windows/windns/src/windns/windns.cpp
@@ -104,8 +104,6 @@ WinDns_Set(
if (nullptr == g_Context
|| nullptr == ipv4Servers
|| 0 == numIpv4Servers
- || nullptr == ipv6Servers
- || 0 == numIpv6Servers
|| nullptr == recoverySink)
{
return false;
diff --git a/windows/winfw/src/winfw/fwcontext.cpp b/windows/winfw/src/winfw/fwcontext.cpp
index c25dbbbe0c..3a90c97b9f 100644
--- a/windows/winfw/src/winfw/fwcontext.cpp
+++ b/windows/winfw/src/winfw/fwcontext.cpp
@@ -89,7 +89,7 @@ bool FwContext::applyPolicyConnecting(const WinFwSettings &settings, const WinFw
return applyRuleset(ruleset);
}
-bool FwContext::applyPolicyConnected(const WinFwSettings &settings, const WinFwRelay &relay, const wchar_t *tunnelInterfaceAlias, const wchar_t *primaryDns)
+bool FwContext::applyPolicyConnected(const WinFwSettings &settings, const WinFwRelay &relay, const wchar_t *tunnelInterfaceAlias, const wchar_t *v4Gateway, const wchar_t *v6Gateway)
{
Ruleset ruleset;
@@ -110,9 +110,11 @@ bool FwContext::applyPolicyConnected(const WinFwSettings &settings, const WinFwR
tunnelInterfaceAlias
));
+ /// We currently expect DNS servers to only be ran on the tunnel gateway IPs
ruleset.emplace_back(std::make_unique<rules::RestrictDns>(
tunnelInterfaceAlias,
- wfp::IpAddress(primaryDns)
+ wfp::IpAddress(v4Gateway),
+ (v6Gateway != nullptr) ? &wfp::IpAddress(v6Gateway) : nullptr
));
return applyRuleset(ruleset);
diff --git a/windows/winfw/src/winfw/fwcontext.h b/windows/winfw/src/winfw/fwcontext.h
index d4198be9e4..65c45ac539 100644
--- a/windows/winfw/src/winfw/fwcontext.h
+++ b/windows/winfw/src/winfw/fwcontext.h
@@ -14,7 +14,7 @@ public:
FwContext(uint32_t timeout);
bool applyPolicyConnecting(const WinFwSettings &settings, const WinFwRelay &relay);
- bool applyPolicyConnected(const WinFwSettings &settings, const WinFwRelay &relay, const wchar_t *tunnelInterfaceAlias, const wchar_t *primaryDns);
+ bool applyPolicyConnected(const WinFwSettings &settings, const WinFwRelay &relay, const wchar_t *tunnelInterfaceAlias, const wchar_t *v4DnsHosts, const wchar_t *v6DnsHost);
bool applyPolicyBlocked(const WinFwSettings &settings);
bool reset();
diff --git a/windows/winfw/src/winfw/rules/restrictdns.cpp b/windows/winfw/src/winfw/rules/restrictdns.cpp
index d8a953fb3a..53c303cc47 100644
--- a/windows/winfw/src/winfw/rules/restrictdns.cpp
+++ b/windows/winfw/src/winfw/rules/restrictdns.cpp
@@ -12,9 +12,11 @@ using namespace wfp::conditions;
namespace rules
{
-RestrictDns::RestrictDns(const std::wstring &tunnelInterfaceAlias, const wfp::IpAddress &dns)
+RestrictDns::RestrictDns(const std::wstring &tunnelInterfaceAlias, const wfp::IpAddress v4DnsHost, wfp::IpAddress *v6DnsHost)
: m_tunnelInterfaceAlias(tunnelInterfaceAlias)
- , m_dns(dns)
+ , m_v4DnsHost(v4DnsHost)
+ , m_v6DnsHost(v6DnsHost)
+
{
}
@@ -73,52 +75,29 @@ bool RestrictDns::apply(IObjectInstaller &objectInstaller)
}
}
- //
- // This next part is a little redundant since the entire rule could be defined
- // using three filters. Let's use four filters to maintain some kind of readability.
- //
- // The reason it would be possible to use three filters is because the single DNS
- // is going to be either v4 or v6, so all requests that cannot be sent to the DNS
- // will have to be blocked (thereby shadowing one of the filters above).
- //
filterBuilder
- .name(L"Restrict DNS requests inside the VPN tunnel");
+ .name(L"Restrict IPv4 DNS requests inside the VPN tunnel")
+ .key(MullvadGuids::FilterRestrictDns_Outbound_Tunnel_Ipv4())
+ .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
- if (m_dns.type() == wfp::IpAddress::Type::Ipv4)
{
- filterBuilder
- .key(MullvadGuids::FilterRestrictDns_Outbound_Tunnel_Ipv4())
- .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
-
- {
- wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
-
- conditionBuilder.add_condition(ConditionPort::Remote(53));
- conditionBuilder.add_condition(ConditionIp::Remote(m_dns, CompareNeq()));
-
- if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
- {
- return false;
- }
- }
-
- filterBuilder
- .key(MullvadGuids::FilterRestrictDns_Outbound_Tunnel_Ipv6())
- .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
-
- wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
+ wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
conditionBuilder.add_condition(ConditionPort::Remote(53));
+ conditionBuilder.add_condition(ConditionIp::Remote(m_v4DnsHost, CompareNeq()));
- return objectInstaller.addFilter(filterBuilder, conditionBuilder);
+ if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
+ {
+ return false;
+ }
}
//
// Specified DNS is IPv6
//
-
filterBuilder
+ .name(L"Restrict IPv6 DNS requests inside the VPN tunnel")
.key(MullvadGuids::FilterRestrictDns_Outbound_Tunnel_Ipv6())
.layer(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
@@ -126,23 +105,12 @@ bool RestrictDns::apply(IObjectInstaller &objectInstaller)
wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V6);
conditionBuilder.add_condition(ConditionPort::Remote(53));
- conditionBuilder.add_condition(ConditionIp::Remote(m_dns, CompareNeq()));
-
- if (!objectInstaller.addFilter(filterBuilder, conditionBuilder))
- {
- return false;
+ if (m_v6DnsHost != nullptr) {
+ conditionBuilder.add_condition(ConditionIp::Remote(*m_v6DnsHost, CompareNeq()));
}
- }
- filterBuilder
- .key(MullvadGuids::FilterRestrictDns_Outbound_Tunnel_Ipv4())
- .layer(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
-
- wfp::ConditionBuilder conditionBuilder(FWPM_LAYER_ALE_AUTH_CONNECT_V4);
-
- conditionBuilder.add_condition(ConditionPort::Remote(53));
-
- return objectInstaller.addFilter(filterBuilder, conditionBuilder);
+ return objectInstaller.addFilter(filterBuilder, conditionBuilder);
+ }
}
}
diff --git a/windows/winfw/src/winfw/rules/restrictdns.h b/windows/winfw/src/winfw/rules/restrictdns.h
index da09e970d3..ca3057a5cd 100644
--- a/windows/winfw/src/winfw/rules/restrictdns.h
+++ b/windows/winfw/src/winfw/rules/restrictdns.h
@@ -11,14 +11,16 @@ class RestrictDns : public IFirewallRule
{
public:
- RestrictDns(const std::wstring &tunnelInterfaceAlias, const wfp::IpAddress &dns);
+ RestrictDns(const std::wstring &tunnelInterfaceAlias, const wfp::IpAddress v4DnsHost, wfp::IpAddress *v6DnsHost);
bool apply(IObjectInstaller &objectInstaller) override;
private:
const std::wstring m_tunnelInterfaceAlias;
- const wfp::IpAddress m_dns;
+ const wfp::IpAddress m_v4DnsHost;
+ const wfp::IpAddress *m_v6DnsHost;
+
};
}
diff --git a/windows/winfw/src/winfw/winfw.cpp b/windows/winfw/src/winfw/winfw.cpp
index 233423d1cd..f391d691b2 100644
--- a/windows/winfw/src/winfw/winfw.cpp
+++ b/windows/winfw/src/winfw/winfw.cpp
@@ -117,7 +117,8 @@ WinFw_ApplyPolicyConnected(
const WinFwSettings &settings,
const WinFwRelay &relay,
const wchar_t *tunnelInterfaceAlias,
- const wchar_t *primaryDns
+ const wchar_t *v4Gateway,
+ const wchar_t *v6Gateway
)
{
if (nullptr == g_fwContext)
@@ -127,7 +128,7 @@ WinFw_ApplyPolicyConnected(
try
{
- return g_fwContext->applyPolicyConnected(settings, relay, tunnelInterfaceAlias, primaryDns);
+ return g_fwContext->applyPolicyConnected(settings, relay, tunnelInterfaceAlias, v4Gateway, v6Gateway);
}
catch (std::exception &err)
{
diff --git a/windows/winfw/src/winfw/winfw.h b/windows/winfw/src/winfw/winfw.h
index 38f92aacf2..f0c1adb2dc 100644
--- a/windows/winfw/src/winfw/winfw.h
+++ b/windows/winfw/src/winfw/winfw.h
@@ -123,7 +123,8 @@ WinFw_ApplyPolicyConnected(
const WinFwSettings &settings,
const WinFwRelay &relay,
const wchar_t *tunnelInterfaceAlias,
- const wchar_t *primaryDns
+ const wchar_t *v4Gateway,
+ const wchar_t *v6Gateway
);
//