mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
Added AltProxy API that allows for alternative proxy implementations
to be developed outside the core.
This commit is contained in:
parent
d5f249b3a4
commit
557df02296
@ -301,7 +301,8 @@ namespace openvpn {
|
||||
{
|
||||
ClientState() : conn_timeout(0), tun_persist(false),
|
||||
google_dns_fallback(false), disable_client_cert(false),
|
||||
default_key_direction(-1), force_aes_cbc_ciphersuites(false) {}
|
||||
default_key_direction(-1), force_aes_cbc_ciphersuites(false),
|
||||
alt_proxy(false) {}
|
||||
|
||||
OptionList options;
|
||||
EvalConfig eval;
|
||||
@ -326,6 +327,7 @@ namespace openvpn {
|
||||
std::string gui_version;
|
||||
ProtoContextOptions::Ptr proto_context_options;
|
||||
HTTPProxyTransport::Options::Ptr http_proxy_options;
|
||||
bool alt_proxy;
|
||||
};
|
||||
};
|
||||
|
||||
@ -416,6 +418,7 @@ namespace openvpn {
|
||||
state->default_key_direction = config.defaultKeyDirection;
|
||||
state->force_aes_cbc_ciphersuites = config.forceAesCbcCiphersuites;
|
||||
state->gui_version = config.guiVersion;
|
||||
state->alt_proxy = config.altProxy;
|
||||
if (!config.proxyHost.empty())
|
||||
{
|
||||
HTTPProxyTransport::Options::Ptr ho(new HTTPProxyTransport::Options());
|
||||
@ -597,6 +600,7 @@ namespace openvpn {
|
||||
cc.google_dns_fallback = state->google_dns_fallback;
|
||||
cc.proto_context_options = state->proto_context_options;
|
||||
cc.http_proxy_options = state->http_proxy_options;
|
||||
cc.alt_proxy = state->alt_proxy;
|
||||
cc.reconnect_notify = &state->reconnect_notify;
|
||||
cc.private_key_password = state->private_key_password;
|
||||
cc.disable_client_cert = state->disable_client_cert;
|
||||
|
@ -151,7 +151,8 @@ namespace openvpn {
|
||||
Config() : connTimeout(0), tunPersist(false), googleDnsFallback(false),
|
||||
disableClientCert(false), defaultKeyDirection(-1),
|
||||
forceAesCbcCiphersuites(false),
|
||||
proxyAllowCleartextAuth(false) {}
|
||||
proxyAllowCleartextAuth(false),
|
||||
altProxy(false) {}
|
||||
|
||||
// OpenVPN profile as a string
|
||||
std::string content;
|
||||
@ -219,6 +220,9 @@ namespace openvpn {
|
||||
std::string proxyUsername; // proxy credentials (optional)
|
||||
std::string proxyPassword; // proxy credentials (optional)
|
||||
bool proxyAllowCleartextAuth; // enables HTTP Basic auth
|
||||
|
||||
// Custom proxy implementation
|
||||
bool altProxy;
|
||||
};
|
||||
|
||||
// used to communicate VPN events such as connect, disconnect, etc.
|
||||
|
@ -22,6 +22,12 @@ else
|
||||
fi
|
||||
echo PACKAGE $PKG
|
||||
|
||||
if [ -d "$O3/common" ]; then
|
||||
common="-I$O3/common -DPRIVATE_TUNNEL_PROXY"
|
||||
else
|
||||
common=""
|
||||
fi
|
||||
|
||||
echo SWIG
|
||||
swig -c++ -java -package $pkg -I$O3/core/client -I$O3/core ovpncli.i
|
||||
|
||||
@ -64,6 +70,7 @@ g++ \
|
||||
-DHAVE_LZ4 \
|
||||
-I$O3/core/client \
|
||||
-I$O3/core \
|
||||
$common \
|
||||
-I$DEP_DIR/boost \
|
||||
$ssl_inc \
|
||||
-I$DEP_DIR/snappy/snappy-$PLATFORM/include \
|
||||
@ -80,6 +87,7 @@ g++ \
|
||||
$vis1 $vis2 \
|
||||
-I$O3/core/client \
|
||||
-I$O3/core \
|
||||
$common \
|
||||
-L$DEP_DIR/boost/stage-$PLATFORM/lib \
|
||||
$ssl_libdir \
|
||||
-L$DEP_DIR/minicrypto/minicrypto-$PLATFORM \
|
||||
|
@ -98,8 +98,9 @@ namespace openvpn {
|
||||
if (!test_network())
|
||||
throw ErrorCode(Error::NETWORK_UNAVAILABLE, true, "Network Unavailable");
|
||||
|
||||
RemoteList::Ptr remote_list = client_options->remote_list_precache();
|
||||
RemoteList::PreResolve::Ptr preres(new RemoteList::PreResolve(io_service,
|
||||
client_options->remote_list_ptr(),
|
||||
remote_list,
|
||||
client_options->stats_ptr()));
|
||||
if (preres->work_available())
|
||||
{
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <openvpn/transport/client/udpcli.hpp>
|
||||
#include <openvpn/transport/client/tcpcli.hpp>
|
||||
#include <openvpn/transport/client/httpcli.hpp>
|
||||
|
||||
#include <openvpn/transport/altproxy.hpp>
|
||||
#include <openvpn/client/cliproto.hpp>
|
||||
#include <openvpn/client/cliopthelper.hpp>
|
||||
#include <openvpn/client/optfilt.hpp>
|
||||
@ -68,6 +68,10 @@
|
||||
#include <openvpn/tun/client/tunnull.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef PRIVATE_TUNNEL_PROXY
|
||||
#include <openvpn/pt/ptproxy.hpp>
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class ClientOptions : public RC<thread_unsafe_refcount>
|
||||
@ -84,6 +88,7 @@ namespace openvpn {
|
||||
socket_protect = NULL;
|
||||
reconnect_notify = NULL;
|
||||
conn_timeout = 0;
|
||||
alt_proxy = false;
|
||||
tun_persist = false;
|
||||
google_dns_fallback = false;
|
||||
disable_client_cert = false;
|
||||
@ -102,6 +107,7 @@ namespace openvpn {
|
||||
ClientEvent::Queue::Ptr cli_events;
|
||||
ProtoContextOptions::Ptr proto_context_options;
|
||||
HTTPProxyTransport::Options::Ptr http_proxy_options;
|
||||
bool alt_proxy;
|
||||
bool tun_persist;
|
||||
bool google_dns_fallback;
|
||||
std::string private_key_password;
|
||||
@ -141,10 +147,12 @@ namespace openvpn {
|
||||
userlocked_username = pcc.userlockedUsername();
|
||||
autologin = pcc.autologin();
|
||||
|
||||
// digest factory
|
||||
DigestFactory::Ptr digest_factory(new CryptoDigestFactory<SSLLib::CryptoAPI>());
|
||||
|
||||
// initialize RNG/PRNG
|
||||
rng.reset(new SSLLib::RandomAPI(false));
|
||||
#if ENABLE_PRNG
|
||||
DigestFactory::Ptr digest_factory(new CryptoDigestFactory<SSLLib::CryptoAPI>());
|
||||
prng.reset(new PRNG("SHA1", digest_factory, rng, 16)); // fixme: hangs on OS X 10.6 with USE_POLARSSL_APPLE_HYBRID
|
||||
#else
|
||||
prng.reset(new SSLLib::RandomAPI(true));
|
||||
@ -188,12 +196,17 @@ namespace openvpn {
|
||||
cp->rng = rng;
|
||||
cp->prng = prng;
|
||||
|
||||
#ifdef PRIVATE_TUNNEL_PROXY
|
||||
if (config.alt_proxy)
|
||||
alt_proxy = PTProxy::new_proxy(opt);
|
||||
#endif
|
||||
|
||||
// If HTTP proxy parameters are not supplied by API, try to get them from config
|
||||
if (!http_proxy_options)
|
||||
http_proxy_options = HTTPProxyTransport::Options::parse(opt);
|
||||
|
||||
// load remote list
|
||||
remote_list.reset(new RemoteList(opt, true));
|
||||
remote_list.reset(new RemoteList(opt, "", true));
|
||||
if (!remote_list->defined())
|
||||
throw option_error("no remote option specified");
|
||||
|
||||
@ -206,7 +219,8 @@ namespace openvpn {
|
||||
remote_list->set_server_override(config.server_override);
|
||||
|
||||
// process protocol override, should be called after set_enable_cache
|
||||
remote_list->handle_proto_override(config.proto_override, bool(http_proxy_options));
|
||||
remote_list->handle_proto_override(config.proto_override,
|
||||
http_proxy_options || (alt_proxy && alt_proxy->requires_tcp()));
|
||||
|
||||
// process remote-random
|
||||
if (opt.exists("remote-random"))
|
||||
@ -215,8 +229,13 @@ namespace openvpn {
|
||||
// get "float" option
|
||||
server_addr_float = opt.exists("float");
|
||||
|
||||
// special remote cache handling for HTTP proxy
|
||||
if (http_proxy_options)
|
||||
// special remote cache handling for proxies
|
||||
if (alt_proxy)
|
||||
{
|
||||
remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
|
||||
alt_proxy->set_enable_cache(config.tun_persist);
|
||||
}
|
||||
else if (http_proxy_options)
|
||||
{
|
||||
remote_list->set_enable_cache(false); // remote server addresses will be resolved by proxy
|
||||
http_proxy_options->proxy_server_set_enable_cache(config.tun_persist);
|
||||
@ -349,7 +368,12 @@ namespace openvpn {
|
||||
|
||||
void next()
|
||||
{
|
||||
remote_list->next();
|
||||
bool omit_next = false;
|
||||
|
||||
if (alt_proxy)
|
||||
omit_next = alt_proxy->next();
|
||||
if (!omit_next)
|
||||
remote_list->next();
|
||||
load_transport_config();
|
||||
}
|
||||
|
||||
@ -410,11 +434,28 @@ namespace openvpn {
|
||||
SessionStats& stats() { return *cli_stats; }
|
||||
const SessionStats::Ptr& stats_ptr() const { return cli_stats; }
|
||||
ClientEvent::Queue& events() { return *cli_events; }
|
||||
const RemoteList::Ptr& remote_list_ptr() const { return remote_list; }
|
||||
ClientLifeCycle* lifecycle() { return client_lifecycle.get(); }
|
||||
|
||||
int conn_timeout() const { return conn_timeout_; }
|
||||
|
||||
RemoteList::Ptr remote_list_precache() const
|
||||
{
|
||||
RemoteList::Ptr r;
|
||||
if (alt_proxy)
|
||||
{
|
||||
alt_proxy->precache(r);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (http_proxy_options)
|
||||
{
|
||||
http_proxy_options->proxy_server_precache(r);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
return remote_list;
|
||||
}
|
||||
|
||||
void update_now()
|
||||
{
|
||||
now_.update();
|
||||
@ -435,11 +476,26 @@ namespace openvpn {
|
||||
// set transport protocol in Client::ProtoConfig
|
||||
cp->set_protocol(transport_protocol);
|
||||
|
||||
// If we are connecting over a proxy, and TCP protocol is required, but current
|
||||
// transport protocol is NOT TCP, we will throw an internal error because this
|
||||
// should have been caught earlier in RemoteList::handle_proto_override.
|
||||
|
||||
// construct transport object
|
||||
if (http_proxy_options)
|
||||
if (alt_proxy)
|
||||
{
|
||||
if (alt_proxy->requires_tcp() && !transport_protocol.is_tcp())
|
||||
throw option_error("internal error: no TCP server entries for " + alt_proxy->name() + " transport");
|
||||
AltProxy::Config conf;
|
||||
conf.remote_list = remote_list;
|
||||
conf.frame = frame;
|
||||
conf.stats = cli_stats;
|
||||
conf.digest_factory.reset(new CryptoDigestFactory<SSLLib::CryptoAPI>());
|
||||
conf.socket_protect = socket_protect;
|
||||
conf.rng = rng;
|
||||
transport_factory = alt_proxy->new_transport_client_factory(conf);
|
||||
}
|
||||
else if (http_proxy_options)
|
||||
{
|
||||
// HTTP proxy always uses TCP. If current transport protocol is not TCP, this is
|
||||
// an error that should have been caught earlier in RemoteList::handle_proto_override.
|
||||
if (!transport_protocol.is_tcp())
|
||||
throw option_error("internal error: no TCP server entries for HTTP proxy transport");
|
||||
|
||||
@ -510,6 +566,7 @@ namespace openvpn {
|
||||
PushOptionsBase::Ptr push_base;
|
||||
OptionList::FilterBase::Ptr pushed_options_filter;
|
||||
ClientLifeCycle::Ptr client_lifecycle;
|
||||
AltProxy::Ptr alt_proxy;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
// validate remote list
|
||||
RemoteList rl(options, false);
|
||||
RemoteList rl(options, "", false);
|
||||
|
||||
// determine if private key is encrypted
|
||||
if (!externalPki_)
|
||||
|
@ -55,6 +55,23 @@ namespace openvpn {
|
||||
|
||||
class RemoteList : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
// Directive names that we search for in options
|
||||
struct Directives
|
||||
{
|
||||
void init(const std::string& prefix)
|
||||
{
|
||||
connection = prefix + "connection";
|
||||
remote = prefix + "remote";
|
||||
proto = prefix + "proto";
|
||||
port = prefix + "port";
|
||||
}
|
||||
|
||||
std::string connection;
|
||||
std::string remote;
|
||||
std::string proto;
|
||||
std::string port;
|
||||
};
|
||||
|
||||
// A single IP address that is part of a list of IP addresses
|
||||
// associated with a "remote" item.
|
||||
struct ResolvedAddr : public RC<thread_unsafe_refcount>
|
||||
@ -339,20 +356,26 @@ namespace openvpn {
|
||||
size_t index;
|
||||
};
|
||||
|
||||
static bool directives_defined(const OptionList& opt, const std::string& directive_prefix)
|
||||
{
|
||||
Directives d;
|
||||
d.init(directive_prefix);
|
||||
return opt.get_index_ptr(d.connection) || opt.get_index_ptr(d.remote);
|
||||
}
|
||||
|
||||
// create an empty remote list
|
||||
RemoteList()
|
||||
{
|
||||
init();
|
||||
init("");
|
||||
}
|
||||
|
||||
|
||||
// create a remote list with exactly one item
|
||||
RemoteList(const std::string& server_host,
|
||||
const std::string& server_port,
|
||||
const Protocol& transport_protocol,
|
||||
const std::string& title)
|
||||
{
|
||||
init();
|
||||
init("");
|
||||
|
||||
validate_port(server_port, title);
|
||||
|
||||
@ -364,9 +387,9 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
// create a remote list from config file option list
|
||||
RemoteList(const OptionList& opt, bool warn)
|
||||
RemoteList(const OptionList& opt, const std::string& directive_prefix, const bool warn)
|
||||
{
|
||||
init();
|
||||
init(directive_prefix);
|
||||
|
||||
// handle remote, port, and proto at the top-level
|
||||
Protocol default_proto(Protocol::UDPv4);
|
||||
@ -376,7 +399,7 @@ namespace openvpn {
|
||||
// cycle through <connection> blocks
|
||||
{
|
||||
const size_t max_conn_block_size = 4096;
|
||||
const OptionList::IndexList* conn = opt.get_index_ptr("connection");
|
||||
const OptionList::IndexList* conn = opt.get_index_ptr(directives.connection);
|
||||
if (conn)
|
||||
{
|
||||
for (OptionList::IndexList::const_iterator i = conn->begin(); i != conn->end(); ++i)
|
||||
@ -427,6 +450,11 @@ namespace openvpn {
|
||||
enable_cache = enable_cache_arg;
|
||||
}
|
||||
|
||||
bool get_enable_cache() const
|
||||
{
|
||||
return enable_cache;
|
||||
}
|
||||
|
||||
// override all server hosts to server_override
|
||||
void set_server_override(const std::string& server_override)
|
||||
{
|
||||
@ -466,17 +494,17 @@ namespace openvpn {
|
||||
}
|
||||
|
||||
// Higher-level version of set_proto_override that also supports indication
|
||||
// on whether or not HTTP proxy is enabled. Should be called after set_enable_cache
|
||||
// on whether or not TCP-based proxies are enabled. Should be called after set_enable_cache
|
||||
// because it may modify enable_cache flag.
|
||||
void handle_proto_override(const Protocol& proto_override, const bool http_proxy_enabled)
|
||||
void handle_proto_override(const Protocol& proto_override, const bool tcp_proxy_enabled)
|
||||
{
|
||||
if (http_proxy_enabled)
|
||||
if (tcp_proxy_enabled)
|
||||
{
|
||||
const Protocol tcp(Protocol::TCP);
|
||||
if (contains_protocol(tcp))
|
||||
set_proto_override(tcp);
|
||||
else
|
||||
throw option_error("cannot connect via HTTP proxy because no TCP server entries exist in profile");
|
||||
throw option_error("cannot connect via TCP-based proxy because no TCP server entries exist in profile");
|
||||
}
|
||||
else if (proto_override.defined() && contains_protocol(proto_override))
|
||||
set_proto_override(proto_override);
|
||||
@ -589,9 +617,10 @@ namespace openvpn {
|
||||
|
||||
private:
|
||||
// initialization, called by constructors
|
||||
void init()
|
||||
void init(const std::string& directive_prefix)
|
||||
{
|
||||
enable_cache = false;
|
||||
directives.init(directive_prefix);
|
||||
}
|
||||
|
||||
// reset the cache associated with all items
|
||||
@ -702,24 +731,24 @@ namespace openvpn {
|
||||
{
|
||||
// parse "proto" option if present
|
||||
{
|
||||
const Option* o = opt.get_ptr("proto");
|
||||
const Option* o = opt.get_ptr(directives.proto);
|
||||
if (o)
|
||||
default_proto = Protocol::parse(o->get(1, 16), true);
|
||||
}
|
||||
|
||||
// parse "port" option if present
|
||||
{
|
||||
const Option* o = opt.get_ptr("port");
|
||||
const Option* o = opt.get_ptr(directives.port);
|
||||
if (o)
|
||||
{
|
||||
default_port = o->get(1, 16);
|
||||
validate_port(default_port, "port");
|
||||
validate_port(default_port, directives.port);
|
||||
}
|
||||
}
|
||||
|
||||
// cycle through remote entries
|
||||
{
|
||||
const OptionList::IndexList* rem = opt.get_index_ptr("remote");
|
||||
const OptionList::IndexList* rem = opt.get_index_ptr(directives.remote);
|
||||
if (rem)
|
||||
{
|
||||
for (OptionList::IndexList::const_iterator i = rem->begin(); i != rem->end(); ++i)
|
||||
@ -731,7 +760,7 @@ namespace openvpn {
|
||||
if (o.size() >= 3)
|
||||
{
|
||||
e->server_port = o.get(2, 16);
|
||||
validate_port(e->server_port, "port");
|
||||
validate_port(e->server_port, directives.port);
|
||||
}
|
||||
else
|
||||
e->server_port = default_port;
|
||||
@ -755,6 +784,8 @@ namespace openvpn {
|
||||
Index index;
|
||||
|
||||
std::vector<Item::Ptr> list;
|
||||
|
||||
Directives directives;
|
||||
};
|
||||
|
||||
}
|
||||
|
76
openvpn/transport/altproxy.hpp
Normal file
76
openvpn/transport/altproxy.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2015 OpenVPN Technologies, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_TRANSPORT_ALTPROXY_H
|
||||
#define OPENVPN_TRANSPORT_ALTPROXY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/transport/client/transbase.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
struct AltProxy : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
struct Config
|
||||
{
|
||||
Config()
|
||||
: send_queue_max_size(1024),
|
||||
free_list_max_size(8),
|
||||
socket_protect(NULL)
|
||||
{}
|
||||
|
||||
RemoteList::Ptr remote_list;
|
||||
size_t send_queue_max_size;
|
||||
size_t free_list_max_size;
|
||||
Frame::Ptr frame;
|
||||
SessionStats::Ptr stats;
|
||||
|
||||
RandomAPI::Ptr rng;
|
||||
DigestFactory::Ptr digest_factory;
|
||||
|
||||
SocketProtect* socket_protect;
|
||||
};
|
||||
|
||||
typedef boost::intrusive_ptr<AltProxy> Ptr;
|
||||
|
||||
// return proxy name
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
// called to indicate whether or not remote_list should be cached
|
||||
virtual void set_enable_cache(const bool enable_cache) = 0;
|
||||
|
||||
// return a RemoteList::Ptr (optional) to precache it
|
||||
virtual void precache(RemoteList::Ptr& r) = 0;
|
||||
|
||||
// iterate to next host in proxy-specific remote_list, return true
|
||||
// to prevent next() from being called on global remote_list
|
||||
virtual bool next() = 0;
|
||||
|
||||
// return true if this proxy method only supports TCP transport
|
||||
virtual bool requires_tcp() const = 0;
|
||||
|
||||
// return a new TransportClientFactory for this proxy
|
||||
virtual TransportClientFactory::Ptr new_transport_client_factory(const Config&) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -95,6 +95,12 @@ namespace openvpn {
|
||||
proxy_server->set_enable_cache(enable_cache);
|
||||
}
|
||||
|
||||
void proxy_server_precache(RemoteList::Ptr& r)
|
||||
{
|
||||
if (proxy_server->get_enable_cache())
|
||||
r = proxy_server;
|
||||
}
|
||||
|
||||
static Ptr parse(const OptionList& opt)
|
||||
{
|
||||
if (opt.exists("http-proxy"))
|
||||
|
40
openvpn/transport/mutate.hpp
Normal file
40
openvpn/transport/mutate.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2015 OpenVPN Technologies, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_TRANSPORT_MUTATE_H
|
||||
#define OPENVPN_TRANSPORT_MUTATE_H
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class TransportMutateStream : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
public:
|
||||
typedef boost::intrusive_ptr<TransportMutateStream> Ptr;
|
||||
|
||||
virtual void pre_send(BufferAllocated& buf) = 0;
|
||||
virtual void post_recv(BufferAllocated& buf) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -25,6 +25,7 @@
|
||||
#define OPENVPN_TRANSPORT_TCPLINK_H
|
||||
|
||||
#include <deque>
|
||||
#include <utility> // for std::move
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
@ -36,6 +37,7 @@
|
||||
#include <openvpn/frame/frame.hpp>
|
||||
#include <openvpn/log/sessionstats.hpp>
|
||||
#include <openvpn/transport/pktstream.hpp>
|
||||
#include <openvpn/transport/mutate.hpp>
|
||||
|
||||
#if defined(OPENVPN_DEBUG_TCPLINK) && OPENVPN_DEBUG_TCPLINK >= 1
|
||||
#define OPENVPN_LOG_TCPLINK_ERROR(x) OPENVPN_LOG(x)
|
||||
@ -105,6 +107,11 @@ namespace openvpn {
|
||||
return raw_mode;
|
||||
}
|
||||
|
||||
void set_mutate(const TransportMutateStream::Ptr& mutate_arg)
|
||||
{
|
||||
mutate = mutate_arg;
|
||||
}
|
||||
|
||||
bool send(BufferAllocated& b)
|
||||
{
|
||||
if (halt)
|
||||
@ -128,8 +135,12 @@ namespace openvpn {
|
||||
buf.reset(new BufferAllocated());
|
||||
buf->swap(b);
|
||||
if (!is_raw_mode())
|
||||
PacketStream::prepend_size(*buf);
|
||||
queue.push_back(buf);
|
||||
{
|
||||
PacketStream::prepend_size(*buf);
|
||||
if (mutate)
|
||||
mutate->pre_send(*buf);
|
||||
}
|
||||
queue.push_back(std::move(buf));
|
||||
if (queue.size() == 1) // send operation not currently active?
|
||||
queue_send();
|
||||
return true;
|
||||
@ -192,7 +203,7 @@ namespace openvpn {
|
||||
if (free_list.size() < free_list_max_size)
|
||||
{
|
||||
buf->reset_content();
|
||||
free_list.push_back(buf); // recycle the buffer for later use
|
||||
free_list.push_back(std::move(buf)); // recycle the buffer for later use
|
||||
}
|
||||
}
|
||||
else if (bytes_sent < buf->size())
|
||||
@ -242,10 +253,20 @@ namespace openvpn {
|
||||
pfp->buf.set_size(bytes_recvd);
|
||||
if (!is_raw_mode())
|
||||
{
|
||||
BufferAllocated pkt;
|
||||
put_pktstream(pfp->buf, pkt);
|
||||
if (!pfp->buf.allocated() && pkt.allocated()) // recycle pkt allocated buffer
|
||||
pfp->buf.move(pkt);
|
||||
try {
|
||||
BufferAllocated pkt;
|
||||
put_pktstream(pfp->buf, pkt);
|
||||
if (!pfp->buf.allocated() && pkt.allocated()) // recycle pkt allocated buffer
|
||||
pfp->buf.move(pkt);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
OPENVPN_LOG_TCPLINK_ERROR("TCP packet extract error: " << e.what());
|
||||
stats->error(Error::TCP_SIZE_ERROR);
|
||||
read_handler->tcp_error_handler("TCP_SIZE_ERROR");
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
read_handler->tcp_read_handler(pfp->buf);
|
||||
@ -271,6 +292,8 @@ namespace openvpn {
|
||||
{
|
||||
stats->inc_stat(SessionStats::BYTES_IN, buf.size());
|
||||
stats->inc_stat(SessionStats::PACKETS_IN, 1);
|
||||
if (mutate)
|
||||
mutate->post_recv(buf);
|
||||
while (buf.size())
|
||||
{
|
||||
pktstream.put(buf, frame_context);
|
||||
@ -293,6 +316,7 @@ namespace openvpn {
|
||||
Queue queue; // send queue
|
||||
Queue free_list; // recycled free buffers for send queue
|
||||
PacketStream pktstream;
|
||||
TransportMutateStream::Ptr mutate;
|
||||
};
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
1
test/ovpncli/.gitignore
vendored
1
test/ovpncli/.gitignore
vendored
@ -1 +1,2 @@
|
||||
cli
|
||||
cli.dSYM
|
||||
|
@ -189,6 +189,7 @@ int main(int argc, char *argv[])
|
||||
{ "proxy-username", required_argument, NULL, 'U' },
|
||||
{ "proxy-password", required_argument, NULL, 'W' },
|
||||
{ "proxy-basic", no_argument, NULL, 'B' },
|
||||
{ "alt-proxy", no_argument, NULL, 'A' },
|
||||
{ "eval", no_argument, NULL, 'e' },
|
||||
{ "self-test", no_argument, NULL, 'T' },
|
||||
{ "cache-password", no_argument, NULL, 'C' },
|
||||
@ -232,10 +233,11 @@ int main(int argc, char *argv[])
|
||||
bool tunPersist = false;
|
||||
bool merge = false;
|
||||
bool version = false;
|
||||
bool altProxy = false;
|
||||
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "BeTCxfgjmvu:p:r:P:s:t:c:z:h:q:U:W:k:", longopts, NULL)) != -1)
|
||||
while ((ch = getopt_long(argc, argv, "BAeTCxfgjmvu:p:r:P:s:t:c:z:h:q:U:W:k:", longopts, NULL)) != -1)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
@ -290,6 +292,9 @@ int main(int argc, char *argv[])
|
||||
case 'B':
|
||||
proxyAllowCleartextAuth = true;
|
||||
break;
|
||||
case 'A':
|
||||
altProxy = true;
|
||||
break;
|
||||
case 'f':
|
||||
forceAesCbcCiphersuites = true;
|
||||
break;
|
||||
@ -368,6 +373,7 @@ int main(int argc, char *argv[])
|
||||
config.proxyUsername = proxyUsername;
|
||||
config.proxyPassword = proxyPassword;
|
||||
config.proxyAllowCleartextAuth = proxyAllowCleartextAuth;
|
||||
config.altProxy = altProxy;
|
||||
config.defaultKeyDirection = defaultKeyDirection;
|
||||
config.forceAesCbcCiphersuites = forceAesCbcCiphersuites;
|
||||
config.googleDnsFallback = googleDnsFallback;
|
||||
|
@ -1,15 +1,15 @@
|
||||
#!/bin/bash
|
||||
[ "$NULL" = "1" ] && export GCC_EXTRA="-DOPENVPN_FORCE_TUN_NULL -DTUN_NULL_EXIT"
|
||||
[ "$NULL" = "1" ] && export GCC_EXTRA="$GCC_EXTRA -DOPENVPN_FORCE_TUN_NULL -DTUN_NULL_EXIT"
|
||||
if [ "$(uname)" == "Darwin" ]; then
|
||||
cd $O3/core
|
||||
. vars/vars-osx64
|
||||
. vars/setpath
|
||||
cd test/ovpncli
|
||||
PSSL=1 SNAP=1 LZ4=1 build cli 2>&1
|
||||
PSSL=1 SNAP=1 LZ4=1 PTPROXY=1 build cli 2>&1
|
||||
else
|
||||
cd $O3/core
|
||||
. vars/vars-linux
|
||||
. vars/setpath
|
||||
cd test/ovpncli
|
||||
PSSL=1 SNAP=1 LZ4=1 NOSSL=1 build cli 2>&1
|
||||
PSSL=1 SNAP=1 LZ4=1 NOSSL=1 PTPROXY=1 build cli 2>&1
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user