0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 04:02:15 +02:00
openvpn3/openvpn/ssl/tlsver.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

125 lines
3.7 KiB
C++
Raw Normal View History

// 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-2022 OpenVPN 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/>.
// Parse the tls-version-min option.
#pragma once
#include <string>
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/options.hpp>
namespace openvpn::TLSVersion {
enum class Type
{
UNDEF,
V1_0,
V1_1,
V1_2,
V1_3
};
inline bool operator<(const Type &A, const Type &B)
{
return static_cast<int>(A) < static_cast<int>(B);
}
inline const std::string to_string(const Type version)
{
switch (version)
{
case Type::UNDEF:
return "UNDEF";
case Type::V1_0:
return "V1_0";
case Type::V1_1:
return "V1_1";
case Type::V1_2:
return "V1_2";
case Type::V1_3:
return "V1_3";
default:
return "???";
}
}
inline Type parse_tls_version_min(const std::string &ver,
const bool or_highest,
const Type max_version)
{
if (ver == "1.0" && Type::V1_0 <= max_version)
return Type::V1_0;
else if (ver == "1.1" && Type::V1_1 <= max_version)
return Type::V1_1;
else if (ver == "1.2" && Type::V1_2 <= max_version)
return Type::V1_2;
else if (ver == "1.3" && Type::V1_3 <= max_version)
return Type::V1_3;
else if (or_highest)
return max_version;
else
throw option_error("tls-version-min: unrecognized TLS version");
}
Added Relay capability, a kind of proxy function similar to HTTP CONNECT but implemented over the OpenVPN protocol. 1. Client connects to relay server as if it were connecting to an ordinary OpenVPN server. 2. Client authenticates to relay server using its client certificate. 3. Client sends a PUSH_REQUEST method to relay server which then replies with a RELAY message instead of PUSH_REPLY. 4. On receiving the RELAY message, the client attempts to reconnect using the existing transport socket. The server will proxy this new connection (at the transport layer) to a second server (chosen by the relay server) that is the target of proxy. 5. The client must establish and authenticate a new session from scratch with the target server, only reusing the transport layer socket from the original connection to the relay server. 6. The relay acts as a man-in-the-middle only at the transport layer (like most proxies), i.e. it forwards the encrypted session between client and target server without decrypting or having the capability to decrypt the session. 7. The client is designed to protect against potentially untrusted or malicious relays: (a) The client never transmits the target server username/password credentials to the relay server. (b) The relay forwards the encrypted OpenVPN session between client and target server without having access to the session keys. (c) The client configuration has a special directive for relay server CA (<relay-extra-ca>) and relay server tls-auth key (<relay-tls-auth>) to allow for separation of TLS/crypto configuration between relay and target servers. (d) The client will reject any PUSH_REPLY messages from the relay itself to prevent the relay from trying to establish a tunnel directly with the client. Example configuring a client for relay: # remote addresses point to the relay server remote ... 1194 udp remote ... 443 tcp # include all other directives for connecting # to the target server # enable relay mode relay-mode # constrain the relay server's cert type relay-ns-cert-type server # include extra CAs that validate the relay # server cert (optional). <relay-extra-ca> -----BEGIN CERTIFICATE----- . . . -----END CERTIFICATE----- </relay-extra-ca> # specify the TLS auth key for the relay server relay-key-direction 1 <relay-tls-auth> -----BEGIN OpenVPN Static key V1----- . . . -----END OpenVPN Static key V1----- </relay-tls-auth>
2016-11-20 21:06:35 +01:00
inline Type parse_tls_version_min(const OptionList &opt,
const std::string &relay_prefix,
const Type max_version)
{
Added Relay capability, a kind of proxy function similar to HTTP CONNECT but implemented over the OpenVPN protocol. 1. Client connects to relay server as if it were connecting to an ordinary OpenVPN server. 2. Client authenticates to relay server using its client certificate. 3. Client sends a PUSH_REQUEST method to relay server which then replies with a RELAY message instead of PUSH_REPLY. 4. On receiving the RELAY message, the client attempts to reconnect using the existing transport socket. The server will proxy this new connection (at the transport layer) to a second server (chosen by the relay server) that is the target of proxy. 5. The client must establish and authenticate a new session from scratch with the target server, only reusing the transport layer socket from the original connection to the relay server. 6. The relay acts as a man-in-the-middle only at the transport layer (like most proxies), i.e. it forwards the encrypted session between client and target server without decrypting or having the capability to decrypt the session. 7. The client is designed to protect against potentially untrusted or malicious relays: (a) The client never transmits the target server username/password credentials to the relay server. (b) The relay forwards the encrypted OpenVPN session between client and target server without having access to the session keys. (c) The client configuration has a special directive for relay server CA (<relay-extra-ca>) and relay server tls-auth key (<relay-tls-auth>) to allow for separation of TLS/crypto configuration between relay and target servers. (d) The client will reject any PUSH_REPLY messages from the relay itself to prevent the relay from trying to establish a tunnel directly with the client. Example configuring a client for relay: # remote addresses point to the relay server remote ... 1194 udp remote ... 443 tcp # include all other directives for connecting # to the target server # enable relay mode relay-mode # constrain the relay server's cert type relay-ns-cert-type server # include extra CAs that validate the relay # server cert (optional). <relay-extra-ca> -----BEGIN CERTIFICATE----- . . . -----END CERTIFICATE----- </relay-extra-ca> # specify the TLS auth key for the relay server relay-key-direction 1 <relay-tls-auth> -----BEGIN OpenVPN Static key V1----- . . . -----END OpenVPN Static key V1----- </relay-tls-auth>
2016-11-20 21:06:35 +01:00
const Option *o = opt.get_ptr(relay_prefix + "tls-version-min");
if (o)
{
const std::string ver = o->get_optional(1, 16);
const bool or_highest = (o->get_optional(2, 16) == "or-highest");
return parse_tls_version_min(ver, or_highest, max_version);
}
return Type::UNDEF;
}
inline void apply_override(Type &tvm, const std::string &override)
{
const Type orig = tvm;
Type newtvm = Type::UNDEF;
if (override.empty() || override == "default")
newtvm = tvm;
else if (override == "disabled")
tvm = Type::UNDEF;
else if (override == "tls_1_0")
newtvm = Type::V1_0;
else if (override == "tls_1_1")
newtvm = Type::V1_1;
else if (override == "tls_1_2")
newtvm = Type::V1_2;
else if (override == "tls_1_3")
newtvm = Type::V1_3;
else
throw option_error("tls-version-min: unrecognized override string");
if (newtvm > orig || newtvm == Type::UNDEF)
tvm = newtvm;
// OPENVPN_LOG("*** TLS-version-min before=" << to_string(orig) << " override=" << override << " after=" << to_string(tvm)); // fixme
}
} // namespace openvpn::TLSVersion