summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--talpid-core/src/split.rs55
-rw-r--r--talpid-core/src/tunnel_state_machine/connected_state.rs18
2 files changed, 68 insertions, 5 deletions
diff --git a/talpid-core/src/split.rs b/talpid-core/src/split.rs
index 04a57c2034..cab42fd265 100644
--- a/talpid-core/src/split.rs
+++ b/talpid-core/src/split.rs
@@ -2,6 +2,7 @@ use regex::Regex;
use std::{
fs,
io::{self, BufRead, BufReader, Write},
+ net::IpAddr,
path::Path,
process::Command,
};
@@ -45,6 +46,14 @@ pub enum Error {
/// Unable to read cgroup.procs.
#[error(display = "Unable to obtain PIDs from cgroup.procs")]
ListCGroupPids(#[error(source)] io::Error),
+
+ /// Unable to add setup DNS routing.
+ #[error(display = "Failed to add routing table DNS rules")]
+ SetDns(#[error(source)] io::Error),
+
+ /// Unable to flush routing table.
+ #[error(display = "Failed to clear routing table DNS rules")]
+ FlushDns(#[error(source)] io::Error),
}
/// Route PID-associated packets through the physical interface.
@@ -75,6 +84,52 @@ pub fn route_marked_packets() -> Result<(), Error> {
cmd.output().map(|_| ()).map_err(Error::RoutingTableSetup)
}
+/// Route DNS requests through the tunnel interface.
+pub fn route_dns(tunnel_alias: &str, dns_servers: &[IpAddr]) -> Result<(), Error> {
+ // TODO: IPv6
+
+ let mut cmd = Command::new("ip");
+ cmd.args(&["-4", "route", "flush", "table", ROUTING_TABLE_NAME]);
+
+ log::trace!("running cmd - {:?}", &cmd);
+ cmd.output().map_err(Error::SetDns)?;
+
+ for server in dns_servers {
+ if let IpAddr::V4(addr) = server {
+ let addr = addr.to_string();
+
+ let mut cmd = Command::new("ip");
+ cmd.args(&[
+ "-4",
+ "route",
+ "add",
+ &addr,
+ "via",
+ &addr,
+ "dev",
+ tunnel_alias,
+ "table",
+ ROUTING_TABLE_NAME,
+ ]);
+
+ log::trace!("running cmd - {:?}", &cmd);
+ cmd.output().map_err(Error::SetDns)?;
+ }
+ }
+
+ Ok(())
+}
+
+/// Reset DNS rules.
+pub fn flush_dns() -> Result<(), Error> {
+ // For now, simply flush it
+ let mut cmd = Command::new("ip");
+ cmd.args(&["-4", "route", "flush", "table", ROUTING_TABLE_NAME]);
+
+ log::trace!("running cmd - {:?}", &cmd);
+ cmd.output().map(|_| ()).map_err(Error::FlushDns)
+}
+
/// Set up policy-based routing for marked packets.
pub fn initialize_routing_table() -> Result<(), Error> {
// TODO: ensure the ID does not conflict with that of another table
diff --git a/talpid-core/src/tunnel_state_machine/connected_state.rs b/talpid-core/src/tunnel_state_machine/connected_state.rs
index deb7e265a4..e936499f47 100644
--- a/talpid-core/src/tunnel_state_machine/connected_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connected_state.rs
@@ -4,6 +4,7 @@ use super::{
};
use crate::{
firewall::FirewallPolicy,
+ split,
tunnel::{CloseHandle, TunnelEvent, TunnelMetadata},
};
use futures01::{
@@ -13,7 +14,7 @@ use futures01::{
use talpid_types::{
net::{Endpoint, TunnelParameters},
tunnel::ErrorStateCause,
- ErrorExt,
+ BoxedError, ErrorExt,
};
pub struct ConnectedStateBootstrap {
@@ -69,10 +70,7 @@ impl ConnectedState {
}
}
- fn set_dns(
- &self,
- shared_values: &mut SharedTunnelStateValues,
- ) -> Result<(), crate::dns::Error> {
+ fn set_dns(&self, shared_values: &mut SharedTunnelStateValues) -> Result<(), BoxedError> {
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());
@@ -81,9 +79,19 @@ impl ConnectedState {
shared_values
.dns_monitor
.set(&self.metadata.interface, &dns_ips)
+ .map_err(BoxedError::new)?;
+
+ split::route_dns(&self.metadata.interface, &dns_ips).map_err(BoxedError::new)
}
fn reset_dns(shared_values: &mut SharedTunnelStateValues) {
+ if let Err(error) = split::flush_dns() {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Unable to update split-tunnel route")
+ );
+ }
+
if let Err(error) = shared_values.dns_monitor.reset() {
log::error!("{}", error.display_chain_with_msg("Unable to reset DNS"));
}