summaryrefslogtreecommitdiffhomepage
path: root/talpid-tunnel/src/tun_provider/mod.rs
blob: 7174427df2a461b7bad8257e9d030a967385db8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#[cfg(target_os = "android")]
use crate::tun_provider::imp::VpnServiceConfig;
use cfg_if::cfg_if;
use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

cfg_if! {
    if #[cfg(target_os = "android")] {
        #[path = "android/mod.rs"]
        mod imp;
        use self::imp::{AndroidTunProvider, VpnServiceTun};
        pub use self::imp::Error;

        pub type Tun = VpnServiceTun;
        pub type TunProvider = AndroidTunProvider;
    } else if #[cfg(all(unix, not(target_os = "android")))] {
        #[path = "unix.rs"]
        mod imp;
        use self::imp::{UnixTun, UnixTunProvider};
        pub use self::imp::Error;

        pub type Tun = UnixTun;
        pub type TunProvider = UnixTunProvider;
    } else if #[cfg(all(windows, feature = "boringtun"))] {
        #[path = "windows.rs"]
        mod imp;
        use self::imp::{WindowsTun, WindowsTunProvider};
        pub use self::imp::Error;

        pub type Tun = WindowsTun;
        pub type TunProvider = WindowsTunProvider;
    } else {
        mod stub;
        use self::stub::StubTunProvider;
        pub use self::stub::Error;

        pub type TunProvider = StubTunProvider;
    }
}

/// Configuration for creating a tunnel device.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TunConfig {
    /// Interface name to use.
    #[cfg(target_os = "linux")]
    pub name: Option<String>,

    /// Whether to enable the packet_information option on the tun device.
    #[cfg(target_os = "linux")]
    pub packet_information: bool,

    /// IP addresses for the tunnel interface.
    pub addresses: Vec<IpAddr>,

    /// MTU of the tunnel interface.
    pub mtu: u16,

    /// IPv4 address of the VPN server, and the default IPv4 DNS resolver.
    pub ipv4_gateway: Ipv4Addr,

    /// IPv6 address of the VPN server, and the default IPv6 DNS resolver.
    pub ipv6_gateway: Option<Ipv6Addr>,

    /// Routes to configure for the tunnel.
    pub routes: Vec<IpNetwork>,

    /// Exclude private IPs from the tunnel
    pub allow_lan: bool,

    /// DNS servers to use for the tunnel config.
    /// Unless specified, the gateways will be used for DNS
    pub dns_servers: Option<Vec<IpAddr>>,

    /// Applications to exclude from the tunnel.
    pub excluded_packages: Vec<String>,
}

impl TunConfig {
    /// Return a copy of all gateway addresses
    pub fn gateways(&self) -> Vec<IpAddr> {
        let mut servers = vec![self.ipv4_gateway.into()];
        if let Some(gateway) = self.ipv6_gateway {
            servers.push(gateway.into());
        }
        servers
    }

    /// Routes to configure for the tunnel.
    #[cfg(target_os = "android")]
    pub fn real_routes(&self) -> Vec<IpNetwork> {
        VpnServiceConfig::new(self.clone())
            .routes
            .iter()
            .map(IpNetwork::from)
            .collect()
    }
}

/// Return a tunnel configuration that routes all traffic inside the tunnel.
///
/// Most values except the routes are nonsensical. This is mostly used as a reasonable default on
/// Android to route all traffic inside the tunnel.
pub fn blocking_config() -> TunConfig {
    TunConfig {
        #[cfg(target_os = "linux")]
        name: None,
        #[cfg(target_os = "linux")]
        packet_information: false,
        addresses: vec![IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))],
        mtu: 1380,
        ipv4_gateway: Ipv4Addr::new(10, 64, 0, 1),
        ipv6_gateway: None,
        routes: DEFAULT_ROUTES.to_vec(),
        allow_lan: false,
        dns_servers: None,
        excluded_packages: vec![],
    }
}

const DEFAULT_ROUTES: [IpNetwork; 2] = [
    IpNetwork::V4(IPV4_DEFAULT_ROUTE),
    IpNetwork::V6(IPV6_DEFAULT_ROUTE),
];
const IPV4_DEFAULT_ROUTE: Ipv4Network = Ipv4Network::new_checked(Ipv4Addr::UNSPECIFIED, 0).unwrap();
const IPV6_DEFAULT_ROUTE: Ipv6Network = Ipv6Network::new_checked(Ipv6Addr::UNSPECIFIED, 0).unwrap();