OpenVPN 3 Core Library
Loading...
Searching...
No Matches
tunsetup.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
13// Client tun setup for Windows
14
15#pragma once
16
17#include <string>
18#include <sstream>
19#include <ostream>
20#include <memory>
21#include <utility>
22#include <thread>
23#include <algorithm>
24
26#include <openvpn/common/rc.hpp>
32#include <openvpn/time/time.hpp>
33#include <openvpn/tun/proxy.hpp>
39#include <openvpn/win/cmd.hpp>
40
41#if _WIN32_WINNT >= 0x0600 // Vista+
45#endif
46
47#include <versionhelpers.h>
48
49// use IP Helper on Windows by default
50#ifdef OPENVPN_USE_NETSH
51#define TUNWINDOWS Util::TunNETSH
52#else
53#define TUNWINDOWS Util::TunIPHELPER
54#endif
55
56namespace openvpn::TunWin {
57class Setup : public SetupBase
58{
59 public:
61
62 Setup(openvpn_io::io_context &io_context_arg, const Type tun_type, bool allow_local_dns_resolvers_arg)
63 : delete_route_timer(io_context_arg),
64 tun_type_(tun_type),
65 allow_local_dns_resolvers(allow_local_dns_resolvers_arg)
66 {
67 }
68
70 {
71 return tap_;
72 }
73
74 void set_adapter_state(const Util::TapNameGuidPair &tap) override
75 {
76 tap_ = tap;
77 }
78
89 void set_process_id(DWORD process_id)
90 {
91 process_id_ = process_id;
92 }
93
94 HANDLE get_handle(std::ostream &os) override
95 {
96 if (tap_.index_defined())
97 // tap has already been opened
98 return INVALID_HANDLE_VALUE;
99
100 // enumerate available TAP adapters
102 os << "TAP ADAPTERS:" << std::endl
103 << guids.to_string() << std::endl;
104
105 // open TAP device handle
106 std::string path_opened;
107 Win::ScopedHANDLE th(Util::tap_open(tun_type_, guids, path_opened, tap_));
108 os << "Open TAP device \"" + tap_.name + "\" PATH=\"" + path_opened + '\"';
109 if (!th.defined())
110 {
111 os << " FAILED" << std::endl;
112 throw ErrorCode(Error::TUN_IFACE_CREATE, true, "cannot acquire TAP handle");
113 }
114
115 os << " SUCCEEDED" << std::endl;
116 if (tun_type_ == TapWindows6)
117 {
118 Util::TAPDriverVersion version(th());
119 os << version.to_string() << std::endl;
120 }
121
122 return th.release();
123 }
124
125 // Set up the TAP device
126 HANDLE establish(const TunBuilderCapture &pull,
127 const std::wstring &openvpn_app_path,
128 Stop *stop,
129 std::ostream &os,
130 RingBuffer::Ptr ring_buffer) override // defined by SetupBase
131 {
132 // close out old remove cmds, if they exist
133 destroy(os);
134
135 ScopedHANDLE adapter_handle;
136 if (tun_type_ != OvpnDco)
137 adapter_handle.replace(get_handle(os));
139
140 // create ActionLists for setting up and removing adapter properties
141 ActionList::Ptr add_cmds(new ActionList());
143
144 // populate add/remove lists with actions
145 switch (pull.layer())
146 {
148 adapter_config(adapter_handle(), openvpn_app_path, tap_, pull, false, *add_cmds, *remove_cmds, os);
149 break;
151 adapter_config_l2(adapter_handle(), openvpn_app_path, tap_, pull, *add_cmds, *remove_cmds, os);
152 break;
153 default:
154 throw tun_win_setup("layer undefined");
155 }
156 // execute the add actions
157 add_cmds->execute(os);
158
159 // now that the add actions have succeeded,
160 // enable the remove actions
162
163 // if layer 2, save state
164 if (pull.layer() == Layer::OSI_LAYER_2)
165 l2_state.reset(new L2State(tap_, openvpn_app_path));
166
167 if (ring_buffer)
168 register_rings(adapter_handle(), ring_buffer);
169
172
173 return adapter_handle.release();
174 }
175
176 // In layer 2 mode, return true route_delay seconds after
177 // the adapter properties matches the data given in pull.
178 // This method is usually called once per second until it
179 // returns true.
180 bool l2_ready(const TunBuilderCapture &pull) override
181 {
182 const unsigned int route_delay = 5;
183 if (l2_state)
184 {
185 if (l2_state->props_ready.defined())
186 {
187 if (Time::now() >= l2_state->props_ready)
188 return true;
189 }
190 else
191 {
192 const Util::IPNetmask4 vpn_addr(pull, "VPN IP");
193 const Util::IPAdaptersInfo ai;
194 if (ai.is_up(l2_state->tap.index, vpn_addr))
195 l2_state->props_ready = Time::now() + Time::Duration::seconds(route_delay);
196 }
197 }
198 return false;
199 }
200
201 // Finish the layer 2 configuration, should be called
202 // after l2_ready() returns true.
203 void l2_finish(const TunBuilderCapture &pull,
204 Stop *stop,
205 std::ostream &os) override
206 {
207 std::unique_ptr<L2State> l2s(std::move(l2_state));
208 if (l2s)
209 {
211 ActionList::Ptr add_cmds(new ActionList());
212 adapter_config(nh(), l2s->openvpn_app_path, l2s->tap, pull, true, *add_cmds, *remove_cmds, os);
213 add_cmds->execute(os);
214 }
215 }
216
217 void destroy(std::ostream &os) override // defined by DestructorBase
218 {
219 // l2_state
220 l2_state.reset();
221
222 // l2_thread
223 if (l2_thread)
224 {
225 try
226 {
227 l2_thread->join();
228 }
229 catch (...)
230 {
231 }
232 l2_thread.reset();
233 }
234
235 // remove_cmds
236 if (remove_cmds)
237 {
240 }
241
242 delete_route_timer.cancel();
243
245 }
246
247 virtual ~Setup()
248 {
249 std::ostringstream os;
250 destroy(os);
251 }
252
253 DWORD vpn_interface_index() const override
254 {
256 }
257
258 static void add_bypass_route(const Util::BestGateway &gw,
259 const std::string &route,
260 bool ipv6,
261 ActionList &add_cmds,
262 ActionList &remove_cmds_bypass_gw)
263 {
264 if (!ipv6)
265 {
266 if (!gw.local_route())
267 {
268 add_cmds.add(new WinCmd("netsh interface ip add route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active"));
269 remove_cmds_bypass_gw.add(new WinCmd("netsh interface ip delete route " + route + "/32 " + to_string(gw.interface_index()) + ' ' + gw.gateway_address() + " store=active"));
270 }
271 else
272 {
273 OPENVPN_LOG("Skip bypass route to " << route << ", route is local");
274 }
275 }
276 }
277
278 private:
279 struct L2State
280 {
282 const std::wstring &openvpn_app_path_arg)
283 : tap(tap_arg),
284 openvpn_app_path(openvpn_app_path_arg)
285 {
286 }
287
289 std::wstring openvpn_app_path;
291 };
292
293 class UseDNS
294 {
295 public:
296 UseDNS() = default;
297
299 {
300 if (pull.dns_options.servers.empty())
301 return;
302 for (const auto &ip : pull.dns_options.servers.begin()->second.addresses)
303 add(ip.address, pull);
304 }
305
306 static bool enabled(const std::string &address,
307 const TunBuilderCapture &pull)
308 {
309 return IP::Addr(address).is_ipv6() && pull.block_ipv6 ? false : true;
310 }
311
312 int add(const std::string &address,
313 const TunBuilderCapture &pull)
314 {
315 if (enabled(address, pull))
316 return indices[IP::Addr(address).is_ipv6() ? 1 : 0]++;
317 else
318 return -1;
319 }
320
321 int ipv4() const
322 {
323 return indices[0];
324 }
325 int ipv6() const
326 {
327 return indices[1];
328 }
329
330 private:
331 int indices[2] = {0, 0};
332 };
333
345 const std::string &itf_index_name,
346 const std::vector<std::string> &addresses,
347 const TunBuilderCapture &pull)
348 {
349 // Usage: set dnsservers [name=]<string> [source=]dhcp|static
350 // [[address=]<IP address>|none]
351 // [[register=]none|primary|both]
352 // [[validate=]yes|no]
353 // Usage: add dnsservers [name=]<string> [address=]<IPv4 address>
354 // [[index=]<integer>] [[validate=]yes|no]
355 // Usage: delete dnsservers [name=]<string> [[address=]<IP address>|all] [[validate=]yes|no]
356 //
357 // Usage: set dnsservers [name=]<string> [source=]dhcp|static
358 // [[address=]<IPv6 address>|none]
359 // [[register=]none|primary|both]
360 // [[validate=]yes|no]
361 // Usage: add dnsservers [name=]<string> [address=]<IPv6 address>
362 // [[index=]<integer>] [[validate=]yes|no]
363 // Usage: delete dnsservers [name=]<string> [[address=]<IPv6 address>|all] [[validate=]yes|no]
364
365 // fix for vista and dnsserver vs win7+ dnsservers
366 std::string dns_servers_cmd = "dnsservers";
367 std::string validate_cmd = " validate=no";
368 if (IsWindowsVistaOrGreater() && !IsWindows7OrGreater())
369 {
370 dns_servers_cmd = "dnsserver";
371 validate_cmd = "";
372 }
373
374 UseDNS dc;
375 for (const auto &address : addresses)
376 {
377 // 0-based index for specific IPv4/IPv6 protocol, or -1 if disabled
378 const int count = dc.add(address, pull);
379 if (count >= 0)
380 {
381 const std::string proto = IP::Addr(address).is_ipv6() ? "ipv6" : "ip";
382 if (count)
383 create.add(new WinCmd("netsh interface " + proto + " add " + dns_servers_cmd + " " + itf_index_name + ' ' + address + " " + to_string(count + 1) + validate_cmd));
384 else
385 {
386 create.add(new WinCmd("netsh interface " + proto + " set " + dns_servers_cmd + " " + itf_index_name + " static " + address + " register=primary" + validate_cmd));
387 destroy.add(new WinCmd("netsh interface " + proto + " delete " + dns_servers_cmd + " " + itf_index_name + " all" + validate_cmd));
388 }
389 }
390 }
391 }
392
393 void register_rings(HANDLE handle, RingBuffer::Ptr ring_buffer)
394 {
395 TUN_REGISTER_RINGS rings;
396
397 ZeroMemory(&rings, sizeof(rings));
398
399 rings.receive.ring = ring_buffer->receive_ring();
400 rings.receive.tail_moved = ring_buffer->receive_ring_tail_moved();
401 rings.receive.ring_size = sizeof(rings.receive.ring->data);
402
403 rings.send.ring = ring_buffer->send_ring();
404 rings.send.tail_moved = ring_buffer->send_ring_tail_moved();
405 rings.send.ring_size = sizeof(rings.send.ring->data);
406
407 {
408 Win::Impersonate imp(true);
409
410 DWORD len;
411 if (!DeviceIoControl(handle, TUN_IOCTL_REGISTER_RINGS, &rings, sizeof(rings), NULL, 0, &len, NULL))
412 {
413 const Win::LastError err;
414 throw ErrorCode(Error::TUN_REGISTER_RINGS_ERROR, true, "Error registering ring buffers: " + err.message());
415 }
416 }
417 }
418
419 // Configure TAP adapter on Vista and higher
420 void adapter_config(HANDLE th,
421 const std::wstring &openvpn_app_path,
422 const Util::TapNameGuidPair &tap,
423 const TunBuilderCapture &pull,
424 const bool l2_post,
425 ActionList &create,
427 std::ostream &os)
428 {
429 // Windows interface index
430 const std::string tap_index_name = tap.index_or_name();
431
432 // special IPv6 next-hop recognized by TAP driver (magic)
433 const std::string ipv6_next_hop = "fe80::8";
434
435 // set local4 and local6 to point to IPv4/6 route configurations
436 const TunBuilderCapture::RouteAddress *local4 = pull.vpn_ipv4();
437 const TunBuilderCapture::RouteAddress *local6 = pull.vpn_ipv6();
438
439 if (!l2_post)
440 {
441 // set TAP media status to CONNECTED
442 if (tun_type_ == TapWindows6)
444
445 // try to delete any stale routes on interface left over from previous session
447 }
448
449 // Set IPv4 Interface
450 //
451 // Usage: set address [name=]<string>
452 // [[source=]dhcp|static]
453 // [[address=]<IPv4 address>[/<integer>] [[mask=]<IPv4 mask>]
454 // [[gateway=]<IPv4 address>|none [gwmetric=]<integer>]
455 // [[type=]unicast|anycast]
456 // [[subinterface=]<string>]
457 // [[store=]active|persistent]
458 // Usage: delete address [name=]<string> [[address=]<IPv4 address>]
459 // [[gateway=]<IPv4 address>|all]
460 // [[store=]active|persistent]
461 if (local4)
462 {
463 // Process ifconfig and topology
464 if (!l2_post)
465 {
466 // set high metric on interface so that rogue route which Windows creates (0.0.0.0/0)
467 // won't affect anything
468 create.add(new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=9000"));
469
470 const std::string metric = route_metric_opt(pull, *local4, MT_IFACE);
471 const std::string netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length).to_string();
472 const IP::Addr localaddr = IP::Addr::from_string(local4->address);
473 const IP::Addr remoteaddr = IP::Addr::from_string(local4->gateway);
474 if (tun_type_ == TapWindows6)
475 {
476 if (local4->net30)
477 Util::tap_configure_topology_net30(th, localaddr, remoteaddr);
478 else
480 }
481 create.add(new WinCmd("netsh interface ip set address " + tap_index_name + " static " + local4->address + ' ' + netmask + " gateway=" + local4->gateway + metric + " store=active"));
482 destroy.add(new WinCmd("netsh interface ip delete address " + tap_index_name + ' ' + local4->address + " gateway=all store=active"));
483
484 // specifying 'gateway' when setting ip address makes Windows add unnecessary route 0.0.0.0/0,
485 // which might cause routing conflicts, so we have to delete it after a small delay.
486 // If route is deleted before profile is created, then profile won't be created at all (OVPN-135)
487 WinCmd::Ptr cmd_delroute = new WinCmd("netsh interface ip delete route 0.0.0.0/0 " + tap_index_name + ' ' + local4->gateway + " store=active");
488
489 // set lowest interface metric to make Windows use pushed DNS search domain
490 WinCmd::Ptr cmd_setmetric = new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=1");
491
492 delete_route_timer.expires_after(Time::Duration::seconds(5));
493 delete_route_timer.async_wait([self = Ptr(this),
494 cmd_delroute = std::move(cmd_delroute),
495 cmd_setmetric = std::move(cmd_setmetric)](const openvpn_io::error_code &error)
496 {
497 if (!error)
498 {
499 std::ostringstream os;
500 cmd_delroute->execute(os);
501 cmd_setmetric->execute(os);
502 } });
503 }
504 }
505
506 // Should we block IPv6?
507 if (pull.block_ipv6)
508 {
509 static const char *const block_ipv6_net[] = {
510 "2000::/4",
511 "3000::/4",
512 "fc00::/7",
513 };
514 for (size_t i = 0; i < array_size(block_ipv6_net); ++i)
515 {
516 create.add(new WinCmd("netsh interface ipv6 add route " + std::string(block_ipv6_net[i]) + " interface=1 store=active"));
517 destroy.add(new WinCmd("netsh interface ipv6 delete route " + std::string(block_ipv6_net[i]) + " interface=1 store=active"));
518 }
519 }
520
521 // Set IPv6 Interface
522 //
523 // Usage: set address [interface=]<string> [address=]<IPv6 address>
524 // [[type=]unicast|anycast]
525 // [[validlifetime=]<integer>|infinite]
526 // [[preferredlifetime=]<integer>|infinite]
527 // [[store=]active|persistent]
528 // Usage: delete address [interface=]<string> [address=]<IPv6 address>
529 // [[store=]active|persistent]
530 if (local6 && !pull.block_ipv6 && !l2_post)
531 {
532 create.add(new WinCmd("netsh interface ipv6 set address " + tap_index_name + ' ' + local6->address + " store=active"));
533 destroy.add(new WinCmd("netsh interface ipv6 delete address " + tap_index_name + ' ' + local6->address + " store=active"));
534
535 create.add(new WinCmd("netsh interface ipv6 add route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
536 destroy.add(new WinCmd("netsh interface ipv6 delete route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
537 }
538
539 // Process Routes
540 //
541 // Usage: add route [prefix=]<IPv4 address>/<integer> [interface=]<string>
542 // [[nexthop=]<IPv4 address>] [[siteprefixlength=]<integer>]
543 // [[metric=]<integer>] [[publish=]no|age|yes]
544 // [[validlifetime=]<integer>|infinite]
545 // [[preferredlifetime=]<integer>|infinite]
546 // [[store=]active|persistent]
547 // Usage: delete route [prefix=]<IPv4 address>/<integer> [interface=]<string>
548 // [[nexthop=]<IPv4 address>]
549 // [[store=]active|persistent]
550 //
551 // Usage: add route [prefix=]<IPv6 address>/<integer> [interface=]<string>
552 // [[nexthop=]<IPv6 address>] [[siteprefixlength=]<integer>]
553 // [[metric=]<integer>] [[publish=]no|age|yes]
554 // [[validlifetime=]<integer>|infinite]
555 // [[preferredlifetime=]<integer>|infinite]
556 // [[store=]active|persistent]
557 // Usage: delete route [prefix=]<IPv6 address>/<integer> [interface=]<string>
558 // [[nexthop=]<IPv6 address>]
559 // [[store=]active|persistent]
560 {
561 for (auto &route : pull.add_routes)
562 {
563 if (route.ipv6)
564 {
565 if (!pull.block_ipv6)
566 {
567 const std::string metric = route_metric_opt(pull, route, MT_NETSH);
568 create.add(new WinCmd("netsh interface ipv6 add route " + route.address + '/' + to_string(route.prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + metric + " store=active"));
569 destroy.add(new WinCmd("netsh interface ipv6 delete route " + route.address + '/' + to_string(route.prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
570 }
571 }
572 else
573 {
574 if (local4)
575 {
576 int metric = pull.route_metric_default;
577 if (route.metric >= 0)
578 metric = route.metric;
579 create.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap.index, tap.name, local4->gateway, metric, true));
580 destroy.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap.index, tap.name, local4->gateway, metric, false));
581 }
582 else
583 throw tun_win_setup("IPv4 routes pushed without IPv4 ifconfig");
584 }
585 }
586 }
587
588 // Process exclude routes
589 if (!pull.exclude_routes.empty())
590 {
591 const Util::BestGateway gw{AF_INET};
592 if (gw.defined())
593 {
594 bool ipv6_error = false;
595 for (auto &route : pull.exclude_routes)
596 {
597 int metric = pull.route_metric_default;
598 if (route.metric >= 0)
599 metric = route.metric;
600
601 if (route.ipv6)
602 {
603 ipv6_error = true;
604 }
605 else
606 {
607 create.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, gw.interface_index(), "", gw.gateway_address(), metric, true));
608 destroy.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, gw.interface_index(), "", gw.gateway_address(), metric, false));
609 }
610 }
611 if (ipv6_error)
612 os << "NOTE: exclude IPv6 routes not currently supported" << std::endl;
613 }
614 else
615 os << "NOTE: exclude routes error: cannot detect default gateway" << std::endl;
616 }
617
618 // Process IPv4 redirect-gateway
619 if (pull.reroute_gw.ipv4)
620 {
621 // get default gateway
622 ADDRESS_FAMILY af = pull.remote_address.ipv6 ? AF_INET6 : AF_INET;
623 const Util::BestGateway gw{af, pull.remote_address.address, tap.index};
624
625 if (!gw.local_route())
626 {
627 // add server bypass route
628 if (gw.defined())
629 {
631 add_bypass_route(gw, pull.remote_address.address, false, create, destroy);
632 }
633 else
634 throw tun_win_setup("redirect-gateway error: cannot find gateway for bypass route");
635 }
636
637 create.add(new WinCmd("netsh interface ip add route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
638 create.add(new WinCmd("netsh interface ip add route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
639 destroy.add(new WinCmd("netsh interface ip delete route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
640 destroy.add(new WinCmd("netsh interface ip delete route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
641 }
642
643 // Process IPv6 redirect-gateway
644 if (pull.reroute_gw.ipv6 && !pull.block_ipv6)
645 {
646 create.add(new WinCmd("netsh interface ipv6 add route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
647 create.add(new WinCmd("netsh interface ipv6 add route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
648 destroy.add(new WinCmd("netsh interface ipv6 delete route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
649 destroy.add(new WinCmd("netsh interface ipv6 delete route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
650 }
651
652 // Process redirect-gateway "block-local" flag:
653 // Block traffic on all interfaces but VPN and loopback
654 const bool use_wfp = IsWindows8OrGreater();
655 const bool block_local_traffic = (pull.reroute_gw.flags & RedirectGatewayFlags::RG_BLOCK_LOCAL) != 0;
656 if (use_wfp && block_local_traffic && !openvpn_app_path.empty())
657 {
659 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, block_type, wfp));
660 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, block_type, wfp));
661 }
662
663 // The process id for NRPT rules
664 DWORD pid = process_id_ ? process_id_ : ::GetCurrentProcessId();
665
666 // Process DNS related settings
667 {
669 {
670 // apply DNS settings from --dns options
671 std::vector<std::string> addresses;
672 std::vector<std::string> split_domains;
673 std::vector<std::wstring> wide_search_domains;
674 std::string search_domains;
675 bool dnssec = false;
676
677 for (const auto &[priority, server] : pull.dns_options.servers)
678 {
679 bool secure_transport = server.transport == DnsServer::Transport::HTTPS
680 || server.transport == DnsServer::Transport::TLS;
681 bool custom_port = std::any_of(server.addresses.begin(),
682 server.addresses.end(),
683 [&](const DnsAddress &a)
684 { return a.port != 0 && a.port != 53; });
685 if (secure_transport || custom_port)
686 {
687 continue; // unsupported, try next server
688 }
689
690 // DNS server address(es)
691 for (const auto &addr : server.addresses)
692 {
693 addresses.push_back(addr.address);
694 }
695
696 // DNS server split domain(s)
697 for (const auto &dom : server.domains)
698 {
699 split_domains.push_back("." + dom.domain);
700 }
701
702 std::string delimiter;
703 for (const auto &domain : pull.dns_options.search_domains)
704 {
705 wide_search_domains.emplace_back(wstring::from_utf8(domain.to_string()));
706 search_domains.append(delimiter + domain.to_string());
707 delimiter = ",";
708 }
709
710 dnssec = server.dnssec == DnsServer::Security::Yes;
711 break;
712 }
713
714 // disconnect if we didn't find a compatible DNS server profile
715 if (!pull.dns_options.servers.empty() && addresses.empty())
716 {
717 throw tun_win_setup("no applicable DNS server config found");
718 }
719
720 if (!allow_local_dns_resolvers || !split_domains.empty())
721 {
722 // To keep local resolvers working, only split rules must be created
723 create.add(new NRPT::ActionCreate(pid, split_domains, addresses, wide_search_domains, dnssec));
724 destroy.add(new NRPT::ActionDelete(pid));
725 }
727 {
728 // Set pushed DNS servers with the adapter. In case the local resolver
729 // doesn't work the VPN DNS resolvers will serve as a fallback
730 set_adapter_dns(create, destroy, tap_index_name, addresses, pull);
731 }
732
733 create.add(new DNS::ActionCreate(tap.name, search_domains));
735
736 // Apply changes to DNS settings
737 create.add(new DNS::ActionApply());
738 destroy.add(new DNS::ActionApply());
739
740 // Use WFP for DNS leak protection unless local traffic is blocked already.
741 // Block DNS on all interfaces except the TAP adapter.
742 if (use_wfp && pull.block_outside_dns && !block_local_traffic && !openvpn_app_path.empty())
743 {
745 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, block_type, wfp));
746 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, block_type, wfp));
747 }
748 }
749 else
750 {
751 // apply DNS settings from --dhcp-options
752 const bool use_nrpt = IsWindows8OrGreater();
753
754 // count IPv4/IPv6 DNS servers
755 const UseDNS dns(pull);
756 const DnsServer &server = pull.dns_options.servers.begin()->second;
757
758 // will DNS requests be split between VPN DNS server and local?
759 const bool split_dns = (!server.domains.empty()
760 && !(pull.reroute_gw.ipv4 && dns.ipv4())
761 && !(pull.reroute_gw.ipv6 && dns.ipv6()));
762
763 // add DNS servers via netsh
764 if (!(use_nrpt && split_dns) && !l2_post)
765 {
766 std::vector<std::string> addresses;
767 std::for_each(addresses.begin(), addresses.end(), [&addresses](const std::string &addr)
768 { addresses.push_back(addr); });
769 set_adapter_dns(create, destroy, tap_index_name, addresses, pull);
770 }
771
772 // If NRPT enabled and at least one IPv4 or IPv6 DNS
773 // server was added, add NRPT registry entries to
774 // route DNS through the tunnel.
775 // Also consider selective DNS routing using domain
776 // suffix list from pull.search_domains as set by
777 // "dhcp-option DOMAIN ..." directives.
778 if (use_nrpt && (dns.ipv4() || dns.ipv6()))
779 {
780 // domain suffix list
781 std::vector<std::string> split_domains;
782
783 // Only add DNS routing suffixes if not rerouting gateway.
784 // Otherwise, route all DNS requests with wildcard (".").
785 if (split_dns)
786 {
787 for (const auto &sd : server.domains)
788 {
789 std::string dom = sd.domain;
790 if (!dom.empty())
791 {
792 // each DNS suffix must begin with '.'
793 if (dom[0] != '.')
794 dom = "." + dom;
795 split_domains.push_back(std::move(dom));
796 }
797 }
798 }
799
800 // DNS server list
801 std::vector<std::string> dserv;
802 for (const auto &ip : server.addresses)
803 dserv.push_back(IP::Addr(ip.address).to_string());
804
805 // To keep local resolvers working, only split rules must be created
806 if (!allow_local_dns_resolvers || !split_domains.empty())
807 {
808 std::vector<std::wstring> wide_search_domains;
809 for (const auto &domain : pull.dns_options.search_domains)
810 {
811 wide_search_domains.emplace_back(wstring::from_utf8(domain.to_string()));
812 }
813 create.add(new NRPT::ActionCreate(pid, split_domains, dserv, wide_search_domains, false));
814 destroy.add(new NRPT::ActionDelete(pid));
815
816 // Apply changes to DNS settings
817 create.add(new DNS::ActionApply());
818 destroy.add(new DNS::ActionApply());
819 }
820 }
821
822 // Set a default TAP-adapter domain suffix using
823 // "dhcp-option ADAPTER_DOMAIN_SUFFIX mycompany.com" directive.
824 if (!pull.dns_options.search_domains.empty())
825 {
826 // Only the first search domain is used
827 const std::string adapter_domain_suffix = pull.dns_options.search_domains[0].domain;
828 create.add(new Util::ActionSetAdapterDomainSuffix(adapter_domain_suffix, tap.guid));
830 }
831
832
833 // Use WFP for DNS leak protection unless local traffic is blocked already.
834 // Block DNS on all interfaces except the TAP adapter.
835 if (use_wfp && !split_dns && !block_local_traffic
836 && !openvpn_app_path.empty() && (dns.ipv4() || dns.ipv6()))
837 {
839 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, block_type, wfp));
840 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, block_type, wfp));
841 }
842
843 // flush DNS cache
844 create.add(new WinCmd("ipconfig /flushdns"));
845 destroy.add(new WinCmd("ipconfig /flushdns"));
846 }
847 }
848
849 // Process WINS Servers
850 //
851 // Usage: set winsservers [name=]<string> [source=]dhcp|static
852 // [[address=]<IP address>|none]
853 // Usage: add winsservers [name=]<string> [address=]<IP address> [[index=]<integer>]
854 // Usage: delete winsservers [name=]<string> [[address=]<IP address>|all]
855 {
856 for (size_t i = 0; i < pull.wins_servers.size(); ++i)
857 {
859 if (i)
860 create.add(new WinCmd("netsh interface ip add winsservers " + tap_index_name + ' ' + ws.address + ' ' + to_string(i + 1)));
861 else
862 {
863 create.add(new WinCmd("netsh interface ip set winsservers " + tap_index_name + " static " + ws.address));
864 destroy.add(new WinCmd("netsh interface ip delete winsservers " + tap_index_name + " all"));
865 }
866 }
867 }
868
869 OPENVPN_LOG("proxy_auto_config_url " << pull.proxy_auto_config_url.url);
871 ProxySettings::add_actions<WinProxySettings>(pull, create, destroy);
872 }
873
874 void adapter_config_l2(HANDLE th,
875 const std::wstring &openvpn_app_path,
876 const Util::TapNameGuidPair &tap,
877 const TunBuilderCapture &pull,
878 ActionList &create,
880 std::ostream &os)
881 {
882 // Make sure the TAP adapter is set for DHCP
883 {
884 const Util::IPAdaptersInfo ai;
885 if (!ai.is_dhcp_enabled(tap.index))
886 {
887 os << "TAP: DHCP is disabled, attempting to enable" << std::endl;
888 ActionList::Ptr cmds(new ActionList());
889 cmds->add(new Util::ActionEnableDHCP(tap));
890 cmds->execute(os);
891 }
892 }
893
894 // set TAP media status to CONNECTED
896
897 // ARP
899
900 // We must do DHCP release/renew in a background thread
901 // so the foreground can forward the DHCP negotiation packets
902 // over the tunnel.
903 l2_thread.reset(new std::thread([tap, logwrap = Log::Context::Wrapper()]()
904 {
905 Log::Context logctx(logwrap);
906 ::Sleep(250);
908 {
909 std::ostringstream os;
910 Util::dhcp_release(ii, tap.index, os);
911 OPENVPN_LOG_STRING(os.str());
912 }
913 ::Sleep(250);
914 {
915 std::ostringstream os;
916 Util::dhcp_renew(ii, tap.index, os);
917 OPENVPN_LOG_STRING(os.str());
918 } }));
919 }
920
927
928 static std::string route_metric_opt(const TunBuilderCapture &pull,
929 const TunBuilderCapture::RouteBase &route,
930 const MetricType mt)
931 {
932 int metric = pull.route_metric_default;
933 if (route.metric >= 0)
934 metric = route.metric;
935 if (metric >= 0)
936 {
937 switch (mt)
938 {
939 case MT_ROUTE:
940 return " METRIC " + std::to_string(metric); // route command form
941 case MT_NETSH:
942 return " metric=" + std::to_string(metric); // "netsh interface ip[v6] add route" form
943 case MT_IFACE:
944 return " gwmetric=" + std::to_string(metric); // "netsh interface ip set address" form
945 }
946 }
947 return "";
948 }
949
950#if _WIN32_WINNT >= 0x0600 // Vista+
952#endif
953
954 std::unique_ptr<std::thread> l2_thread;
955 std::unique_ptr<L2State> l2_state;
956
959
961
965 DWORD process_id_ = 0;
966};
967} // namespace openvpn::TunWin
void destroy(std::ostream &os) override
Definition action.hpp:151
void add(Action *action)
Definition action.hpp:57
virtual std::unordered_set< std::string > execute(std::ostream &os)
Executes a sequence of actions and returns marks of failed actions.
Definition action.hpp:98
void enable_destroy(const bool state)
Definition action.hpp:141
std::size_t expires_after(const Time::Duration &d)
Definition asiotimer.hpp:69
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:105
std::string to_string() const
Definition ip.hpp:528
bool is_ipv6() const
Definition ip.hpp:949
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
Definition ipv4.hpp:189
std::string to_string() const
Definition ipv4.hpp:232
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
static TimeType now()
Definition time.hpp:305
bool defined() const
Checks if the URL is defined.
Definition capture.hpp:421
Route address class that may use non-canonical form.
Definition capture.hpp:295
Base class for route-related functionality representing a network route.
Definition capture.hpp:197
Windows Internet Name Service (WINS) server configuration.
Definition capture.hpp:565
RemoteAddress remote_address
Definition capture.hpp:1082
std::vector< Route > add_routes
Definition capture.hpp:1091
ProxyAutoConfigURL proxy_auto_config_url
Definition capture.hpp:1096
const RouteAddress * vpn_ipv6() const
Gets the IPv6 tunnel address.
Definition capture.hpp:914
const RouteAddress * vpn_ipv4() const
Gets the IPv4 tunnel address.
Definition capture.hpp:902
std::vector< Route > exclude_routes
Definition capture.hpp:1092
std::vector< WINSServer > wins_servers
Definition capture.hpp:1100
UseDNS(const TunBuilderCapture &pull)
Definition tunsetup.hpp:298
int add(const std::string &address, const TunBuilderCapture &pull)
Definition tunsetup.hpp:312
static bool enabled(const std::string &address, const TunBuilderCapture &pull)
Definition tunsetup.hpp:306
RCPtr< Setup > Ptr
Definition tunsetup.hpp:60
void set_process_id(DWORD process_id)
Set the process id to be used with the NPRT rules.
Definition tunsetup.hpp:89
Util::TapNameGuidPair tap_
Definition tunsetup.hpp:963
DWORD vpn_interface_index() const override
Definition tunsetup.hpp:253
static void add_bypass_route(const Util::BestGateway &gw, const std::string &route, bool ipv6, ActionList &add_cmds, ActionList &remove_cmds_bypass_gw)
Definition tunsetup.hpp:258
void l2_finish(const TunBuilderCapture &pull, Stop *stop, std::ostream &os) override
Definition tunsetup.hpp:203
void destroy(std::ostream &os) override
Definition tunsetup.hpp:217
void register_rings(HANDLE handle, RingBuffer::Ptr ring_buffer)
Definition tunsetup.hpp:393
std::unique_ptr< L2State > l2_state
Definition tunsetup.hpp:955
void set_adapter_dns(ActionList &create, ActionList &destroy, const std::string &itf_index_name, const std::vector< std::string > &addresses, const TunBuilderCapture &pull)
Set the DNS server addresses with the VPN adapter.
Definition tunsetup.hpp:343
void adapter_config(HANDLE th, const std::wstring &openvpn_app_path, const Util::TapNameGuidPair &tap, const TunBuilderCapture &pull, const bool l2_post, ActionList &create, ActionList &destroy, std::ostream &os)
Definition tunsetup.hpp:420
ActionList::Ptr remove_cmds
Definition tunsetup.hpp:958
void adapter_config_l2(HANDLE th, const std::wstring &openvpn_app_path, const Util::TapNameGuidPair &tap, const TunBuilderCapture &pull, ActionList &create, ActionList &destroy, std::ostream &os)
Definition tunsetup.hpp:874
static std::string route_metric_opt(const TunBuilderCapture &pull, const TunBuilderCapture::RouteBase &route, const MetricType mt)
Definition tunsetup.hpp:928
Setup(openvpn_io::io_context &io_context_arg, const Type tun_type, bool allow_local_dns_resolvers_arg)
Definition tunsetup.hpp:62
bool l2_ready(const TunBuilderCapture &pull) override
Definition tunsetup.hpp:180
std::unique_ptr< std::thread > l2_thread
Definition tunsetup.hpp:954
AsioTimer delete_route_timer
Definition tunsetup.hpp:960
Util::TapNameGuidPair get_adapter_state() override
Definition tunsetup.hpp:69
HANDLE establish(const TunBuilderCapture &pull, const std::wstring &openvpn_app_path, Stop *stop, std::ostream &os, RingBuffer::Ptr ring_buffer) override
Definition tunsetup.hpp:126
HANDLE get_handle(std::ostream &os) override
Definition tunsetup.hpp:94
void set_adapter_state(const Util::TapNameGuidPair &tap) override
Definition tunsetup.hpp:74
const std::string & gateway_address() const
Definition tunutil.hpp:1160
Wrapper class for a WFP session.
Definition wfp.hpp:165
Block
Enum for type of local traffic to block.
Definition wfp.hpp:152
virtual void execute(std::ostream &os) override
Definition cmd.hpp:38
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
@ TUN_REGISTER_RINGS_ERROR
Definition error.hpp:44
void flush_arp(const DWORD adapter_index, std::ostream &os)
Definition tunutil.hpp:736
void dhcp_release(const InterfaceInfoList &ii, const DWORD adapter_index, std::ostream &os)
Definition tunutil.hpp:706
HANDLE tap_open(const Type tun_type, const TapNameGuidPairList &guids, std::string &path_opened, TapNameGuidPair &used)
Definition tunutil.hpp:528
void tap_configure_topology_subnet(HANDLE th, const IP::Addr &local, const unsigned int prefix_len)
Definition tunutil.hpp:589
void dhcp_renew(const InterfaceInfoList &ii, const DWORD adapter_index, std::ostream &os)
Definition tunutil.hpp:721
void tap_set_media_status(HANDLE th, bool media_status)
Definition tunutil.hpp:638
void tap_configure_topology_net30(HANDLE th, const IP::Addr &local_addr, const IP::Addr &remote_addr)
Definition tunutil.hpp:614
DNS utilities for Windows.
constexpr std::size_t array_size(T(&)[N])
Definition arraysize.hpp:19
constexpr std::uint32_t INVALID_ADAPTER_INDEX
Definition tunbase.hpp:29
#define TUN_IOCTL_REGISTER_RINGS
A name server address and optional port.
std::map< int, DnsServer > servers
std::vector< DnsDomain > search_domains
DNS settings for a name server.
std::vector< DnsAddress > addresses
std::vector< DnsDomain > domains
Argument to construct a Context in a different thread.
Scoped RAII for the global_log pointer.
Util::TapNameGuidPair tap
Definition tunsetup.hpp:288
L2State(const Util::TapNameGuidPair &tap_arg, const std::wstring &openvpn_app_path_arg)
Definition tunsetup.hpp:281
struct openvpn::TunWin::TUN_REGISTER_RINGS::@116 receive
struct openvpn::TunWin::TUN_REGISTER_RINGS::@116 send
UCHAR data[WINTUN_RING_CAPACITY+WINTUN_RING_TRAILING_BYTES+WINTUN_RING_FRAMING_SIZE]
bool is_up(const DWORD index, const IPNetmask4 &vpn_addr) const
Definition tunutil.hpp:822
bool is_dhcp_enabled(const DWORD index) const
Definition tunutil.hpp:836
const auto metric
remote_address ipv6
dns_options search_domains
remote_address address
std::ostringstream os