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 else
122 return false;
123 }
124
126 {
127 return true;
128 }
129
131 {
132 if (impl)
133 return impl->send_queue_size();
134 else
135 return 0;
136 }
137
138 void reset_align_adjust(const size_t align_adjust) override
139 {
140 if (impl)
141 impl->reset_align_adjust(align_adjust);
142 }
143
144 void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
145 {
148 const IP::Addr addr = server_endpoint_addr();
149 proto = server_protocol.str();
150 ip_addr = addr.to_string();
151 }
152
154 {
155 return IP::Addr::from_asio(server_endpoint.address());
156 }
157
158 unsigned short server_endpoint_port() const override
159 {
160 return server_endpoint.port();
161 }
162
163 openvpn_io::detail::socket_type native_handle() override
164 {
165 return socket.native_handle();
166 }
167
169 {
170 return server_protocol;
171 }
172
173 void stop() override
174 {
175 stop_();
176 }
177 ~Client() override
178 {
179 stop_();
180 }
181
182 private:
183 Client(openvpn_io::io_context &io_context_arg,
184 ClientConfig *config_arg,
185 TransportClientParent *parent_arg)
186 : AsyncResolvableTCP(io_context_arg),
187 io_context(io_context_arg),
188 socket(io_context_arg),
189 config(config_arg),
190 parent(parent_arg),
191 resolver(io_context_arg),
192 halt(false),
193 stop_requeueing(false)
194 {
195 }
196
197 void transport_reparent(TransportClientParent *parent_arg) override
198 {
199 parent = parent_arg;
200 }
201
203 {
204 stop_requeueing = true;
205 }
206
207 bool send_const(const Buffer &cbuf)
208 {
209 if (impl)
210 {
211 BufferAllocated buf(cbuf, 0);
212 return impl->send(buf);
213 }
214 else
215 return false;
216 }
217
219 {
220 if (impl)
221 return impl->send(buf);
222 else
223 return false;
224 }
225
226 void tcp_eof_handler() // called by LinkImpl::Base
227 {
228 config->stats->error(Error::NETWORK_EOF_ERROR);
229 tcp_error_handler("NETWORK_EOF_ERROR");
230 }
231
232 bool tcp_read_handler(BufferAllocated &buf) // called by LinkImpl::Base
233 {
235 return !stop_requeueing;
236 }
237
238 void tcp_write_queue_needs_send() // called by LinkImpl::Base
239 {
241 }
242
243 void tcp_error_handler(const char *error) // called by LinkImpl::Base
244 {
245 std::ostringstream os;
246 os << "Transport error on '" << server_host << ": " << error;
247 stop();
249 }
250
251 void stop_()
252 {
253 if (!halt)
254 {
255 halt = true;
256 if (impl)
257 impl->stop();
258
259 socket.close();
260 resolver.cancel();
262 }
263 }
264
265 // do DNS resolve
266 void resolve_callback(const openvpn_io::error_code &error,
267 results_type results) override
268 {
269 if (!halt)
270 {
271 if (!error)
272 {
273 // save resolved endpoint list in remote_list
274 config->remote_list->set_endpoint_range(results);
276 }
277 else
278 {
279 std::ostringstream os;
280 os << "DNS resolve error on '" << server_host << "' for " << server_protocol.str() << " session: " << error.message();
281 config->stats->error(Error::RESOLVE_ERROR);
282 stop();
284 }
285 }
286 }
287
288 // do TCP connect
290 {
291 config->remote_list->get_endpoint(server_endpoint);
292 OPENVPN_LOG("Contacting " << server_endpoint << " via "
293 << server_protocol.str());
295 socket.open(server_endpoint.protocol());
296
297 if (config->socket_protect)
298 {
299 if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
300 {
301 config->stats->error(Error::SOCKET_PROTECT_ERROR);
302 stop();
303 parent->transport_error(Error::UNDEF, "socket_protect error (" + std::string(server_protocol.str()) + ")");
304 return;
305 }
306 }
307
308 socket.set_option(openvpn_io::ip::tcp::no_delay(true));
309 socket.async_connect(server_endpoint, [self = Ptr(this)](const openvpn_io::error_code &error)
310 {
312 self->start_impl_(error); });
313 }
314
315 // start I/O on TCP socket
316 void start_impl_(const openvpn_io::error_code &error)
317 {
318 if (!halt)
319 {
320 if (!error)
321 {
322#ifdef OPENVPN_TLS_LINK
323 if (config->use_tls)
324 {
326 SSLLib::SSLAPI::Config::Ptr ssl_conf;
327 ssl_conf.reset(new SSLLib::SSLAPI::Config());
328 ssl_conf->set_mode(Mode(Mode::CLIENT));
329 ssl_conf->set_local_cert_enabled(false);
330 ssl_conf->set_frame(config->frame);
331 ssl_conf->set_rng(new SSLLib::RandomAPI());
332
333 if (!config->tls_ca.empty())
334 {
335 ssl_conf->load_ca(config->tls_ca, true);
336 }
337 else
338 {
340 }
341
342 ssl_conf->set_flags(flags);
343 ssl_factory = ssl_conf->new_factory();
344
345 impl.reset(new LinkImplTLS(this,
347 socket,
348 0,
349 config->free_list_max_size,
350 config->frame,
351 config->stats,
352 ssl_factory));
353 }
354 else
355#endif
356 impl.reset(new LinkImpl(this,
357 socket,
358 0, // send_queue_max_size is unlimited because we regulate size in cliproto.hpp
359 config->free_list_max_size,
360 (*config->frame)[Frame::READ_LINK_TCP],
361 config->stats));
362
363#ifdef OPENVPN_GREMLIN
364 impl->gremlin_config(config->gremlin_config);
365#endif
366 impl->start();
368 impl->set_raw_mode(true);
370 }
371 else
372 {
373 std::ostringstream os;
374 os << server_protocol.str() << " connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message();
375 config->stats->error(Error::TCP_CONNECT_ERROR);
376 stop();
378 }
379 }
380 }
381
382 std::string server_host;
383 std::string server_port;
385
386 openvpn_io::io_context &io_context;
387 openvpn_io::ip::tcp::socket socket;
391 openvpn_io::ip::tcp::resolver resolver;
392 LinkImpl::Base::protocol::endpoint server_endpoint;
393 bool halt;
395
396#ifdef OPENVPN_TLS_LINK
397 SSLFactoryAPI::Ptr ssl_factory;
398#endif
399};
400
401inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
402 TransportClientParent *parent)
403{
404 return TransportClient::Ptr(new Client(io_context, this, parent));
405}
406} // namespace openvpn::TCPTransport
407
408#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
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
void process_push(const OptionList &opt)
RCPtr< ClientConfig > Ptr
Definition tcpcli.hpp:34
TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context, TransportClientParent *parent) override
Definition tcpcli.hpp:401
void process_push(const OptionList &opt) override
Definition tcpcli.hpp:60
LinkImpl::Base::protocol::endpoint server_endpoint
Definition tcpcli.hpp:392
void transport_start() override
Definition tcpcli.hpp:86
openvpn_io::ip::tcp::resolver resolver
Definition tcpcli.hpp:391
ClientConfig::Ptr config
Definition tcpcli.hpp:388
void transport_stop_requeueing() override
Definition tcpcli.hpp:202
void start_impl_(const openvpn_io::error_code &error)
Definition tcpcli.hpp:316
openvpn_io::io_context & io_context
Definition tcpcli.hpp:386
bool send(BufferAllocated &buf)
Definition tcpcli.hpp:218
bool transport_has_send_queue() override
Definition tcpcli.hpp:125
bool send_const(const Buffer &cbuf)
Definition tcpcli.hpp:207
size_t transport_send_queue_size() override
Definition tcpcli.hpp:130
void transport_reparent(TransportClientParent *parent_arg) override
Definition tcpcli.hpp:197
IP::Addr server_endpoint_addr() const override
Definition tcpcli.hpp:153
TCPLink< openvpn_io::ip::tcp, Client *, false > LinkImpl
Definition tcpcli.hpp:77
void tcp_error_handler(const char *error)
Definition tcpcli.hpp:243
openvpn_io::detail::socket_type native_handle() override
Definition tcpcli.hpp:163
openvpn_io::ip::tcp::socket socket
Definition tcpcli.hpp:387
bool tcp_read_handler(BufferAllocated &buf)
Definition tcpcli.hpp:232
void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
Definition tcpcli.hpp:144
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TransportClientParent *parent_arg)
Definition tcpcli.hpp:183
bool transport_send_queue_empty() override
Definition tcpcli.hpp:117
TransportClientParent * parent
Definition tcpcli.hpp:389
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:266
unsigned short server_endpoint_port() const override
Definition tcpcli.hpp:158
void reset_align_adjust(const size_t align_adjust) override
Definition tcpcli.hpp:138
Protocol transport_protocol() const override
Definition tcpcli.hpp:168
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