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->size() > 0;
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 else
202 return false;
203 }
204
206 {
207 return !res_addr_list || decay_time <= time(nullptr);
208 }
209
210 std::string to_string() const
211 {
212 std::ostringstream out;
213 out << "host=" << actual_host();
214 if (res_addr_list)
215 out << '[' << res_addr_list->to_string() << ']';
216 out << " port=" << server_port
217 << " proto=" << transport_protocol.str();
218 return out.str();
219 }
220 };
221
223 {
224 virtual ~RemoteOverride() = default;
225
226 virtual Item::Ptr get() = 0;
227 };
228
229 private:
230 // Directive names that we search for in options
232 {
233 explicit Directives(const std::string &conn_tag = "")
234 : connection(conn_tag.length() ? conn_tag : "connection")
235 {
236 }
237
238 const std::string connection;
239 const std::string remote = "remote";
240 const std::string proto = "proto";
241 const std::string port = "port";
242 };
243
244 // Used to index into remote list items and their address(es).
245 struct Index
246 {
247 void reset()
248 {
249 item_ = item_addr_ = 0;
250 }
252 {
253 item_addr_ = 0;
254 }
255 void set_item(const size_t i)
256 {
257 item_ = i;
258 }
259
260 size_t item() const
261 {
262 return item_;
263 }
264 size_t item_addr() const
265 {
266 return item_addr_;
267 }
268
269 // return true if item index was incremented
270 bool increment(const Advance type, const size_t item_len, const size_t addr_len)
271 {
272 if (type == Advance::Remote || ++item_addr_ >= addr_len)
273 {
274 item_addr_ = 0;
275 if (++item_ >= item_len)
276 item_ = 0;
277 return true;
278 }
279 else
280 return false;
281 }
282
283 private:
284 size_t item_ = 0;
285 size_t item_addr_ = 0;
286 };
287
288 public:
289 // Used for errors occurring after initial options processing,
290 // and generally indicate logic errors
291 // (option_error used during initial options processing).
292 OPENVPN_EXCEPTION(remote_list_error);
293
295
296 // Helper class used to resolve all items in remote list.
297 // This is useful in tun_persist mode, where it may be necessary
298 // to pre-resolve all potential remote server items prior
299 // to initial tunnel establishment. Also used when trying to
300 // re-resolve items which had too many failed attempts.
301 class BulkResolve : public virtual RC<thread_unsafe_refcount>, protected AsyncResolvableTCP
302 {
303 public:
305
307 {
308 virtual ~NotifyCallback() = default;
309
310 // client callback when resolve operation is complete
311 virtual void bulk_resolve_done() = 0;
312 };
313
314 BulkResolve(openvpn_io::io_context &io_context_arg,
315 const RemoteList::Ptr &remote_list_arg,
316 const SessionStats::Ptr &stats_arg)
317 : AsyncResolvableTCP(io_context_arg),
318 notify_callback(nullptr),
319 remote_list(remote_list_arg),
320 stats(stats_arg),
321 index(0)
322 {
324 }
325
326 bool work_available() const
327 {
329 }
330
331 void start(NotifyCallback *notify_callback_arg)
332 {
333 if (notify_callback_arg)
334 {
335 // This method is a no-op (i.e. bulk_resolve_done is called immediately)
336 // if caching not enabled in underlying remote_list or if start() was
337 // previously called and is still in progress.
339 {
340 notify_callback = notify_callback_arg;
341 index = 0;
343 resolve_next();
344 }
345 else
346 notify_callback_arg->bulk_resolve_done();
347 }
348 }
349
350 void cancel()
351 {
352 notify_callback = nullptr;
353 index = 0;
355 }
356
357 protected:
359 {
360 while (index < remote_list->list.size())
361 {
362 // try to resolve item if needed
363 auto &item = remote_list->list[index];
364 if (item->need_resolve())
365 {
366 // next item to resolve
367 OPENVPN_LOG_REMOTELIST("*** BulkResolve RESOLVE on " << item->to_string());
368 async_resolve_name(item->actual_host(), item->server_port);
369 return;
370 }
371 ++index;
372 }
373
374 // Done resolving list. Prune out all entries we were unable to
375 // resolve unless doing so would result in an empty list.
376 // Then call client's callback method.
377 {
382 cancel();
383 ncb->bulk_resolve_done();
384 }
385 }
386
387 // callback on resolve completion
388 void resolve_callback(const openvpn_io::error_code &error,
389 results_type results) override
390 {
391 if (notify_callback && index < remote_list->list.size())
392 {
393 auto indexed_item(remote_list->index.item());
394 const auto item_in_use(remote_list->list[indexed_item]);
395 const auto resolve_item(remote_list->list[index++]);
396 if (!error)
397 {
398 // Set results to Items, where applicable
399 auto rand = remote_list->random ? remote_list->rng.get() : nullptr;
400 for (auto &item : remote_list->list)
401 {
402 // Skip already resolved and items with different hostname
403 if (!item->need_resolve()
404 || item->server_host != resolve_item->server_host)
405 continue;
406
407 // Reset item's address index as the list changes
408 if (item == item_in_use)
410
411 item->set_endpoint_range(results, rand, remote_list->cache_lifetime);
412 item->random_host = resolve_item->random_host;
413 }
414 }
415 else
416 {
417 // resolve failed
418 OPENVPN_LOG("DNS bulk-resolve error on " << resolve_item->actual_host()
419 << ": " << error.message());
420 if (stats)
422 }
423 resolve_next();
424 }
425 }
426
430 size_t index;
431 };
432
433 // create a remote list with a RemoteOverride callback
434 RemoteList(RemoteOverride *remote_override_arg)
435 : remote_override(remote_override_arg)
436 {
437 next();
438 }
439
440 // create a remote list with exactly one item
441 RemoteList(const std::string &server_host,
442 const std::string &server_port,
443 const Protocol &transport_protocol,
444 const std::string &title)
445 {
446 HostPort::validate_port(server_port, title);
447
448 Item::Ptr item(new Item());
449 item->server_host = server_host;
450 item->server_port = server_port;
451 item->transport_protocol = transport_protocol;
452 list.push_back(item);
453 }
454
455 // RemoteList flags
456 enum
457 {
461 ALLOW_EMPTY = 1 << 3,
462 };
463
464 // create a remote list from config file option list
466 const std::string &connection_tag,
467 const unsigned int flags,
468 ConnBlockFactory *conn_block_factory,
469 RandomAPI::Ptr rng_arg)
470 : random_hostname(opt.exists("remote-random-hostname")),
471 directives(connection_tag), rng(rng_arg)
472 {
474
475 // defaults
476 const Protocol default_proto = get_proto(opt, Protocol(Protocol::UDPv4));
477 const std::string default_port = get_port(opt, "1194");
478
479 // handle remote, port, and proto at the top-level
480 if (!(flags & CONN_BLOCK_ONLY))
481 add(opt, default_proto, default_port, ConnBlock::Ptr());
482
483 // cycle through <connection> blocks
484 {
485 const size_t max_conn_block_size = 4096;
487 if (conn)
488 {
489 for (OptionList::IndexList::const_iterator i = conn->begin(); i != conn->end(); ++i)
490 {
491 try
492 {
493 const Option &o = opt[*i];
494 o.touch();
495 const std::string &conn_block_text = o.get(1, Option::MULTILINE);
496 OptionList::Limits limits("<connection> block is too large",
497 max_conn_block_size,
502 OptionList::Ptr conn_block = OptionList::parse_from_config_static_ptr(conn_block_text, &limits);
503 const Protocol block_proto = get_proto(*conn_block, default_proto);
504 const std::string block_port = get_port(*conn_block, default_port);
505
506 // unsupported options
508 {
509 unsupported_in_connection_block(*conn_block, "http-proxy");
510 unsupported_in_connection_block(*conn_block, "http-proxy-option");
511 unsupported_in_connection_block(*conn_block, "http-proxy-user-pass");
512 }
513
514 // connection block options encapsulation via user-defined factory
515 {
517 if (conn_block_factory)
518 cb = conn_block_factory->new_conn_block(conn_block);
519 if (!(flags & CONN_BLOCK_OMIT_UNDEF) || cb)
520 add(*conn_block, block_proto, block_port, cb);
521 }
522 }
523 catch (Exception &e)
524 {
525 e.remove_label("option_error");
526 e.add_label("connection_block");
527 throw;
528 }
529 }
530 }
531 }
532
533 if (!(flags & ALLOW_EMPTY) && list.empty())
534 throw option_error(ERR_INVALID_CONFIG, "remote option not specified");
535 }
536
537 void process_push(const OptionList &opt)
538 {
540 }
541
542 // if cache is enabled, all DNS names will be preemptively queried
543 void set_enable_cache(const bool enable_cache_arg)
544 {
545 enable_cache = enable_cache_arg;
546 }
547
548 bool get_enable_cache() const
549 {
550 return enable_cache;
551 }
552
553 // override all server hosts to server_override
554 void set_server_override(const std::string &server_override)
555 {
556 if (server_override.empty())
557 return;
558 for (auto &item : list)
559 {
560 item->server_host = server_override;
561 item->random_host.clear();
562 item->res_addr_list.reset();
563 }
564 random_hostname = false;
565 reset_cache();
566 }
567
568 // override all server ports to port_override
569 void set_port_override(const std::string &port_override)
570 {
571 if (port_override.empty())
572 return;
573 for (auto &item : list)
574 {
575 item->server_port = port_override;
576 item->res_addr_list.reset();
577 }
578 reset_cache();
579 }
580
581 // override all Item's transport_protocol version to v
583 {
585 return;
586 for (auto item : list)
587 item->transport_protocol.mod_addr_version(v);
588 reset_cache();
589 }
590
591 void set_random(const RandomAPI::Ptr &rng_arg)
592 {
593 rng = rng_arg;
594 }
595
596 // randomize item list, used to implement remote-random directive
598 {
599 if (rng)
600 {
601 random = true;
602 std::shuffle(list.begin(), list.end(), *rng);
603 index.reset();
604 }
605 }
606
607 // Higher-level version of set_proto_override that also supports indication
608 // on whether or not TCP-based proxies are enabled. Should be called after set_enable_cache
609 // because it may modify enable_cache flag.
610 void handle_proto_override(const Protocol &proto_override, const bool tcp_proxy_enabled)
611 {
612 if (tcp_proxy_enabled)
613 {
614 const Protocol tcp(Protocol::TCP);
615 if (contains_protocol(tcp))
617 else
618 throw option_error(ERR_INVALID_CONFIG, "cannot connect via TCP-based proxy because no TCP server entries exist in profile");
619 }
620 else if (proto_override.defined() && contains_protocol(proto_override))
621 set_proto_override(proto_override);
622 }
623
624 // increment to next IP address or remote list entry
626 {
627 if (remote_override)
628 {
629 Item::Ptr item = remote_override->get();
630 if (item)
631 {
632 list.clear();
633 index.reset();
634 list.push_back(std::move(item));
635 return;
636 }
637 }
638
639 if (type != Advance::None)
640 {
641 bool item_changed = index.increment(type, list.size(), item_addr_length(index.item()));
642 if (item_changed && !enable_cache)
644 }
645 }
646
647 // Return details about current connection entry.
648 // Return value is true if get_endpoint may be called
649 // without raising an exception.
650 bool endpoint_available(std::string *server_host, std::string *server_port, Protocol *transport_protocol) const
651 {
652 const Item &item = *list[item_index()];
653 if (server_host)
654 *server_host = item.actual_host();
655 if (server_port)
656 *server_port = item.server_port;
657 const bool cached = (item.res_addr_list && index.item_addr() < item.res_addr_list->size());
658 if (transport_protocol)
659 {
660 *transport_protocol = item.transport_protocol;
661 }
662 return cached;
663 }
664
665 // cache a list of DNS-resolved IP addresses
666 template <class EPRANGE>
667 void set_endpoint_range(EPRANGE &endpoint_range)
668 {
669 Item &item = *list[item_index()];
670 auto rand = random ? rng.get() : nullptr;
671 std::size_t lifetime = enable_cache ? cache_lifetime : 0;
672 item.set_endpoint_range(endpoint_range, rand, lifetime);
674 }
675
676 // get an endpoint for contacting server
677 template <class EP>
678 void get_endpoint(EP &endpoint) const
679 {
680 const Item &item = *list[item_index()];
681 if (!item.get_endpoint(endpoint, index.item_addr()))
682 throw remote_list_error("current remote server endpoint is undefined");
683 }
684
685 // return true if object has at least one connection entry
686 bool defined() const
687 {
688 return list.size() > 0;
689 }
690
691 // return remote list size
692 size_t size() const
693 {
694 return list.size();
695 }
696
697 Item::Ptr get_item(const size_t index) const
698 {
699 return list.at(index);
700 }
701
702 // return hostname (or IP address) of current connection entry
703 std::string current_server_host() const
704 {
705 const Item &item = *list[item_index()];
706 return item.actual_host();
707 }
708
709 // return transport protocol of current connection entry
711 {
712 const Item &item = *list[item_index()];
713 return item.transport_protocol;
714 }
715
716 template <typename T>
718 {
719 const Item &item = *list[item_index()];
720 return dynamic_cast<T *>(item.conn_block.get());
721 }
722
723 std::string to_string() const
724 {
725 std::ostringstream out;
726 for (size_t i = 0; i < list.size(); ++i)
727 {
728 const Item &e = *list[i];
729 out << '[' << i << "] " << e.to_string() << std::endl;
730 }
731 return out.str();
732 }
733
734 // return a list of unique, cached IP addresses
736 {
737 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
738 {
739 const Item &item = **i;
740 if (item.res_addr_list_defined())
741 {
742 const ResolvedAddrList &ral = *item.res_addr_list;
743 for (ResolvedAddrList::const_iterator j = ral.begin(); j != ral.end(); ++j)
744 {
745 const ResolvedAddr &addr = **j;
746 addrlist.add(addr.addr);
747 }
748 }
749 }
750 }
751
752 // reset the cache associated with all items
754 {
755 for (auto &e : list)
756 {
757 e->res_addr_list.reset(nullptr);
758 randomize_host(*e);
759 }
760 index.reset();
761 }
762
763 // if caching is disabled, reset the cache for current item
765 {
766 if (!enable_cache)
768 }
769
770 private:
771 // Process --remote-cache-lifetime option
773 {
774 if (!opt.exists("remote-cache-lifetime"))
775 return;
776
777 const bool lifetimes_set = cache_lifetime != 0;
778 cache_lifetime = opt.get("remote-cache-lifetime").get_num(1, 0);
779 if (!enable_cache || lifetimes_set)
780 return;
781
782 // Init lifetimes on items with adresses
783 for (auto &item : list)
784 {
785 if (item->res_addr_list_defined())
786 item->decay_time = time(nullptr) + cache_lifetime;
787 }
788 }
789
790 // reset the cache associated with a given item
791 void reset_item(const size_t i)
792 {
793 if (i < list.size())
794 {
795 list[i]->res_addr_list.reset(nullptr);
796 list[i]->decay_time = std::numeric_limits<std::time_t>::max();
797 randomize_host(*list[i]);
798 }
799 }
800
801 // return the current item index (into list) and raise an exception
802 // if it is undefined
803 size_t item_index() const
804 {
805 const size_t pri = index.item();
806 if (pri < list.size())
807 return pri;
808 else
809 throw remote_list_error("current remote server item is undefined");
810 }
811
812 // return the number of cached IP addresses associated with a given item
813 size_t item_addr_length(const size_t i) const
814 {
815 if (i < list.size())
816 {
817 const Item &item = *list[i];
818 if (item.res_addr_list)
819 return item.res_addr_list->size();
820 }
821 return 0;
822 }
823
824 // return true if at least one remote entry is of type proto
825 bool contains_protocol(const Protocol &proto)
826 {
827 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
828 {
829 if (proto.transport_match((*i)->transport_protocol))
830 return true;
831 }
832 return false;
833 }
834
835 // prune remote entries so that only those of Protocol proto_override remain
836 void set_proto_override(const Protocol &proto_override)
837 {
838 if (proto_override.defined())
839 {
840 size_t di = 0;
841 for (size_t si = 0; si < list.size(); ++si)
842 {
843 const Item &item = *list[si];
844 if (proto_override.transport_match(item.transport_protocol))
845 {
846 if (si != di)
847 list[di] = list[si];
848 ++di;
849 }
850 }
851 if (di != list.size())
852 list.resize(di);
853 reset_cache();
854 }
855 }
856
857 // Return true if at least one cached Item exists
859 {
860 for (std::vector<Item::Ptr>::const_iterator i = list.begin(); i != list.end(); ++i)
861 {
862 const Item &item = **i;
863 if (item.res_addr_list_defined())
864 return true;
865 }
866 return false;
867 }
868
869 // Prune uncached Items so that only Items containing a res_addr_list with
870 // size > 0 remain.
872 {
873 size_t di = 0;
874 for (size_t si = 0; si < list.size(); ++si)
875 {
876 const Item &item = *list[si];
877 if (item.res_addr_list_defined())
878 {
879 if (si != di)
880 {
881 list[di] = list[si];
882 if (si == index.item())
883 index.set_item(di);
884 }
885 ++di;
886 }
887 }
888 if (di != list.size())
889 list.resize(di);
890 }
891
892 std::string get_port(const OptionList &opt, const std::string &default_port)
893 {
894 // parse "port" option if present
895 const Option *o = opt.get_ptr(directives.port);
896 if (!o)
897 return default_port;
898
899 std::string port = o->get(1, 16);
901 return port;
902 }
903
904 Protocol get_proto(const OptionList &opt, const Protocol &default_proto)
905 {
906 // parse "proto" option if present
907 const Option *o = opt.get_ptr(directives.proto);
908 if (o)
910
911 return default_proto;
912 }
913
914 void add(const OptionList &opt, const Protocol &default_proto, const std::string &default_port, ConnBlock::Ptr conn_block)
915 {
917 if (!rem)
918 return;
919
920 // cycle through remote entries
921 for (const auto &i : *rem)
922 {
923 Item::Ptr e(new Item());
924 const Option &o = opt[i];
925 o.touch();
926 e->server_host = o.get(1, 256);
927 int adj = 0;
928 if (o.size() >= 3)
929 {
930 e->server_port = o.get(2, 16);
931 if (Protocol::is_local_type(e->server_port))
932 {
933 adj = -1;
934 e->server_port = "";
935 }
936 else
937 HostPort::validate_port(e->server_port, directives.port);
938 }
939 else
940 e->server_port = default_port;
941 if (o.size() >= (size_t)(4 + adj))
942 e->transport_protocol = Protocol::parse(o.get(3 + adj, 16), Protocol::CLIENT_SUFFIX);
943 else
944 e->transport_protocol = default_proto;
945 e->conn_block = conn_block;
946 randomize_host(*e);
947 if (conn_block)
948 conn_block->new_item(*e);
949 list.push_back(e);
950 }
951 }
952
953 void unsupported_in_connection_block(const OptionList &options, const std::string &option)
954 {
955 if (options.exists(option))
956 OPENVPN_LOG("NOTE: " << option << " directive is not currently supported in <connection> blocks");
957 }
958
960 {
961 if (!random_hostname || !rng)
962 return;
963
964 try
965 {
966 // Throws if server_host is not an IP address
967 IP::Addr(item.server_host);
968 }
969 catch (const IP::ip_exception &)
970 {
971 // Produce 6 bytes of random prefix data
972 unsigned char prefix[6];
973 rng->rand_bytes(prefix, sizeof(prefix));
974
975 // Prepend it to the server_host
976 std::ostringstream random_host;
977 random_host << std::hex;
978 for (std::size_t i = 0; i < sizeof(prefix); ++i)
979 {
980 random_host << std::setw(2) << std::setfill('0')
981 << static_cast<unsigned>(prefix[i]);
982 }
983 random_host << "." << item.server_host;
984
985 item.random_host = random_host.str();
986 }
987 }
988
989 std::size_t cache_lifetime = 0;
990 bool random_hostname = false;
991 bool random = false;
992 bool enable_cache = false;
994
995 std::vector<Item::Ptr> list;
996
998
1000
1002};
1003
1004} // namespace openvpn
1005
1006#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:63
void add_label(const std::string &label)
Definition exception.hpp:58
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:1276
static OptionList::Ptr parse_from_config_static_ptr(const std::string &str, Limits *lim)
Definition options.hpp:867
const Option & get(const std::string &name) const
Definition options.hpp:1254
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
std::vector< unsigned int > IndexList
Definition options.hpp:520
bool exists(const std::string &name) const
Definition options.hpp:1325
void touch(bool lightly=false) const
Definition options.hpp:385
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:187
T get_num(const size_t idx) const
Definition options.hpp:222
size_t size() const
Definition options.hpp:327
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:912
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
RCPtr< RemoteList > Ptr
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
RCPtr< ConnBlockFactory > Ptr
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)
RCPtr< ResolvedAddrList > Ptr
reroute_gw flags
proxy_host_port port
std::string ret
static std::stringstream out
Definition test_path.cpp:10