OpenVPN 3 Core Library
Loading...
Searching...
No Matches
tcpcli.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// TCP transport object specialized for client.
13
14#ifndef OPENVPN_TRANSPORT_CLIENT_TCPCLI_H
15#define OPENVPN_TRANSPORT_CLIENT_TCPCLI_H
16
17#include <sstream>
18
19#include <openvpn/io/io.hpp>
20
22#ifdef OPENVPN_TLS_LINK
23#include <openvpn/transport/tlslink.hpp>
24#endif
28
30
32{
33 public:
35
40
42
43#ifdef OPENVPN_TLS_LINK
44 bool use_tls = false;
45 std::string tls_ca;
46#endif
47
48#ifdef OPENVPN_GREMLIN
49 Gremlin::Config::Ptr gremlin_config;
50#endif
51
52 static Ptr new_obj()
53 {
54 return new ClientConfig;
55 }
56
57 TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context,
58 TransportClientParent *parent) override;
59
60 void process_push(const OptionList &opt) override
61 {
63 }
64
65 private:
68 socket_protect(nullptr)
69 {
70 }
71};
72
74{
76
78#ifdef OPENVPN_TLS_LINK
79 typedef TLSLink<openvpn_io::ip::tcp, Client *, false> LinkImplTLS;
80#endif
81
82 friend class ClientConfig; // calls constructor
83 friend LinkImpl::Base; // calls tcp_read_handler
84
85 public:
86 void transport_start() override
87 {
88 if (!impl)
89 {
90 halt = false;
91 stop_requeueing = false;
92 if (config->remote_list->endpoint_available(&server_host,
95 {
97 }
98 else
99 {
101
103 }
104 }
105 }
106
107 bool transport_send_const(const Buffer &buf) override
108 {
109 return send_const(buf);
110 }
111
112 bool transport_send(BufferAllocated &buf) override
113 {
114 return send(buf);
115 }
116
118 {
119 if (impl)
120 return impl->send_queue_empty();
121 return false;
122 }
123
125 {
126 return true;
127 }
128
130 {
131 if (impl)
132 return impl->send_queue_size();
133 return 0;
134 }
135
136 void reset_align_adjust(const size_t align_adjust) override
137 {
138 if (impl)
139 impl->reset_align_adjust(align_adjust);
140 }
141
142 void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
143 {
146 const IP::Addr addr = server_endpoint_addr();
147 proto = server_protocol.str();
148 ip_addr = addr.to_string();
149 }
150
152 {
153 return IP::Addr::from_asio(server_endpoint.address());
154 }
155
156 unsigned short server_endpoint_port() const override
157 {
158 return server_endpoint.port();
159 }
160
161 openvpn_io::detail::socket_type native_handle() override
162 {
163 return socket.native_handle();
164 }
165
167 {
168 return server_protocol;
169 }
170
171 void stop() override
172 {
173 stop_();
174 }
175 ~Client() override
176 {
177 stop_();
178 }
179
180 private:
181 Client(openvpn_io::io_context &io_context_arg,
182 ClientConfig *config_arg,
183 TransportClientParent *parent_arg)
184 : AsyncResolvableTCP(io_context_arg),
185 io_context(io_context_arg),
186 socket(io_context_arg),
187 config(config_arg),
188 parent(parent_arg),
189 resolver(io_context_arg),
190 halt(false),
191 stop_requeueing(false)
192 {
193 }
194
195 void transport_reparent(TransportClientParent *parent_arg) override
196 {
197 parent = parent_arg;
198 }
199
201 {
202 stop_requeueing = true;
203 }
204
205 bool send_const(const Buffer &cbuf)
206 {
207 if (impl)
208 {
209 BufferAllocated buf(cbuf);
210 return impl->send(buf);
211 }
212 return false;
213 }
214
216 {
217 if (impl)
218 return impl->send(buf);
219 return false;
220 }
221
222 void tcp_eof_handler() // called by LinkImpl::Base
223 {
224 config->stats->error(Error::NETWORK_EOF_ERROR);
225 tcp_error_handler("NETWORK_EOF_ERROR");
226 }
227
228 bool tcp_read_handler(BufferAllocated &buf) // called by LinkImpl::Base
229 {
231 return !stop_requeueing;
232 }
233
234 void tcp_write_queue_needs_send() // called by LinkImpl::Base
235 {
237 }
238
239 void tcp_error_handler(const char *error) // called by LinkImpl::Base
240 {
241 std::ostringstream os;
242 os << "Transport error on '" << server_host << ": " << error;
243 stop();
245 }
246
247 void stop_()
248 {
249 if (!halt)
250 {
251 halt = true;
252 if (impl)
253 impl->stop();
254
255 socket.close();
256 resolver.cancel();
258 }
259 }
260
261 // do DNS resolve
262 void resolve_callback(const openvpn_io::error_code &error,
263 results_type results) override
264 {
265 if (!halt)
266 {
267 if (!error)
268 {
269 // save resolved endpoint list in remote_list
270 config->remote_list->set_endpoint_range(results);
272 }
273 else
274 {
275 std::ostringstream os;
276 os << "DNS resolve error on '" << server_host << "' for " << server_protocol.str() << " session: " << error.message();
277 config->stats->error(Error::RESOLVE_ERROR);
278 stop();
280 }
281 }
282 }
283
284 // do TCP connect
286 {
287 config->remote_list->get_endpoint(server_endpoint);
288 OPENVPN_LOG("Contacting " << server_endpoint << " via "
289 << server_protocol.str());
291 socket.open(server_endpoint.protocol());
292
293 if (config->socket_protect)
294 {
295 if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
296 {
297 config->stats->error(Error::SOCKET_PROTECT_ERROR);
298 stop();
299 parent->transport_error(Error::UNDEF, "socket_protect error (" + std::string(server_protocol.str()) + ")");
300 return;
301 }
302 }
303
304 socket.set_option(openvpn_io::ip::tcp::no_delay(true));
305 socket.async_connect(server_endpoint, [self = Ptr(this)](const openvpn_io::error_code &error)
306 {
308 self->start_impl_(error); });
309 }
310
311 // start I/O on TCP socket
312 void start_impl_(const openvpn_io::error_code &error)
313 {
314 if (!halt)
315 {
316 if (!error)
317 {
318#ifdef OPENVPN_TLS_LINK
319 if (config->use_tls)
320 {
322 SSLLib::SSLAPI::Config::Ptr ssl_conf;
323 ssl_conf.reset(new SSLLib::SSLAPI::Config());
324 ssl_conf->set_mode(Mode(Mode::CLIENT));
325 ssl_conf->set_local_cert_enabled(false);
326 ssl_conf->set_frame(config->frame);
327 ssl_conf->set_rng(new SSLLib::RandomAPI());
328
329 if (!config->tls_ca.empty())
330 {
331 ssl_conf->load_ca(config->tls_ca, true);
332 }
333 else
334 {
336 }
337
338 ssl_conf->set_flags(flags);
339 ssl_factory = ssl_conf->new_factory();
340
341 impl.reset(new LinkImplTLS(this,
343 socket,
344 0,
345 config->free_list_max_size,
346 config->frame,
347 config->stats,
348 ssl_factory));
349 }
350 else
351#endif
352 impl.reset(new LinkImpl(this,
353 socket,
354 0, // send_queue_max_size is unlimited because we regulate size in cliproto.hpp
355 config->free_list_max_size,
356 (*config->frame)[Frame::READ_LINK_TCP],
357 config->stats));
358
359#ifdef OPENVPN_GREMLIN
360 impl->gremlin_config(config->gremlin_config);
361#endif
362 impl->start();
364 impl->set_raw_mode(true);
366 }
367 else
368 {
369 std::ostringstream os;
370 os << server_protocol.str() << " connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message();
371 config->stats->error(Error::TCP_CONNECT_ERROR);
372 stop();
374 }
375 }
376 }
377
378 std::string server_host;
379 std::string server_port;
381
382 openvpn_io::io_context &io_context;
383 openvpn_io::ip::tcp::socket socket;
387 openvpn_io::ip::tcp::resolver resolver;
388 LinkImpl::Base::protocol::endpoint server_endpoint;
389 bool halt;
391
392#ifdef OPENVPN_TLS_LINK
393 SSLFactoryAPI::Ptr ssl_factory;
394#endif
395};
396
397inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
398 TransportClientParent *parent)
399{
400 return TransportClient::Ptr(new Client(io_context, this, parent));
401}
402} // namespace openvpn::TCPTransport
403
404#endif
#define OPENVPN_ASYNC_HANDLER
Definition bigmutex.hpp:36
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
static Addr from_asio(const openvpn_io::ip::address &addr)
Definition ip.hpp:576
std::string to_string() const
Definition ip.hpp:528
const char * str() const
Definition protocol.hpp:212
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
void process_push(const OptionList &opt)
TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context, TransportClientParent *parent) override
Definition tcpcli.hpp:397
void process_push(const OptionList &opt) override
Definition tcpcli.hpp:60
LinkImpl::Base::protocol::endpoint server_endpoint
Definition tcpcli.hpp:388
void transport_start() override
Definition tcpcli.hpp:86
openvpn_io::ip::tcp::resolver resolver
Definition tcpcli.hpp:387
ClientConfig::Ptr config
Definition tcpcli.hpp:384
void transport_stop_requeueing() override
Definition tcpcli.hpp:200
void start_impl_(const openvpn_io::error_code &error)
Definition tcpcli.hpp:312
openvpn_io::io_context & io_context
Definition tcpcli.hpp:382
bool send(BufferAllocated &buf)
Definition tcpcli.hpp:215
bool transport_has_send_queue() override
Definition tcpcli.hpp:124
bool send_const(const Buffer &cbuf)
Definition tcpcli.hpp:205
size_t transport_send_queue_size() override
Definition tcpcli.hpp:129
void transport_reparent(TransportClientParent *parent_arg) override
Definition tcpcli.hpp:195
IP::Addr server_endpoint_addr() const override
Definition tcpcli.hpp:151
void tcp_error_handler(const char *error)
Definition tcpcli.hpp:239
openvpn_io::detail::socket_type native_handle() override
Definition tcpcli.hpp:161
TCPLink< openvpn_io::ip::tcp, Client *, false > LinkImpl
Definition tcpcli.hpp:77
openvpn_io::ip::tcp::socket socket
Definition tcpcli.hpp:383
bool tcp_read_handler(BufferAllocated &buf)
Definition tcpcli.hpp:228
void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
Definition tcpcli.hpp:142
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TransportClientParent *parent_arg)
Definition tcpcli.hpp:181
bool transport_send_queue_empty() override
Definition tcpcli.hpp:117
TransportClientParent * parent
Definition tcpcli.hpp:385
bool transport_send_const(const Buffer &buf) override
Definition tcpcli.hpp:107
void resolve_callback(const openvpn_io::error_code &error, results_type results) override
Definition tcpcli.hpp:262
unsigned short server_endpoint_port() const override
Definition tcpcli.hpp:156
void reset_align_adjust(const size_t align_adjust) override
Definition tcpcli.hpp:136
Protocol transport_protocol() const override
Definition tcpcli.hpp:166
bool transport_send(BufferAllocated &buf) override
Definition tcpcli.hpp:112
#define OPENVPN_LOG(args)
@ NETWORK_EOF_ERROR
Definition error.hpp:25
@ TCP_CONNECT_ERROR
Definition error.hpp:50
@ SOCKET_PROTECT_ERROR
Definition error.hpp:36
virtual void transport_connecting()=0
virtual void transport_pre_resolve()=0
virtual void transport_error(const Error::Type fatal_err, const std::string &err_text)=0
virtual bool transport_is_openvpn_protocol()=0
virtual void transport_wait()=0
virtual void transport_recv(BufferAllocated &buf)=0
virtual void transport_needs_send()=0
RCPtr< TransportClient > Ptr
Definition transbase.hpp:37
reroute_gw flags
proxy_host_port port
proxy_host_port host
std::ostringstream os