OpenVPN 3 Core Library
Loading...
Searching...
No Matches
cliemuexr.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Emulate Excluded Routes implementation (needed by Android)
13
14#ifndef OPENVPN_CLIENT_CLIEMUEXR_H
15#define OPENVPN_CLIENT_CLIEMUEXR_H
16
20
21namespace openvpn {
23{
24 public:
25 OPENVPN_EXCEPTION(emulate_exclude_route_error);
26
28
29 explicit EmulateExcludeRouteImpl(const bool exclude_server_address)
30 : exclude_server_address_(exclude_server_address)
31 {
32 }
33
34 private:
35 void add_route(const bool add, const IP::Addr &addr, const int prefix_len) override
36 {
37 (add ? include : exclude).emplace_back(addr, prefix_len);
38 }
39
40 void add_default_routes(bool ipv4, bool ipv6) override
41 {
42 if (ipv4)
44 if (ipv6)
46 }
47
48 bool enabled(const IPVerFlags &ipv) const override
49 {
50 return exclude.size() && (ipv.rgv4() || ipv.rgv6());
51 }
52
53 void emulate(TunBuilderBase *tb, IPVerFlags &ipv, const IP::Addr &server_addr) const override
54 {
55 const unsigned int ip_ver_flags = ipv.ip_ver_flags();
56 IP::RouteList rl, tempExcludeList;
57 rl.reserve(include.size() + exclude.size());
58 rl.insert(rl.end(), include.begin(), include.end());
59 rl.insert(rl.end(), exclude.begin(), exclude.end());
60
61 // Check if we have to exclude the server, if yes we temporarily add it to the list
62 // of excluded networks as small individual /32 or /128 network
63 const IP::RouteList *excludedRoutes = &exclude;
64
66 && (server_addr.version_mask() & ip_ver_flags)
67 && !exclude.contains(IP::Route(server_addr, server_addr.size())))
68 {
69 rl.emplace_back(server_addr, server_addr.size());
70 // Create a temporary list that includes all the routes + the server
71 tempExcludeList = exclude;
72 tempExcludeList.emplace_back(server_addr, server_addr.size());
73 excludedRoutes = &tempExcludeList;
74 }
75
76
77 if (excludedRoutes->empty())
78 {
79 // Samsung's Android VPN API does different things if you have
80 // 0.0.0.0/0 in the list of installed routes
81 // (even if 0.0.0.0/1 and 128.0.0.0/1 and are present it behaves different)
82
83 // We normally always split the address space, breaking a 0.0.0.0/0 into
84 // smaller routes. If no routes are excluded, we install the original
85 // routes without modifying them
86
87 for (const auto &rt : include)
88 {
89 if (rt.version() & ip_ver_flags)
90 {
91 if (!tb->tun_builder_add_route(rt.addr.to_string(), rt.prefix_len, -1, rt.addr.version() == IP::Addr::V6))
92 throw emulate_exclude_route_error("tun_builder_add_route failed");
93 }
94 }
95 return;
96 }
97
98 // Complete address space (0.0.0.0/0 or ::/0) split into smaller networks
99 // Figure out which parts of this non overlapping address we want to install
100 for (const auto &r : IP::AddressSpaceSplitter(rl, ip_ver_flags))
101 {
102 if (check_route_should_be_installed(r, *excludedRoutes))
103 if (!tb->tun_builder_add_route(r.addr.to_string(), r.prefix_len, -1, r.addr.version() == IP::Addr::V6))
104 throw emulate_exclude_route_error("tun_builder_add_route failed");
105 }
106
108 }
109
110 bool check_route_should_be_installed(const IP::Route &r, const IP::RouteList &excludedRoutes) const
111 {
112 // The whole address space was partioned into NON-overlapping routes that
113 // we get one by one with the parameter r.
114 // Therefore we already know that the whole route r either is included or
115 // excluded IPs.
116 // Figure out if this particular route should be installed or not
117
118 IP::Route const *bestroute = nullptr;
119 // Get the best (longest-prefix/smallest) route from included routes that completely
120 // matches this route
121 for (const auto &incRoute : include)
122 {
123 if (incRoute.contains(r))
124 {
125 if (!bestroute || bestroute->prefix_len < incRoute.prefix_len)
126 bestroute = &incRoute;
127 }
128 }
129
130 // No positive route matches the route at all, do not install it
131 if (!bestroute)
132 return false;
133
134 // Check if there is a more specific exclude route
135 for (const auto &exclRoute : excludedRoutes)
136 {
137 if (exclRoute.contains(r) && exclRoute.prefix_len > bestroute->prefix_len)
138 return false;
139 }
140 return true;
141 }
142
146};
147
149{
150 public:
152
153 EmulateExcludeRouteFactoryImpl(const bool exclude_server_address)
154 : exclude_server_address_(exclude_server_address)
155 {
156 }
157
158 private:
163
165};
166} // namespace openvpn
167
168#endif
RCPtr< EmulateExcludeRouteFactoryImpl > Ptr
EmulateExcludeRouteFactoryImpl(const bool exclude_server_address)
EmulateExcludeRoute::Ptr new_obj() const override
OPENVPN_EXCEPTION(emulate_exclude_route_error)
void add_default_routes(bool ipv4, bool ipv6) override
Definition cliemuexr.hpp:40
void emulate(TunBuilderBase *tb, IPVerFlags &ipv, const IP::Addr &server_addr) const override
Definition cliemuexr.hpp:53
EmulateExcludeRouteImpl(const bool exclude_server_address)
Definition cliemuexr.hpp:29
bool check_route_should_be_installed(const IP::Route &r, const IP::RouteList &excludedRoutes) const
RCPtr< EmulateExcludeRouteImpl > Ptr
Definition cliemuexr.hpp:27
void add_route(const bool add, const IP::Addr &addr, const int prefix_len) override
Definition cliemuexr.hpp:35
bool enabled(const IPVerFlags &ipv) const override
Definition cliemuexr.hpp:48
IP::Addr::VersionMask ip_ver_flags() const
bool rgv6() const
bool rgv4() const
void set_emulate_exclude_routes()
unsigned int size() const
Definition ip.hpp:1016
static VersionMask version_mask(const Version ver)
Definition ip.hpp:900
static Addr from_zero(const Version v)
Definition ip.hpp:450
unsigned int prefix_len
Definition route.hpp:38
The smart pointer class.
Definition rc.hpp:119
TunBuilder methods, loosely based on the Android VpnService.Builder abstraction.
Definition base.hpp:42
virtual bool tun_builder_add_route(const std::string &address, int prefix_length, int metric, bool ipv6)
Callback to add a route to the VPN interface.
Definition base.hpp:158
RCPtr< EmulateExcludeRoute > Ptr
Definition emuexr.hpp:24
bool contains(const R &c) const
Definition route.hpp:348
remote_address ipv6
reroute_gw ipv4
int prefix_len(const IPv4::Addr::base_type mask)
static void add(const Time &t1, const Time::Duration &d1)