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 {
238 remove_cmds->destroy(os);
240 }
241
242 delete_route_timer.cancel();
243
244 vpn_interface_index_ = DWORD(-1);
245 }
246
247 virtual ~Setup()
248 {
249 std::ostringstream os;
250 destroy(os);
251 }
252
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 &addr : pull.dns_options.servers.begin()->second.addresses)
303 add(addr, pull);
304 }
305
306 static bool enabled(const DnsAddress &addr,
307 const TunBuilderCapture &pull)
308 {
309 return IP::Addr(addr.address).is_ipv6() && pull.block_ipv6 ? false : true;
310 }
311
312 int add(const DnsAddress &addr,
313 const TunBuilderCapture &pull)
314 {
315 if (enabled(addr, pull))
316 return indices[IP::Addr(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
334 void register_rings(HANDLE handle, RingBuffer::Ptr ring_buffer)
335 {
336 TUN_REGISTER_RINGS rings;
337
338 ZeroMemory(&rings, sizeof(rings));
339
340 rings.receive.ring = ring_buffer->receive_ring();
341 rings.receive.tail_moved = ring_buffer->receive_ring_tail_moved();
342 rings.receive.ring_size = sizeof(rings.receive.ring->data);
343
344 rings.send.ring = ring_buffer->send_ring();
345 rings.send.tail_moved = ring_buffer->send_ring_tail_moved();
346 rings.send.ring_size = sizeof(rings.send.ring->data);
347
348 {
349 Win::Impersonate imp(true);
350
351 DWORD len;
352 if (!DeviceIoControl(handle, TUN_IOCTL_REGISTER_RINGS, &rings, sizeof(rings), NULL, 0, &len, NULL))
353 {
354 const Win::LastError err;
355 throw ErrorCode(Error::TUN_REGISTER_RINGS_ERROR, true, "Error registering ring buffers: " + err.message());
356 }
357 }
358 }
359
360 // Configure TAP adapter on Vista and higher
361 void adapter_config(HANDLE th,
362 const std::wstring &openvpn_app_path,
363 const Util::TapNameGuidPair &tap,
364 const TunBuilderCapture &pull,
365 const bool l2_post,
366 ActionList &create,
368 std::ostream &os)
369 {
370 // Windows interface index
371 const std::string tap_index_name = tap.index_or_name();
372
373 // special IPv6 next-hop recognized by TAP driver (magic)
374 const std::string ipv6_next_hop = "fe80::8";
375
376 // set local4 and local6 to point to IPv4/6 route configurations
377 const TunBuilderCapture::RouteAddress *local4 = pull.vpn_ipv4();
378 const TunBuilderCapture::RouteAddress *local6 = pull.vpn_ipv6();
379
380 if (!l2_post)
381 {
382 // set TAP media status to CONNECTED
383 if (tun_type_ == TapWindows6)
385
386 // try to delete any stale routes on interface left over from previous session
388 }
389
390 // Set IPv4 Interface
391 //
392 // Usage: set address [name=]<string>
393 // [[source=]dhcp|static]
394 // [[address=]<IPv4 address>[/<integer>] [[mask=]<IPv4 mask>]
395 // [[gateway=]<IPv4 address>|none [gwmetric=]<integer>]
396 // [[type=]unicast|anycast]
397 // [[subinterface=]<string>]
398 // [[store=]active|persistent]
399 // Usage: delete address [name=]<string> [[address=]<IPv4 address>]
400 // [[gateway=]<IPv4 address>|all]
401 // [[store=]active|persistent]
402 if (local4)
403 {
404 // Process ifconfig and topology
405 if (!l2_post)
406 {
407 // set high metric on interface so that rogue route which Windows creates (0.0.0.0/0)
408 // won't affect anything
409 create.add(new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=9000"));
410
411 const std::string metric = route_metric_opt(pull, *local4, MT_IFACE);
412 const std::string netmask = IPv4::Addr::netmask_from_prefix_len(local4->prefix_length).to_string();
413 const IP::Addr localaddr = IP::Addr::from_string(local4->address);
414 const IP::Addr remoteaddr = IP::Addr::from_string(local4->gateway);
415 if (tun_type_ == TapWindows6)
416 {
417 if (local4->net30)
418 Util::tap_configure_topology_net30(th, localaddr, remoteaddr);
419 else
421 }
422 create.add(new WinCmd("netsh interface ip set address " + tap_index_name + " static " + local4->address + ' ' + netmask + " gateway=" + local4->gateway + metric + " store=active"));
423 destroy.add(new WinCmd("netsh interface ip delete address " + tap_index_name + ' ' + local4->address + " gateway=all store=active"));
424
425 // specifying 'gateway' when setting ip address makes Windows add unnecessary route 0.0.0.0/0,
426 // which might cause routing conflicts, so we have to delete it after a small delay.
427 // If route is deleted before profile is created, then profile won't be created at all (OVPN-135)
428 WinCmd::Ptr cmd_delroute = new WinCmd("netsh interface ip delete route 0.0.0.0/0 " + tap_index_name + ' ' + local4->gateway + " store=active");
429
430 // set lowest interface metric to make Windows use pushed DNS search domain
431 WinCmd::Ptr cmd_setmetric = new WinCmd("netsh interface ip set interface " + tap_index_name + " metric=1");
432
433 delete_route_timer.expires_after(Time::Duration::seconds(5));
434 delete_route_timer.async_wait([self = Ptr(this),
435 cmd_delroute = std::move(cmd_delroute),
436 cmd_setmetric = std::move(cmd_setmetric)](const openvpn_io::error_code &error)
437 {
438 if (!error)
439 {
440 std::ostringstream os;
441 cmd_delroute->execute(os);
442 cmd_setmetric->execute(os);
443 } });
444 }
445 }
446
447 // Should we block IPv6?
448 if (pull.block_ipv6)
449 {
450 static const char *const block_ipv6_net[] = {
451 "2000::/4",
452 "3000::/4",
453 "fc00::/7",
454 };
455 for (size_t i = 0; i < array_size(block_ipv6_net); ++i)
456 {
457 create.add(new WinCmd("netsh interface ipv6 add route " + std::string(block_ipv6_net[i]) + " interface=1 store=active"));
458 destroy.add(new WinCmd("netsh interface ipv6 delete route " + std::string(block_ipv6_net[i]) + " interface=1 store=active"));
459 }
460 }
461
462 // Set IPv6 Interface
463 //
464 // Usage: set address [interface=]<string> [address=]<IPv6 address>
465 // [[type=]unicast|anycast]
466 // [[validlifetime=]<integer>|infinite]
467 // [[preferredlifetime=]<integer>|infinite]
468 // [[store=]active|persistent]
469 // Usage: delete address [interface=]<string> [address=]<IPv6 address>
470 // [[store=]active|persistent]
471 if (local6 && !pull.block_ipv6 && !l2_post)
472 {
473 create.add(new WinCmd("netsh interface ipv6 set address " + tap_index_name + ' ' + local6->address + " store=active"));
474 destroy.add(new WinCmd("netsh interface ipv6 delete address " + tap_index_name + ' ' + local6->address + " store=active"));
475
476 create.add(new WinCmd("netsh interface ipv6 add route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
477 destroy.add(new WinCmd("netsh interface ipv6 delete route " + local6->gateway + '/' + to_string(local6->prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
478 }
479
480 // Process Routes
481 //
482 // Usage: add route [prefix=]<IPv4 address>/<integer> [interface=]<string>
483 // [[nexthop=]<IPv4 address>] [[siteprefixlength=]<integer>]
484 // [[metric=]<integer>] [[publish=]no|age|yes]
485 // [[validlifetime=]<integer>|infinite]
486 // [[preferredlifetime=]<integer>|infinite]
487 // [[store=]active|persistent]
488 // Usage: delete route [prefix=]<IPv4 address>/<integer> [interface=]<string>
489 // [[nexthop=]<IPv4 address>]
490 // [[store=]active|persistent]
491 //
492 // Usage: add route [prefix=]<IPv6 address>/<integer> [interface=]<string>
493 // [[nexthop=]<IPv6 address>] [[siteprefixlength=]<integer>]
494 // [[metric=]<integer>] [[publish=]no|age|yes]
495 // [[validlifetime=]<integer>|infinite]
496 // [[preferredlifetime=]<integer>|infinite]
497 // [[store=]active|persistent]
498 // Usage: delete route [prefix=]<IPv6 address>/<integer> [interface=]<string>
499 // [[nexthop=]<IPv6 address>]
500 // [[store=]active|persistent]
501 {
502 for (auto &route : pull.add_routes)
503 {
504 if (route.ipv6)
505 {
506 if (!pull.block_ipv6)
507 {
508 const std::string metric = route_metric_opt(pull, route, MT_NETSH);
509 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"));
510 destroy.add(new WinCmd("netsh interface ipv6 delete route " + route.address + '/' + to_string(route.prefix_length) + ' ' + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
511 }
512 }
513 else
514 {
515 if (local4)
516 {
517 int metric = pull.route_metric_default;
518 if (route.metric >= 0)
519 metric = route.metric;
520 create.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap.index, tap.name, local4->gateway, metric, true));
521 destroy.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, tap.index, tap.name, local4->gateway, metric, false));
522 }
523 else
524 throw tun_win_setup("IPv4 routes pushed without IPv4 ifconfig");
525 }
526 }
527 }
528
529 // Process exclude routes
530 if (!pull.exclude_routes.empty())
531 {
532 const Util::BestGateway gw{AF_INET};
533 if (gw.defined())
534 {
535 bool ipv6_error = false;
536 for (auto &route : pull.exclude_routes)
537 {
538 int metric = pull.route_metric_default;
539 if (route.metric >= 0)
540 metric = route.metric;
541
542 if (route.ipv6)
543 {
544 ipv6_error = true;
545 }
546 else
547 {
548 create.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, gw.interface_index(), "", gw.gateway_address(), metric, true));
549 destroy.add(new TUNWINDOWS::AddRoute4Cmd(route.address, route.prefix_length, gw.interface_index(), "", gw.gateway_address(), metric, false));
550 }
551 }
552 if (ipv6_error)
553 os << "NOTE: exclude IPv6 routes not currently supported" << std::endl;
554 }
555 else
556 os << "NOTE: exclude routes error: cannot detect default gateway" << std::endl;
557 }
558
559 // Process IPv4 redirect-gateway
560 if (pull.reroute_gw.ipv4)
561 {
562 // get default gateway
563 ADDRESS_FAMILY af = pull.remote_address.ipv6 ? AF_INET6 : AF_INET;
564 const Util::BestGateway gw{af, pull.remote_address.address, tap.index};
565
566 if (!gw.local_route())
567 {
568 // add server bypass route
569 if (gw.defined())
570 {
572 add_bypass_route(gw, pull.remote_address.address, false, create, destroy);
573 }
574 else
575 throw tun_win_setup("redirect-gateway error: cannot find gateway for bypass route");
576 }
577
578 create.add(new WinCmd("netsh interface ip add route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
579 create.add(new WinCmd("netsh interface ip add route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
580 destroy.add(new WinCmd("netsh interface ip delete route 0.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
581 destroy.add(new WinCmd("netsh interface ip delete route 128.0.0.0/1 " + tap_index_name + ' ' + local4->gateway + " store=active"));
582 }
583
584 // Process IPv6 redirect-gateway
585 if (pull.reroute_gw.ipv6 && !pull.block_ipv6)
586 {
587 create.add(new WinCmd("netsh interface ipv6 add route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
588 create.add(new WinCmd("netsh interface ipv6 add route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
589 destroy.add(new WinCmd("netsh interface ipv6 delete route 0::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
590 destroy.add(new WinCmd("netsh interface ipv6 delete route 8000::/1 " + tap_index_name + ' ' + ipv6_next_hop + " store=active"));
591 }
592
593 // Process redirect-gateway "block-local" flag:
594 // Block traffic on all interfaces but VPN and loopback
595 const bool use_wfp = IsWindows8OrGreater();
596 const bool block_local_traffic = (pull.reroute_gw.flags & RedirectGatewayFlags::RG_BLOCK_LOCAL) != 0;
597 if (use_wfp && block_local_traffic && !openvpn_app_path.empty())
598 {
600 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, block_type, wfp));
601 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, block_type, wfp));
602 }
603
604 // The process id for NRPT rules
605 DWORD pid = process_id_ ? process_id_ : ::GetCurrentProcessId();
606
607 // Process DNS related settings
608 {
610 {
611 // apply DNS settings from --dns options
612 std::vector<std::string> addresses;
613 std::vector<std::string> split_domains;
614 std::vector<std::wstring> wide_search_domains;
615 std::string search_domains;
616 bool dnssec = false;
617
618 for (const auto &[priority, server] : pull.dns_options.servers)
619 {
620 bool secure_transport = server.transport == DnsServer::Transport::HTTPS
621 || server.transport == DnsServer::Transport::TLS;
622 bool custom_port = std::any_of(server.addresses.begin(),
623 server.addresses.end(),
624 [&](const DnsAddress &a)
625 { return a.port != 0 && a.port != 53; });
626 if (secure_transport || custom_port)
627 {
628 continue; // unsupported, try next server
629 }
630
631 // DNS server address(es)
632 for (const auto &addr : server.addresses)
633 {
634 addresses.push_back(addr.address);
635 }
636
637 // DNS server split domain(s)
638 for (const auto &dom : server.domains)
639 {
640 split_domains.push_back("." + dom.domain);
641 }
642
643 std::string delimiter;
644 for (const auto &domain : pull.dns_options.search_domains)
645 {
646 wide_search_domains.emplace_back(wstring::from_utf8(domain.to_string()));
647 search_domains.append(delimiter + domain.to_string());
648 delimiter = ",";
649 }
650
651 dnssec = server.dnssec == DnsServer::Security::Yes;
652 break;
653 }
654
655 // disconnect if we didn't find a compatible DNS server profile
656 if (!pull.dns_options.servers.empty() && addresses.empty())
657 {
658 throw tun_win_setup("no applicable DNS server config found");
659 }
660
661 // To keep local resolvers working, only split rules must be created
662 if (!allow_local_dns_resolvers || !split_domains.empty())
663 {
664 create.add(new NRPT::ActionCreate(pid, split_domains, addresses, wide_search_domains, dnssec));
665 destroy.add(new NRPT::ActionDelete(pid));
666 }
667
668 create.add(new DNS::ActionCreate(tap.name, search_domains));
669 destroy.add(new DNS::ActionDelete(tap.name, search_domains));
670
671 // Apply changes to DNS settings
672 create.add(new DNS::ActionApply());
673 destroy.add(new DNS::ActionApply());
674
675 // Use WFP for DNS leak protection unless local traffic is blocked already.
676 // Block DNS on all interfaces except the TAP adapter.
677 if (use_wfp && pull.block_outside_dns && !block_local_traffic
678 && !allow_local_dns_resolvers && !openvpn_app_path.empty())
679 {
680 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, WFP::Block::Dns, wfp));
681 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, WFP::Block::Dns, wfp));
682 }
683 }
684 else
685 {
686 // apply DNS settings from --dhcp-options
687 const bool use_nrpt = IsWindows8OrGreater();
688
689 // count IPv4/IPv6 DNS servers
690 const UseDNS dns(pull);
691 const DnsServer &server = pull.dns_options.servers.begin()->second;
692
693 // will DNS requests be split between VPN DNS server and local?
694 const bool split_dns = (!server.domains.empty()
695 && !(pull.reroute_gw.ipv4 && dns.ipv4())
696 && !(pull.reroute_gw.ipv6 && dns.ipv6()));
697
698 // add DNS servers via netsh
699 if (!(use_nrpt && split_dns) && !l2_post)
700 {
701 // Usage: set dnsservers [name=]<string> [source=]dhcp|static
702 // [[address=]<IP address>|none]
703 // [[register=]none|primary|both]
704 // [[validate=]yes|no]
705 // Usage: add dnsservers [name=]<string> [address=]<IPv4 address>
706 // [[index=]<integer>] [[validate=]yes|no]
707 // Usage: delete dnsservers [name=]<string> [[address=]<IP address>|all] [[validate=]yes|no]
708 //
709 // Usage: set dnsservers [name=]<string> [source=]dhcp|static
710 // [[address=]<IPv6 address>|none]
711 // [[register=]none|primary|both]
712 // [[validate=]yes|no]
713 // Usage: add dnsservers [name=]<string> [address=]<IPv6 address>
714 // [[index=]<integer>] [[validate=]yes|no]
715 // Usage: delete dnsservers [name=]<string> [[address=]<IPv6 address>|all] [[validate=]yes|no]
716
717 // fix for vista and dnsserver vs win7+ dnsservers
718 std::string dns_servers_cmd = "dnsservers";
719 std::string validate_cmd = " validate=no";
720 if (IsWindowsVistaOrGreater() && !IsWindows7OrGreater())
721 {
722 dns_servers_cmd = "dnsserver";
723 validate_cmd = "";
724 }
725
726 UseDNS dc;
727 for (const auto &ip : server.addresses)
728 {
729 // 0-based index for specific IPv4/IPv6 protocol, or -1 if disabled
730 const int count = dc.add(ip, pull);
731 if (count >= 0)
732 {
733 const std::string proto = IP::Addr(ip.address).is_ipv6() ? "ipv6" : "ip";
734 if (count)
735 create.add(new WinCmd("netsh interface " + proto + " add " + dns_servers_cmd + " " + tap_index_name + ' ' + ip.address + " " + to_string(count + 1) + validate_cmd));
736 else
737 {
738 create.add(new WinCmd("netsh interface " + proto + " set " + dns_servers_cmd + " " + tap_index_name + " static " + ip.address + " register=primary" + validate_cmd));
739 destroy.add(new WinCmd("netsh interface " + proto + " delete " + dns_servers_cmd + " " + tap_index_name + " all" + validate_cmd));
740 }
741 }
742 }
743 }
744
745 // If NRPT enabled and at least one IPv4 or IPv6 DNS
746 // server was added, add NRPT registry entries to
747 // route DNS through the tunnel.
748 // Also consider selective DNS routing using domain
749 // suffix list from pull.search_domains as set by
750 // "dhcp-option DOMAIN ..." directives.
751 if (use_nrpt && (dns.ipv4() || dns.ipv6()))
752 {
753 // domain suffix list
754 std::vector<std::string> split_domains;
755
756 // Only add DNS routing suffixes if not rerouting gateway.
757 // Otherwise, route all DNS requests with wildcard (".").
758 if (split_dns)
759 {
760 for (const auto &sd : server.domains)
761 {
762 std::string dom = sd.domain;
763 if (!dom.empty())
764 {
765 // each DNS suffix must begin with '.'
766 if (dom[0] != '.')
767 dom = "." + dom;
768 split_domains.push_back(std::move(dom));
769 }
770 }
771 }
772
773 // DNS server list
774 std::vector<std::string> dserv;
775 for (const auto &ip : server.addresses)
776 dserv.push_back(IP::Addr(ip.address).to_string());
777
778 // To keep local resolvers working, only split rules must be created
779 if (!allow_local_dns_resolvers || !split_domains.empty())
780 {
781 std::vector<std::wstring> wide_search_domains;
782 for (const auto &domain : pull.dns_options.search_domains)
783 {
784 wide_search_domains.emplace_back(wstring::from_utf8(domain.to_string()));
785 }
786 create.add(new NRPT::ActionCreate(pid, split_domains, dserv, wide_search_domains, false));
787 destroy.add(new NRPT::ActionDelete(pid));
788
789 // Apply changes to DNS settings
790 create.add(new DNS::ActionApply());
791 destroy.add(new DNS::ActionApply());
792 }
793 }
794
795 // Set a default TAP-adapter domain suffix using
796 // "dhcp-option ADAPTER_DOMAIN_SUFFIX mycompany.com" directive.
797 if (!pull.dns_options.search_domains.empty())
798 {
799 // Only the first search domain is used
800 const std::string adapter_domain_suffix = pull.dns_options.search_domains[0].domain;
801 create.add(new Util::ActionSetAdapterDomainSuffix(adapter_domain_suffix, tap.guid));
803 }
804
805
806 // Use WFP for DNS leak protection unless local traffic is blocked already.
807 // Block DNS on all interfaces except the TAP adapter.
808 if (use_wfp && !split_dns && !block_local_traffic && !allow_local_dns_resolvers
809 && !openvpn_app_path.empty() && (dns.ipv4() || dns.ipv6()))
810 {
811 create.add(new WFP::ActionBlock(openvpn_app_path, tap.index, WFP::Block::Dns, wfp));
812 destroy.add(new WFP::ActionUnblock(openvpn_app_path, tap.index, WFP::Block::Dns, wfp));
813 }
814
815 // flush DNS cache
816 create.add(new WinCmd("ipconfig /flushdns"));
817 destroy.add(new WinCmd("ipconfig /flushdns"));
818 }
819 }
820
821 // Process WINS Servers
822 //
823 // Usage: set winsservers [name=]<string> [source=]dhcp|static
824 // [[address=]<IP address>|none]
825 // Usage: add winsservers [name=]<string> [address=]<IP address> [[index=]<integer>]
826 // Usage: delete winsservers [name=]<string> [[address=]<IP address>|all]
827 {
828 for (size_t i = 0; i < pull.wins_servers.size(); ++i)
829 {
831 if (i)
832 create.add(new WinCmd("netsh interface ip add winsservers " + tap_index_name + ' ' + ws.address + ' ' + to_string(i + 1)));
833 else
834 {
835 create.add(new WinCmd("netsh interface ip set winsservers " + tap_index_name + " static " + ws.address));
836 destroy.add(new WinCmd("netsh interface ip delete winsservers " + tap_index_name + " all"));
837 }
838 }
839 }
840
841 OPENVPN_LOG("proxy_auto_config_url " << pull.proxy_auto_config_url.url);
843 ProxySettings::add_actions<WinProxySettings>(pull, create, destroy);
844 }
845
846 void adapter_config_l2(HANDLE th,
847 const std::wstring &openvpn_app_path,
848 const Util::TapNameGuidPair &tap,
849 const TunBuilderCapture &pull,
850 ActionList &create,
852 std::ostream &os)
853 {
854 // Make sure the TAP adapter is set for DHCP
855 {
856 const Util::IPAdaptersInfo ai;
857 if (!ai.is_dhcp_enabled(tap.index))
858 {
859 os << "TAP: DHCP is disabled, attempting to enable" << std::endl;
860 ActionList::Ptr cmds(new ActionList());
861 cmds->add(new Util::ActionEnableDHCP(tap));
862 cmds->execute(os);
863 }
864 }
865
866 // set TAP media status to CONNECTED
868
869 // ARP
870 Util::flush_arp(tap.index, os);
871
872 // We must do DHCP release/renew in a background thread
873 // so the foreground can forward the DHCP negotiation packets
874 // over the tunnel.
875 l2_thread.reset(new std::thread([tap, logwrap = Log::Context::Wrapper()]()
876 {
877 Log::Context logctx(logwrap);
878 ::Sleep(250);
880 {
881 std::ostringstream os;
882 Util::dhcp_release(ii, tap.index, os);
883 OPENVPN_LOG_STRING(os.str());
884 }
885 ::Sleep(250);
886 {
887 std::ostringstream os;
888 Util::dhcp_renew(ii, tap.index, os);
889 OPENVPN_LOG_STRING(os.str());
890 } }));
891 }
892
899
900 static std::string route_metric_opt(const TunBuilderCapture &pull,
901 const TunBuilderCapture::RouteBase &route,
902 const MetricType mt)
903 {
904 int metric = pull.route_metric_default;
905 if (route.metric >= 0)
906 metric = route.metric;
907 if (metric >= 0)
908 {
909 switch (mt)
910 {
911 case MT_ROUTE:
912 return " METRIC " + std::to_string(metric); // route command form
913 case MT_NETSH:
914 return " metric=" + std::to_string(metric); // "netsh interface ip[v6] add route" form
915 case MT_IFACE:
916 return " gwmetric=" + std::to_string(metric); // "netsh interface ip set address" form
917 }
918 }
919 return "";
920 }
921
922#if _WIN32_WINNT >= 0x0600 // Vista+
924#endif
925
926 std::unique_ptr<std::thread> l2_thread;
927 std::unique_ptr<L2State> l2_state;
928
929 DWORD vpn_interface_index_ = DWORD(-1);
931
933
937 DWORD process_id_ = 0;
938};
939} // 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
RemoteAddress remote_address
Definition capture.hpp:665
std::vector< Route > add_routes
Definition capture.hpp:674
ProxyAutoConfigURL proxy_auto_config_url
Definition capture.hpp:679
const RouteAddress * vpn_ipv6() const
Definition capture.hpp:532
const RouteAddress * vpn_ipv4() const
Definition capture.hpp:525
std::vector< Route > exclude_routes
Definition capture.hpp:675
std::vector< WINSServer > wins_servers
Definition capture.hpp:683
UseDNS(const TunBuilderCapture &pull)
Definition tunsetup.hpp:298
static bool enabled(const DnsAddress &addr, const TunBuilderCapture &pull)
Definition tunsetup.hpp:306
int add(const DnsAddress &addr, const TunBuilderCapture &pull)
Definition tunsetup.hpp:312
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:935
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:334
std::unique_ptr< L2State > l2_state
Definition tunsetup.hpp:927
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:361
DWORD vpn_interface_index() const
Definition tunsetup.hpp:253
ActionList::Ptr remove_cmds
Definition tunsetup.hpp:930
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:846
static std::string route_metric_opt(const TunBuilderCapture &pull, const TunBuilderCapture::RouteBase &route, const MetricType mt)
Definition tunsetup.hpp:900
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:926
AsioTimer delete_route_timer
Definition tunsetup.hpp:932
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:164
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.
std::string to_string(T value)
Definition to_string.hpp:33
constexpr std::size_t array_size(T(&)[N])
Definition arraysize.hpp:19
#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::@118 receive
struct openvpn::TunWin::TUN_REGISTER_RINGS::@118 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
remote_address ipv6