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

Rework block-ipv6 to also allow blocking ipv4 and remove IV_IPV6

Since IPv4/IPv6 should be treated equally, we should have also
the opportunity to block IPv4. With this change we follow the API
that also Android provides and expliticly tell tunbuilder what to
do with address families that are not used by the VPN. If a
address family is used by the VPN, nothing changes.

This also remove IV_IPV6 as it is not used.
This commit is contained in:
Arne Schwabe 2021-09-23 14:27:47 +02:00 committed by David Sommerseth
parent 6bb4e9c7be
commit 88b2906a2c
No known key found for this signature in database
GPG Key ID: 86CF944C9671FDF2
8 changed files with 58 additions and 44 deletions

View File

@ -434,7 +434,7 @@ namespace openvpn {
std::string port_override;
Protocol proto_override;
IP::Addr::Version proto_version_override;
IPv6Setting ipv6;
TriStateSetting allowUnusedAddrFamilies;
int conn_timeout = 0;
bool tun_persist = false;
bool wintun = false;
@ -628,8 +628,8 @@ namespace openvpn {
Protocol::parse(config.protoOverride, Protocol::NO_SUFFIX);
// validate IPv6 setting
if (!config.ipv6.empty())
IPv6Setting::parse(config.ipv6);
if (!config.allowUnusedAddrFamilies.empty())
TriStateSetting::parse(config.allowUnusedAddrFamilies);
// parse config
OptionList::KeyValueList kvl;
@ -696,8 +696,8 @@ namespace openvpn {
state->proto_version_override = IP::Addr::Version::V4;
else if (config.protoVersionOverride == 6)
state->proto_version_override = IP::Addr::Version::V6;
if (!config.ipv6.empty())
state->ipv6 = IPv6Setting::parse(config.ipv6);
if (!config.allowUnusedAddrFamilies.empty())
state->allowUnusedAddrFamilies = TriStateSetting::parse(config.allowUnusedAddrFamilies);
if (!config.compressionMode.empty())
state->proto_context_options->parse_compression_mode(config.compressionMode);
if (eval.externalPki)
@ -970,7 +970,7 @@ namespace openvpn {
cc.port_override = state->port_override;
cc.proto_override = state->proto_override;
cc.proto_version_override = state->proto_version_override;
cc.ipv6 = state->ipv6;
cc.allowUnusedAddrFamilies = state->allowUnusedAddrFamilies;
cc.conn_timeout = state->conn_timeout;
cc.tun_persist = state->tun_persist;
cc.wintun = state->wintun;

View File

@ -206,11 +206,11 @@ namespace openvpn {
// Should be 4 for IPv4 or 6 for IPv6.
int protoVersionOverride = 0;
// IPv6 preference
// no -- disable IPv6, so tunnel will be IPv4-only
// yes -- request combined IPv4/IPv6 tunnel
// default (or empty string) -- leave decision to server
std::string ipv6;
// allowUnusedAddrFamilies preference
// no -- disable IPv6/IPv4, so tunnel will be IPv4 or IPv6 only if not dualstack
// yes -- Allow continuing using native IPv4/IPv6 connectivity for single IP family tunnel
// default (or empty string) -- leave decision to server/config
std::string allowUnusedAddrFamilies;
// Connection timeout in seconds, or 0 to retry indefinitely
int connTimeout = 0;

View File

@ -41,7 +41,7 @@
#include <openvpn/crypto/cryptodcsel.hpp>
#include <openvpn/ssl/mssparms.hpp>
#include <openvpn/tun/tunmtu.hpp>
#include <openvpn/tun/ipv6_setting.hpp>
#include <openvpn/tun/tristate_setting.hpp>
#include <openvpn/netconf/hwaddr.hpp>
#include <openvpn/transport/socket_protect.hpp>
@ -127,7 +127,7 @@ namespace openvpn {
std::string platform_version;
Protocol proto_override;
IP::Addr::Version proto_version_override = IP::Addr::Version::UNSPEC;
IPv6Setting ipv6;
TriStateSetting allowUnusedAddrFamilies;
int conn_timeout = 0;
SessionStats::Ptr cli_stats;
ClientEvent::Queue::Ptr cli_events;
@ -528,9 +528,18 @@ namespace openvpn {
// IPv6
{
const unsigned int n = push_base->singleton.extend(opt, "block-ipv6");
if (!n && config.ipv6() == IPv6Setting::No)
push_base->singleton.emplace_back("block-ipv6");
const unsigned int n6 = push_base->singleton.extend(opt, "block-ipv6");
const unsigned int n4 = push_base->singleton.extend(opt, "block-ipv4");
if (!n6 && config.allowUnusedAddrFamilies() == TriStateSetting::No)
{
push_base->singleton.emplace_back("block-ipv6");
}
if (!n4 && config.allowUnusedAddrFamilies() == TriStateSetting::No)
{
push_base->singleton.emplace_back("block-ipv4");
}
}
}
@ -542,12 +551,6 @@ namespace openvpn {
{
PeerInfo::Set::Ptr pi(new PeerInfo::Set);
// IPv6
if (config.ipv6() == IPv6Setting::No)
pi->emplace_back("IV_IPv6", "0");
else if (config.ipv6() == IPv6Setting::Yes)
pi->emplace_back("IV_IPv6", "1");
// autologin sessions
if (autologin_sessions)
pi->emplace_back("IV_AUTO_SESS", "1");

View File

@ -195,11 +195,16 @@ namespace openvpn {
return false;
}
// Optional callback that indicates whether IPv6 traffic should be
// blocked, to prevent unencrypted IPv6 packet leakage when the
// tunnel is IPv4-only, but the local machine has IPv6 connectivity
// to the internet. Enabled by "block-ipv6" config var.
virtual bool tun_builder_set_block_ipv6(bool block_ipv6)
// Optional callback that indicates whether traffic of a certain
// address family (AF_INET or AF_INET6) should be
// blocked or allowed, to prevent unencrypted packet leakage when
// the tunnel is IPv4-only/IPv6-only, but the local machine
// has connectivity with the other protocol to the internet.
// Controlled by "block-ipv6" and block-ipv6 config var.
// If addresses are added for a family this setting should be
// ignored for that family
// See also Android's VPNService.Builder.allowFamily method
virtual bool tun_builder_set_allow_family(int af, bool allow)
{
return true;
}

View File

@ -580,9 +580,12 @@ namespace openvpn {
return true;
}
virtual bool tun_builder_set_block_ipv6(bool value) override
virtual bool tun_builder_set_allow_family(int af, bool value) override
{
block_ipv6 = value;
if (af == AF_INET)
block_ipv4 = value;
else if (af == AF_INET6)
block_ipv6 = value;
return true;
}
@ -655,6 +658,7 @@ namespace openvpn {
os << "Remote Address: " << remote_address.to_string() << std::endl;
render_list(os, "Tunnel Addresses", tunnel_addresses);
os << "Reroute Gateway: " << reroute_gw.to_string() << std::endl;
os << "Block IPv4: " << (block_ipv4 ? "yes" : "no") << std::endl;
os << "Block IPv6: " << (block_ipv6 ? "yes" : "no") << std::endl;
if (route_metric_default >= 0)
os << "Route Metric Default: " << route_metric_default << std::endl;
@ -748,6 +752,7 @@ namespace openvpn {
int tunnel_address_index_ipv4 = -1; // index into tunnel_addresses for IPv4 entry (or -1 if undef)
int tunnel_address_index_ipv6 = -1; // index into tunnel_addresses for IPv6 entry (or -1 if undef)
RerouteGW reroute_gw; // redirect-gateway info
bool block_ipv4 = false; // block IPv4 traffic while VPN is active
bool block_ipv6 = false; // block IPv6 traffic while VPN is active
int route_metric_default = -1; // route-metric directive
std::vector<Route> add_routes; // routes that should be added to tunnel

View File

@ -168,8 +168,9 @@ namespace openvpn {
// add DNS servers and domain prefixes
const unsigned int dhcp_option_flags = add_dhcp_options(tb, opt, quiet);
// Block IPv6?
tb->tun_builder_set_block_ipv6(opt.exists("block-ipv6"));
// Block protocols if explicitly requested
tb->tun_builder_set_allow_family(AF_INET, opt.exists("block-ipv4"));
tb->tun_builder_set_allow_family(AF_INET6, opt.exists("block-ipv6"));
// DNS fallback
if (ipv.rgv4() && !(dhcp_option_flags & F_ADD_DNS))

View File

@ -25,7 +25,7 @@
#include <openvpn/common/exception.hpp>
namespace openvpn {
class IPv6Setting
class TriStateSetting
{
public:
enum Type {
@ -34,11 +34,11 @@ namespace openvpn {
Default,
};
IPv6Setting()
TriStateSetting()
{
}
explicit IPv6Setting(const Type t)
explicit TriStateSetting(const Type t)
: type_(t)
{
}
@ -59,24 +59,24 @@ namespace openvpn {
}
}
static IPv6Setting parse(const std::string& str)
static TriStateSetting parse(const std::string& str)
{
if (str == "no")
return IPv6Setting(No);
return TriStateSetting(No);
else if (str == "yes")
return IPv6Setting(Yes);
return TriStateSetting(Yes);
else if (str == "default")
return IPv6Setting(Default);
return TriStateSetting(Default);
else
throw Exception("IPv6Setting: unrecognized setting: '" + str + '\'');
}
bool operator==(const IPv6Setting& other) const
bool operator==(const TriStateSetting& other) const
{
return type_ == other.type_;
}
bool operator!=(const IPv6Setting& other) const
bool operator!=(const TriStateSetting& other) const
{
return type_ != other.type_;
}

View File

@ -856,7 +856,7 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
std::string response;
std::string dynamicChallengeCookie;
std::string proto;
std::string ipv6;
std::string allowUnusedAddrFamilies;
std::string server;
std::string port;
int timeout = 0;
@ -945,7 +945,7 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
proto = optarg;
break;
case '6':
ipv6 = optarg;
allowUnusedAddrFamilies = optarg;
break;
case 's':
server = optarg;
@ -1096,7 +1096,7 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
config.protoOverride = proto;
config.connTimeout = timeout;
config.compressionMode = compress;
config.ipv6 = ipv6;
config.allowUnusedAddrFamilies = allowUnusedAddrFamilies;
config.privateKeyPassword = privateKeyPassword;
config.tlsVersionMinOverride = tlsVersionMinOverride;
config.tlsCertProfileOverride = tlsCertProfileOverride;
@ -1290,7 +1290,7 @@ int openvpn_client(int argc, char *argv[], const std::string* profile_content)
#ifdef OPENVPN_REMOTE_OVERRIDE
std::cout << "--remote-override : command to run to generate next remote (returning host,ip,port,proto)" << std::endl;
#endif
std::cout << "--ipv6, -6 : IPv6 (yes|no|default)" << std::endl;
std::cout << "--allowAF, -6 : Allow unused Adrress families (yes|no|default)" << std::endl;
std::cout << "--timeout, -t : timeout" << std::endl;
std::cout << "--compress, -c : compression mode (yes|no|asym)" << std::endl;
std::cout << "--pk-password, -z : private key password" << std::endl;