OpenVPN 3 Core Library
Loading...
Searching...
No Matches
remotelist.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// These classes handle parsing and representation of OpenVPN "remote" directives,
13// and the list of IP addresses that they resolve to.
14// <connection> blocks are supported.
15
16#ifndef OPENVPN_CLIENT_REMOTELIST_H
17#define OPENVPN_CLIENT_REMOTELIST_H
18
19#include <ctime>
20#include <string>
21#include <sstream>
22#include <vector>
23#include <algorithm>
24#include <utility>
25#include <thread>
26
27#include <openvpn/io/io.hpp>
29
32#include <openvpn/common/rc.hpp>
37#include <openvpn/addr/ip.hpp>
43
44#if OPENVPN_DEBUG_REMOTELIST >= 1
45#define OPENVPN_LOG_REMOTELIST(x) OPENVPN_LOG(x)
46#else
47#define OPENVPN_LOG_REMOTELIST(x)
48#endif
49
50namespace openvpn {
51class RemoteList : public RC<thread_unsafe_refcount>
52{
53 // A single IP address that is part of a list of IP addresses
54 // associated with a "remote" item.
55 struct ResolvedAddr : public RC<thread_unsafe_refcount>
56 {
59
60 std::string to_string() const
61 {
62 return addr.to_string();
63 }
64 };
65
66 // The IP address list associated with a single "remote" item.
67 struct ResolvedAddrList : public std::vector<ResolvedAddr::Ptr>, public RC<thread_unsafe_refcount>
68 {
70
71 std::string to_string() const
72 {
73 std::string ret;
74 for (std::vector<ResolvedAddr::Ptr>::const_iterator i = begin(); i != end(); ++i)
75 {
76 if (!ret.empty())
77 ret += ' ';
78 ret += (*i)->to_string();
79 }
80 return ret;
81 }
82 };
83
84 public:
85 enum class Advance
86 {
87 None,
88 Addr,
89 Remote
90 };
91
92 struct Item;
93
94 struct ConnBlock : public RC<thread_unsafe_refcount>
95 {
97
98 virtual void new_item(const Item &item) = 0;
99 };
100
102 {
104
105 virtual ~ConnBlockFactory() = default;
106
108 };
109
110 // A single "remote" item
111 struct Item : public RC<thread_unsafe_refcount>
112 {
114
115 // "remote" item parameters from config file
116 std::string server_host;
117 std::string server_port;
119
120 // Non-empty if --remote-random-hostname is active.
121 std::string random_host;
122
123 // IP address list defined after actual_host() is resolved
125
126 // Other options if this is a <connection> block
128
129 // Time when the item's resolved addresses are considered outdated
130 std::time_t decay_time = std::numeric_limits<std::time_t>::max();
131
133 {
134 return res_addr_list && !res_addr_list->empty();
135 }
136
137 std::string actual_host() const
138 {
139 return random_host.empty() ? server_host : random_host;
140 }
141
142 // cache a single IP address
143 void set_ip_addr(const IP::Addr &addr)
144 {
147 ra->addr = addr;
148 res_addr_list->push_back(std::move(ra));
149 decay_time = std::numeric_limits<std::time_t>::max();
150 OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint SET " << to_string());
151 }
152
153 // cache a list of DNS-resolved IP addresses
154 template <class EPRANGE>
155 void set_endpoint_range(const EPRANGE &endpoint_range, RandomAPI *rng, std::size_t addr_lifetime)
156 {
157 // Keep addresses in case there are no results
158 if (endpoint_range.size())
159 {
161 for (const auto &i : endpoint_range)
162 {
163 std::string ep_af = "(unspec)";
164 if (i.endpoint().address().is_v6())
165 ep_af = "IPv6";
166 else if (i.endpoint().address().is_v4())
167 ep_af = "IPv4";
168 // Skip addresses with incompatible family
169 if ((transport_protocol.is_ipv6() && i.endpoint().address().is_v4())
170 || (transport_protocol.is_ipv4() && i.endpoint().address().is_v6()))
171 {
172 OPENVPN_LOG("Endpoint address family (" << ep_af << ") is incompatible with transport protocol (" << transport_protocol.protocol_to_string() << ")");
173 continue;
174 }
176 addr->addr = IP::Addr::from_asio(i.endpoint().address());
177 res_addr_list->push_back(addr);
178 }
179 if (rng && res_addr_list->size() >= 2)
180 std::shuffle(res_addr_list->begin(), res_addr_list->end(), *rng);
181 OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint SET " << to_string());
182 }
183 else if (!res_addr_list)
185
186 if (addr_lifetime)
187 decay_time = time(nullptr) + addr_lifetime;
188 }
189
190 // get an endpoint for contacting server
191 template <class EP>
192 bool get_endpoint(EP &endpoint, const size_t index) const
193 {
194 if (res_addr_list && index < res_addr_list->size())
195 {
196 endpoint.address((*res_addr_list)[index]->addr.to_asio());
197 endpoint.port(parse_number_throw<unsigned short>(server_port, "remote_port"));
198 OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint GET[" << index << "] " << endpoint << ' ' << to_string());
199 return true;
200 }
201 return false;
202 }
203
205 {
206 return !res_addr_list || decay_time <= time(nullptr);
207 }
208
209 std::string to_string() const
210 {
211 std::ostringstream out;
212 out << "host=" << actual_host();
213 if (res_addr_list)
214 out << '[' << res_addr_list->to_string() << ']';
215 out << " port=" << server_port
216 << " proto=" << transport_protocol.str();
217 return out.str();
218 }
219 };
220
222 {
223 virtual ~RemoteOverride() = default;
224
225 virtual Item::Ptr get() = 0;
226 };
227
228 private:
229 // Directive names that we search for in options
231 {
232 explicit Directives(const std::string &conn_tag = "")
233 : connection(!conn_tag.empty() ? conn_tag : "connection")
234 {
235 }
236
237 const std::string connection;
238 const std::string remote = "remote";
239 const std::string proto = "proto";
240 const std::string port = "port";
241 };
242
243 // Used to index into remote list items and their address(es).
244 struct Index
245 {
246 void reset()
247 {
248 item_ = item_addr_ = 0;
249 }
251 {
252 item_addr_ = 0;
253 }
254 void set_item(const size_t i)
255 {
256 item_ = i;
257 }
258
259 size_t item() const
260 {
261 return item_;
262 }
263 size_t item_addr() const
264 {
265 return item_addr_;
266 }
267
268 // return true if item index was incremented
269 bool increment(const Advance type, const size_t item_len, const size_t addr_len)
270 {
271 if (type == Advance::Remote || ++item_addr_ >= addr_len)
272 {
273 item_addr_ = 0;
274 if (++item_ >= item_len)
275 item_ = 0;
276 return true;
277 }
278 return false;
279 }
280
281 private:
282 size_t item_ = 0;
283 size_t item_addr_ = 0;
284 };
285
286 public:
287 // Used for errors occurring after initial options processing,
288 // and generally indicate logic errors
289 // (option_error used during initial options processing).
290 OPENVPN_EXCEPTION(remote_list_error);
291
293
294 // Helper class used to resolve all items in remote list.
295 // This is useful in tun_persist mode, where it may be necessary
296 // to pre-resolve all potential remote server items prior
297 // to initial tunnel establishment. Also used when trying to
298 // re-resolve items which had too many failed attempts.
299 class BulkResolve : public virtual RC<thread_unsafe_refcount>, protected AsyncResolvableTCP
300 {
301 public:
303
305 {
306 virtual ~NotifyCallback() = default;
307
308 // client callback when resolve operation is complete
309 virtual void bulk_resolve_done() = 0;
310 };
311
312 BulkResolve(openvpn_io::io_context &io_context_arg,
313 const RemoteList::Ptr &remote_list_arg,
314 const SessionStats::Ptr &stats_arg)
315 : AsyncResolvableTCP(io_context_arg),
316 notify_callback(nullptr),
317 remote_list(remote_list_arg),
318 stats(stats_arg),
319 index(0)
320 {
322 }
323
324 bool work_available() const
325 {
327 }
328
329 void start(NotifyCallback *notify_callback_arg)
330 {
331 if (notify_callback_arg)
332 {
333 // This method is a no-op (i.e. bulk_resolve_done is called immediately)
334 // if caching not enabled in underlying remote_list or if start() was
335 // previously called and is still in progress.
337 {
338 notify_callback = notify_callback_arg;
339 index = 0;
341 resolve_next();
342 }
343 else
344 notify_callback_arg->bulk_resolve_done();
345 }
346 }
347
348 void cancel()
349 {
350 notify_callback = nullptr;
351 index = 0;
353 }
354
355 protected:
357 {
358 while (index < remote_list->list.size())
359 {
360 // try to resolve item if needed
361 auto &item = remote_list->list[index];
362 if (item->need_resolve())
363 {
364 // next item to resolve
365 OPENVPN_LOG_REMOTELIST("*** BulkResolve RESOLVE on " << item->to_string());
366 async_resolve_name(item->actual_host(), item->server_port);
367 return;
368 }
369 ++index;
370 }
371
372 // Done resolving list. Prune out all entries we were unable to
373 // resolve unless doing so would result in an empty list.
374 // Then call client's callback method.
375 {
380 cancel();
381 ncb->bulk_resolve_done();
382 }
383 }
384
385 // callback on resolve completion
386 void resolve_callback(const openvpn_io::error_code &error,
387 results_type results) override
388 {
389 if (notify_callback && index < remote_list->list.size())
390 {
391 auto indexed_item(remote_list->index.item());
392 const auto item_in_use(remote_list->list[indexed_item]);
393 const auto resolve_item(remote_list->list[index++]);
394 if (!error)
395 {
396 // Set results to Items, where applicable
397 auto rand = remote_list->random ? remote_list->rng.get() : nullptr;
398 for (auto &item : remote_list->list)
399 {
400 // Skip already resolved and items with different hostname
401 if (!item->need_resolve()
402 || item->server_host != resolve_item->server_host)
403 continue;
404
405 // Reset item's address index as the list changes
406 if (item == item_in_use)
408
409 item->set_endpoint_range(results, rand, remote_list->cache_lifetime);
410 item->random_host = resolve_item->random_host;
411 }
412 }
413 else
414 {
415 // resolve failed
416 OPENVPN_LOG("DNS bulk-resolve error on " << resolve_item->actual_host()
417 << ": " << error.message());
418 if (stats)
420 }
421 resolve_next();
422 }
423 }
424
428 size_t index;
429 };
430
431 // create a remote list with a RemoteOverride callback
432 RemoteList(RemoteOverride *remote_override_arg)
433 : remote_override(remote_override_arg)
434 {
435 next();
436 }
437
438 // create a remote list with exactly one item
439 RemoteList(const std::string &server_host,
440 const std::string &server_port,
441 const Protocol &transport_protocol,
442 const std::string &title)
443 {
444 HostPort::validate_port(server_port, title);
445
446 Item::Ptr item(new Item());
447 item->server_host = server_host;
448 item->server_port = server_port;
449 item->transport_protocol = transport_protocol;
450 list.push_back(item);
451 }
452
453 // RemoteList flags
454 enum
455 {
459 ALLOW_EMPTY = 1 << 3,
460 };
461
462 // create a remote list from config file option list
464 const std::string &connection_tag,
465 const unsigned int flags,
466 ConnBlockFactory *conn_block_factory,
467 RandomAPI::Ptr rng_arg)
468 : random_hostname(opt.exists("remote-random-hostname")),
469 directives(connection_tag), rng(rng_arg)
470 {
472
473 // defaults
474 const Protocol default_proto = get_proto(opt, Protocol(Protocol::UDPv4));
475 const std::string default_port = get_port(opt, "1194");
476
477 // handle remote, port, and proto at the top-level
478 if (!(flags & CONN_BLOCK_ONLY))
479 add(opt, default_proto, default_port, ConnBlock::Ptr());
480
481 // cycle through <connection> blocks
482 {
483 const size_t max_conn_block_size = 4096;
485 if (conn)
486 {
487 for (OptionList::IndexList::const_iterator i = conn->begin(); i != conn->end(); ++i)
488 {
489 try
490 {
491 const Option &o = opt[*i];
492 o.touch();
493 const std::string &conn_block_text = o.get(1, Option::MULTILINE);
494 OptionList::Limits limits("<connection> block is too large",
495 max_conn_block_size,
500 OptionList::Ptr conn_block = OptionList::parse_from_config_static_ptr(conn_block_text, &limits);
501 const Protocol block_proto = get_proto(*conn_block, default_proto);
502 const std::string block_port = get_port(*conn_block, default_port);
503
504 // unsupported options
506 {
507 unsupported_in_connection_block(*conn_block, "http-proxy");
508 unsupported_in_connection_block(*conn_block, "http-proxy-option");
509 unsupported_in_connection_block(*conn_block, "http-proxy-user-pass");
510 }
511
512 // connection block options encapsulation via user-defined factory
513 {
515 if (conn_block_factory)
516 cb = conn_block_factory->new_conn_block(conn_block);
517 if (!(flags & CONN_BLOCK_OMIT_UNDEF) || cb)
518 add(*conn_block, block_proto, block_port, cb);
519 }
520 }
521 catch (Exception &e)
522 {
523 e.remove_label("option_error");
524 e.add_label("connection_block");
525 throw;
526 }
527 }
528 }
529 }
530
531 if (!(flags & ALLOW_EMPTY) && list.empty())
532 throw option_error(ERR_INVALID_CONFIG, "remote option not specified");
533 }
534
535 void process_push(const OptionList &opt)
536 {
538 }
539
540 // if cache is enabled, all DNS names will be preemptively queried
541 void set_enable_cache(const bool enable_cache_arg)
542 {
543 enable_cache = enable_cache_arg;
544 }
545
546 bool get_enable_cache() const
547 {
548 return enable_cache;
549 }
550
551 // override all server hosts to server_override
552 void set_server_override(const std::string &server_override)
553 {
554 if (server_override.empty())
555 return;
556 for (auto &item : list)
557 {
558 item->server_host = server_override;
559 item->random_host.clear();
560 item->res_addr_list.reset();
561 }
562 random_hostname = false;
563 reset_cache();
564 }
565
566 // override all server ports to port_override
567 void set_port_override(const std::string &port_override)
568 {
569 if (port_override.empty())
570 return;
571 for (auto &item : list)
572 {
573 item->server_port = port_override;
574 item->res_addr_list.reset();
575 }
576 reset_cache();
577 }
578
579 // override all Item's transport_protocol version to v
581 {
583 return;
584 for (auto item : list)
585 item->transport_protocol.mod_addr_version(v);
586 reset_cache();
587 }
588
589 void set_random(const RandomAPI::Ptr &rng_arg)
590 {
591 rng = rng_arg;
592 }
593
594 // randomize item list, used to implement remote-random directive
596 {
597 if (rng)
598 {
599 random = true;
600 std::shuffle(list.begin(), list.end(), *rng);
601 index.reset();
602 }
603 }
604
605 // Higher-level version of set_proto_override that also supports indication
606 // on whether or not TCP-based proxies are enabled. Should be called after set_enable_cache
607 // because it may modify enable_cache flag.
608 void handle_proto_override(const Protocol &proto_override, const bool tcp_proxy_enabled)
609 {
610 if (tcp_proxy_enabled)
611 {
612 const Protocol tcp(Protocol::TCP);
613 if (contains_protocol(tcp))
615 else
616 throw option_error(ERR_INVALID_CONFIG, "cannot connect via TCP-based proxy because no TCP server entries exist in profile");
617 }
618 else if (proto_override.defined() && contains_protocol(proto_override))
619 set_proto_override(proto_override);
620 }
621
622 // increment to next IP address or remote list entry
624 {
625 if (remote_override)
626 {
627 Item::Ptr item = remote_override->get();
628 if (item)
629 {
630 list.clear();
631 index.reset();
632 list.push_back(std::move(item));
633 return;
634 }
635 }
636
637 if (type != Advance::None)
638 {
639 bool item_changed = index.increment(type, list.size(), item_addr_length(index.item()));
640 if (item_changed && !enable_cache)
642 }
643 }
644
645 // Return details about current connection entry.
646 // Return value is true if get_endpoint may be called
647 // without raising an exception.
648 bool endpoint_available(std::string *server_host, std::string *server_port, Protocol *transport_protocol) const
649 {
650 const Item &item = *list[item_index()];
651 if (server_host)
652 *server_host = item.actual_host();
653 if (server_port)
654 *server_port = item.server_port;
655 const bool cached = (item.res_addr_list && index.item_addr() < item.res_addr_list->size());
656 if (transport_protocol)
657 {
658 *transport_protocol = item.transport_protocol;
659 }
660 return cached;
661 }
662
663 // cache a list of DNS-resolved IP addresses
664 template <class EPRANGE>
665 void set_endpoint_range(EPRANGE &endpoint_range)
666 {
667 Item &item = *list[item_index()];
668 auto rand = random ? rng.get() : nullptr;
669 std::size_t lifetime = enable_cache ? cache_lifetime : 0;
670 item.set_endpoint_range(endpoint_range, rand, lifetime);
672 }
673
674 // get an endpoint for contacting server
675 template <class EP>
676 void get_endpoint(EP &endpoint) const
677 {
678 const Item &item = *list[item_index()];
679 if (!item.get_endpoint(endpoint, index.item_addr()))
680 throw remote_list_error("current remote server endpoint is undefined");
681 }
682
683 // return true if object has at least one connection entry
684 bool defined() const
685 {
686 return !list.empty();
687 }
688
689 // return remote list size
690 size_t size() const
691 {
692 return list.size();
693 }
694
695 Item::Ptr get_item(const size_t index) const
696 {
697 return list.at(index);
698 }
699
700 // return hostname (or IP address) of current connection entry
701 std::string current_server_host() const
702 {
703 const Item &item = *list[item_index()];
704 return item.actual_host();
705 }
706
707 // return transport protocol of current connection entry
709 {
710 const Item &item = *list[item_index()];
711 return item.transport_protocol;
712 }
713
714 template <typename T>
716 {
717 const Item &item = *list[item_index()];
718 return dynamic_cast<T *>(item.conn_block.get());
719 }
720
721 std::string to_string() const
722 {
723 std::ostringstream out;
724 for (size_t i = 0; i < list.size(); ++i)
725 {
726 const Item &e = *list[i];
727 out << '[' << i << "] " << e.to_string() << '\n';
728 }
729 return out.str();
730 }
731
732 // return a list of unique, cached IP addresses
734 {
735 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
736 {
737 const Item &item = **i;
738 if (item.res_addr_list_defined())
739 {
740 const ResolvedAddrList &ral = *item.res_addr_list;
741 for (ResolvedAddrList::const_iterator j = ral.begin(); j != ral.end(); ++j)
742 {
743 const ResolvedAddr &addr = **j;
744 addrlist.add(addr.addr);
745 }
746 }
747 }
748 }
749
750 // reset the cache associated with all items
752 {
753 for (auto &e : list)
754 {
755 e->res_addr_list.reset(nullptr);
756 randomize_host(*e);
757 }
758 index.reset();
759 }
760
761 // if caching is disabled, reset the cache for current item
763 {
764 if (!enable_cache)
766 }
767
768 private:
769 // Process --remote-cache-lifetime option
771 {
772 if (!opt.exists("remote-cache-lifetime"))
773 return;
774
775 const bool lifetimes_set = cache_lifetime != 0;
776 cache_lifetime = opt.get("remote-cache-lifetime").get_num(1, 0);
777 if (!enable_cache || lifetimes_set)
778 return;
779
780 // Init lifetimes on items with adresses
781 for (auto &item : list)
782 {
783 if (item->res_addr_list_defined())
784 item->decay_time = time(nullptr) + cache_lifetime;
785 }
786 }
787
788 // reset the cache associated with a given item
789 void reset_item(const size_t i)
790 {
791 if (i < list.size())
792 {
793 list[i]->res_addr_list.reset(nullptr);
794 list[i]->decay_time = std::numeric_limits<std::time_t>::max();
795 randomize_host(*list[i]);
796 }
797 }
798
799 // return the current item index (into list) and raise an exception
800 // if it is undefined
801 size_t item_index() const
802 {
803 const size_t pri = index.item();
804 if (pri < list.size())
805 return pri;
806 throw remote_list_error("current remote server item is undefined");
807 }
808
809 // return the number of cached IP addresses associated with a given item
810 size_t item_addr_length(const size_t i) const
811 {
812 if (i < list.size())
813 {
814 const Item &item = *list[i];
815 if (item.res_addr_list)
816 return item.res_addr_list->size();
817 }
818 return 0;
819 }
820
821 // return true if at least one remote entry is of type proto
822 bool contains_protocol(const Protocol &proto)
823 {
824 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
825 {
826 if (proto.transport_match((*i)->transport_protocol))
827 return true;
828 }
829 return false;
830 }
831
832 // prune remote entries so that only those of Protocol proto_override remain
833 void set_proto_override(const Protocol &proto_override)
834 {
835 if (proto_override.defined())
836 {
837 size_t di = 0;
838 for (size_t si = 0; si < list.size(); ++si)
839 {
840 const Item &item = *list[si];
841 if (proto_override.transport_match(item.transport_protocol))
842 {
843 if (si != di)
844 list[di] = list[si];
845 ++di;
846 }
847 }
848 if (di != list.size())
849 list.resize(di);
850 reset_cache();
851 }
852 }
853
854 // Return true if at least one cached Item exists
856 {
857 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
858 {
859 const Item &item = **i;
860 if (item.res_addr_list_defined())
861 return true;
862 }
863 return false;
864 }
865
866 // Prune uncached Items so that only Items containing a res_addr_list with
867 // size > 0 remain.
869 {
870 size_t di = 0;
871 for (size_t si = 0; si < list.size(); ++si)
872 {
873 const Item &item = *list[si];
874 if (item.res_addr_list_defined())
875 {
876 if (si != di)
877 {
878 list[di] = list[si];
879 if (si == index.item())
880 index.set_item(di);
881 }
882 ++di;
883 }
884 }
885 if (di != list.size())
886 list.resize(di);
887 }
888
889 std::string get_port(const OptionList &opt, const std::string &default_port)
890 {
891 // parse "port" option if present
892 const Option *o = opt.get_ptr(directives.port);
893 if (!o)
894 return default_port;
895
896 std::string port = o->get(1, 16);
898 return port;
899 }
900
901 Protocol get_proto(const OptionList &opt, const Protocol &default_proto)
902 {
903 // parse "proto" option if present
904 const Option *o = opt.get_ptr(directives.proto);
905 if (o)
907
908 return default_proto;
909 }
910
911 void add(const OptionList &opt, const Protocol &default_proto, const std::string &default_port, ConnBlock::Ptr conn_block)
912 {
914 if (!rem)
915 return;
916
917 // cycle through remote entries
918 for (const auto &i : *rem)
919 {
920 Item::Ptr e(new Item());
921 const Option &o = opt[i];
922 o.touch();
923 e->server_host = o.get(1, 256);
924 int adj = 0;
925 if (o.size() >= 3)
926 {
927 e->server_port = o.get(2, 16);
928 if (Protocol::is_local_type(e->server_port))
929 {
930 adj = -1;
931 e->server_port = "";
932 }
933 else
934 HostPort::validate_port(e->server_port, directives.port);
935 }
936 else
937 e->server_port = default_port;
938 if (o.size() >= (size_t)(4 + adj))
939 e->transport_protocol = Protocol::parse(o.get(3 + adj, 16), Protocol::CLIENT_SUFFIX);
940 else
941 e->transport_protocol = default_proto;
942 e->conn_block = conn_block;
943 randomize_host(*e);
944 if (conn_block)
945 conn_block->new_item(*e);
946 list.push_back(e);
947 }
948 }
949
950 void unsupported_in_connection_block(const OptionList &options, const std::string &option)
951 {
952 if (options.exists(option))
953 OPENVPN_LOG("NOTE: " << option << " directive is not currently supported in <connection> blocks");
954 }
955
957 {
958 if (!random_hostname || !rng)
959 return;
960
961 try
962 {
963 // Throws if server_host is not an IP address
964 IP::Addr(item.server_host);
965 }
966 catch (const IP::ip_exception &)
967 {
968 // Produce 6 bytes of random prefix data
969 unsigned char prefix[6];
970 rng->rand_bytes(prefix, sizeof(prefix));
971
972 // Prepend it to the server_host
973 std::ostringstream random_host;
974 random_host << std::hex;
975 for (std::size_t i = 0; i < sizeof(prefix); ++i)
976 {
977 random_host << std::setw(2) << std::setfill('0')
978 << static_cast<unsigned>(prefix[i]);
979 }
980 random_host << "." << item.server_host;
981
982 item.random_host = random_host.str();
983 }
984 }
985
986 std::size_t cache_lifetime = 0;
987 bool random_hostname = false;
988 bool random = false;
989 bool enable_cache = false;
991
992 std::vector<Item::Ptr> list;
993
995
997
999};
1000
1001} // namespace openvpn
1002
1003#endif
typename RESOLVER_TYPE::results_type results_type
Definition asio.hpp:97
virtual void async_resolve_name(const std::string &host, const std::string &port)
Definition asio.hpp:125
void remove_label(const std::string &label)
Definition exception.hpp:62
void add_label(const std::string &label)
Definition exception.hpp:57
void add(const IP::Addr &a)
Definition addrlist.hpp:26
static Addr from_asio(const openvpn_io::ip::address &addr)
Definition ip.hpp:576
std::string to_string() const
Definition ip.hpp:528
const IndexList * get_index_ptr(const std::string &name) const
Definition options.hpp:1260
static OptionList::Ptr parse_from_config_static_ptr(const std::string &str, Limits *lim)
Definition options.hpp:855
std::vector< unsigned int > IndexList
Definition options.hpp:513
const Option & get(const std::string &name) const
Definition options.hpp:1240
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1174
bool exists(const std::string &name) const
Definition options.hpp:1308
void touch(bool lightly=false) const
Definition options.hpp:378
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:184
T get_num(const size_t idx) const
Definition options.hpp:216
size_t size() const
Definition options.hpp:320
const char * protocol_to_string() const
Definition protocol.hpp:247
const char * str() const
Definition protocol.hpp:212
bool defined() const
Definition protocol.hpp:65
static bool is_local_type(const std::string &str)
Definition protocol.hpp:174
bool is_ipv4() const
Definition protocol.hpp:91
static Protocol parse(const std::string &str, const AllowSuffix allow_suffix, const char *title=nullptr)
Definition protocol.hpp:157
bool transport_match(const Protocol &other) const
Definition protocol.hpp:122
bool is_ipv6() const
Definition protocol.hpp:95
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:908
Abstract base class for random number generators.
Definition randapi.hpp:39
virtual void rand_bytes(unsigned char *buf, size_t size)=0
Fill a buffer with random bytes.
void resolve_callback(const openvpn_io::error_code &error, results_type results) override
void start(NotifyCallback *notify_callback_arg)
BulkResolve(openvpn_io::io_context &io_context_arg, const RemoteList::Ptr &remote_list_arg, const SessionStats::Ptr &stats_arg)
void set_endpoint_range(EPRANGE &endpoint_range)
std::size_t cache_lifetime
bool endpoint_available(std::string *server_host, std::string *server_port, Protocol *transport_protocol) const
void get_endpoint(EP &endpoint) const
RemoteOverride * remote_override
void add(const OptionList &opt, const Protocol &default_proto, const std::string &default_port, ConnBlock::Ptr conn_block)
RemoteList(const OptionList &opt, const std::string &connection_tag, const unsigned int flags, ConnBlockFactory *conn_block_factory, RandomAPI::Ptr rng_arg)
void unsupported_in_connection_block(const OptionList &options, const std::string &option)
void randomize_host(Item &item)
void set_server_override(const std::string &server_override)
void next(Advance type=Advance::Addr)
size_t item_addr_length(const size_t i) const
void cached_ip_address_list(IP::AddrList &addrlist) const
void handle_proto_override(const Protocol &proto_override, const bool tcp_proxy_enabled)
bool defined() const
bool get_enable_cache() const
void set_proto_override(const Protocol &proto_override)
T * current_conn_block_rawptr() const
RemoteList(const std::string &server_host, const std::string &server_port, const Protocol &transport_protocol, const std::string &title)
std::string to_string() const
size_t item_index() const
std::vector< Item::Ptr > list
void set_enable_cache(const bool enable_cache_arg)
RemoteList(RemoteOverride *remote_override_arg)
void set_random(const RandomAPI::Ptr &rng_arg)
void reset_item(const size_t i)
void set_proto_version_override(const IP::Addr::Version v)
Item::Ptr get_item(const size_t index) const
void set_port_override(const std::string &port_override)
RandomAPI::Ptr rng
bool contains_protocol(const Protocol &proto)
std::string get_port(const OptionList &opt, const std::string &default_port)
const Protocol & current_transport_protocol() const
OPENVPN_EXCEPTION(remote_list_error)
void process_push(const OptionList &opt)
bool cached_item_exists() const
std::string current_server_host() const
size_t size() const
Protocol get_proto(const OptionList &opt, const Protocol &default_proto)
void process_cache_lifetime(const OptionList &opt)
virtual void error(const size_t type, const std::string *text=nullptr)
#define OPENVPN_LOG(args)
void validate_port(const std::string &port, const std::string &title, unsigned int *value=nullptr)
Definition hostport.hpp:34
Implementation of the base classes for random number generators.
#define OPENVPN_LOG_REMOTELIST(x)
virtual ConnBlock::Ptr new_conn_block(const OptionList::Ptr &opt)=0
virtual void new_item(const Item &item)=0
Directives(const std::string &conn_tag="")
bool increment(const Advance type, const size_t item_len, const size_t addr_len)
void set_item(const size_t i)
bool get_endpoint(EP &endpoint, const size_t index) const
ResolvedAddrList::Ptr res_addr_list
std::string actual_host() const
std::string to_string() const
void set_endpoint_range(const EPRANGE &endpoint_range, RandomAPI *rng, std::size_t addr_lifetime)
bool res_addr_list_defined() const
void set_ip_addr(const IP::Addr &addr)
reroute_gw flags
proxy_host_port port
std::string ret
static std::stringstream out
Definition test_path.cpp:10