mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
fix handling of --proto option
Make it possible to enforce the protocol family by appending 4/6 to to the protocol, e.g. tcp6 or udp4. While it is already possible to have protocol options like these in the configuration, they are not enforced so far. Thus you could still be connected to a v6 address even though the config requested v4 only. Since v2.3 the openvpn 2.x series behaves like this. So, this is also to catch up with the behavior there. Signed-off-by: Heiko Hund <heiko@openvpn.net>
This commit is contained in:
parent
69ed0a6f10
commit
f1bdbe5088
@ -153,6 +153,10 @@ namespace openvpn {
|
||||
res_addr_list.reset(new ResolvedAddrList());
|
||||
for (const auto &i : endpoint_range)
|
||||
{
|
||||
// Skip addresses with incompatible family
|
||||
if ((transport_protocol.is_ipv6() && i.endpoint().address().is_v4())
|
||||
|| (transport_protocol.is_ipv4() && i.endpoint().address().is_v6()))
|
||||
continue;
|
||||
ResolvedAddr::Ptr addr(new ResolvedAddr());
|
||||
addr->addr = IP::Addr::from_asio(i.endpoint().address());
|
||||
res_addr_list->push_back(addr);
|
||||
@ -316,21 +320,10 @@ namespace openvpn {
|
||||
if (!item.res_addr_list_defined())
|
||||
{
|
||||
// next item to resolve
|
||||
const Item* sitem = remote_list->search_server_host(item.server_host);
|
||||
if (sitem)
|
||||
{
|
||||
// item's server_host matches one previously resolved -- use it
|
||||
OPENVPN_LOG_REMOTELIST("*** PreResolve USED CACHE for " << sitem.actual_host());
|
||||
item.res_addr_list = sitem->res_addr_list;
|
||||
item.random_host = sitem->random_host;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string& host = item.actual_host();
|
||||
OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << host << " : " << item.server_port);
|
||||
async_resolve_name(host, item.server_port);
|
||||
return;
|
||||
}
|
||||
const std::string& host = item.actual_host();
|
||||
OPENVPN_LOG_REMOTELIST("*** PreResolve RESOLVE on " << host << " : " << item.server_port);
|
||||
async_resolve_name(host, item.server_port);
|
||||
return;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
@ -354,17 +347,27 @@ namespace openvpn {
|
||||
{
|
||||
if (notify_callback && index < remote_list->list.size())
|
||||
{
|
||||
Item& item = *remote_list->list[index++];
|
||||
const auto resolve_item(remote_list->list[index++]);
|
||||
if (!error)
|
||||
{
|
||||
// resolve succeeded
|
||||
// Set results to Items, where applicable
|
||||
auto rand = remote_list->random ? remote_list->rng.get() : nullptr;
|
||||
item.set_endpoint_range(results, rand);
|
||||
for (auto& item : remote_list->list)
|
||||
{
|
||||
// Skip already resolved items and items with different hostname
|
||||
if (item->res_addr_list_defined()
|
||||
|| item->server_host != resolve_item->server_host)
|
||||
continue;
|
||||
|
||||
item->set_endpoint_range(results, rand);
|
||||
item->random_host = resolve_item->random_host;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// resolve failed
|
||||
OPENVPN_LOG("DNS pre-resolve error on " << item.actual_host() << ": " << error.message());
|
||||
OPENVPN_LOG("DNS pre-resolve error on " << resolve_item->actual_host()
|
||||
<< ": " << error.message());
|
||||
if (stats)
|
||||
stats->error(Error::RESOLVE_ERROR);
|
||||
}
|
||||
@ -739,18 +742,6 @@ namespace openvpn {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Search for cached Item by server_host
|
||||
Item* search_server_host(const std::string& server_host)
|
||||
{
|
||||
for (std::vector<Item::Ptr>::iterator i = list.begin(); i != list.end(); ++i)
|
||||
{
|
||||
Item* item = i->get();
|
||||
if (server_host == item->server_host && item->res_addr_list_defined())
|
||||
return item;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return true if at least one remote entry is of type proto
|
||||
bool contains_protocol(const Protocol& proto)
|
||||
{
|
||||
|
@ -46,9 +46,9 @@ namespace openvpn {
|
||||
UnixStream, // unix domain socket (stream)
|
||||
UnixDGram, // unix domain socket (datagram)
|
||||
NamedPipe, // named pipe (Windows only)
|
||||
UDP=UDPv4,
|
||||
TCP=TCPv4,
|
||||
TLS=TLSv4,
|
||||
UDP,
|
||||
TCP,
|
||||
TLS,
|
||||
};
|
||||
|
||||
enum AllowSuffix {
|
||||
@ -65,10 +65,11 @@ namespace openvpn {
|
||||
|
||||
void reset() { type_ = NONE; }
|
||||
|
||||
bool is_udp() const { return type_ == UDPv4 || type_ == UDPv6; }
|
||||
bool is_tcp() const { return type_ == TCPv4 || type_ == TCPv6; }
|
||||
bool is_tls() const { return type_ == TLSv4 || type_ == TLSv6; }
|
||||
bool is_udp() const { return type_ == UDP || type_ == UDPv4 || type_ == UDPv6; }
|
||||
bool is_tcp() const { return type_ == TCP || type_ == TCPv4 || type_ == TCPv6; }
|
||||
bool is_tls() const { return type_ == TLS || type_ == TLSv4 || type_ == TLSv6; }
|
||||
bool is_reliable() const { return is_tcp() || is_tls(); }
|
||||
bool is_ipv4() const { return type_ == UDPv4 || type_ == TCPv4 || type_ == TLSv4; }
|
||||
bool is_ipv6() const { return type_ == UDPv6 || type_ == TCPv6 || type_ == TLSv6; }
|
||||
bool is_unix() const { return type_ == UnixStream || type_ == UnixDGram; }
|
||||
bool is_named_pipe() const { return type_ == NamedPipe; }
|
||||
@ -151,12 +152,12 @@ namespace openvpn {
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case UDP:
|
||||
case UDPv4:
|
||||
return 0;
|
||||
case TCPv4:
|
||||
return 1;
|
||||
case UDPv6:
|
||||
return 0;
|
||||
case TCP:
|
||||
case TCPv4:
|
||||
case TCPv6:
|
||||
return 1;
|
||||
case UnixDGram:
|
||||
@ -165,6 +166,7 @@ namespace openvpn {
|
||||
return 3;
|
||||
case NamedPipe:
|
||||
return 4;
|
||||
case TLS:
|
||||
case TLSv4:
|
||||
case TLSv6:
|
||||
return 5;
|
||||
@ -177,14 +179,20 @@ namespace openvpn {
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case UDP:
|
||||
return "UDP";
|
||||
case UDPv4:
|
||||
return "UDPv4";
|
||||
case TCPv4:
|
||||
return "TCPv4";
|
||||
case UDPv6:
|
||||
return "UDPv6";
|
||||
case TCP:
|
||||
return "TCP";
|
||||
case TCPv4:
|
||||
return "TCPv4";
|
||||
case TCPv6:
|
||||
return "TCPv6";
|
||||
case TLS:
|
||||
return "TLS/TCP";
|
||||
case TLSv4:
|
||||
return "TLS/TCPv4";
|
||||
case TLSv6:
|
||||
@ -206,14 +214,20 @@ namespace openvpn {
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case UDP:
|
||||
return "udp";
|
||||
case UDPv4:
|
||||
return "udp4";
|
||||
case TCPv4:
|
||||
return "tcp4";
|
||||
case UDPv6:
|
||||
return "udp6";
|
||||
case TCP:
|
||||
return "tcp";
|
||||
case TCPv4:
|
||||
return "tcp4";
|
||||
case TCPv6:
|
||||
return "tcp6";
|
||||
case TLS:
|
||||
return "tls";
|
||||
case TLSv4:
|
||||
return "tls4";
|
||||
case TLSv6:
|
||||
@ -235,14 +249,20 @@ namespace openvpn {
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
case UDP:
|
||||
return "UDP";
|
||||
case UDPv4:
|
||||
return "UDPv4";
|
||||
case TCPv4:
|
||||
return "TCPv4_CLIENT";
|
||||
case UDPv6:
|
||||
return force_ipv4 ? "UDPv4" : "UDPv6";
|
||||
case TCP:
|
||||
return "TCP_CLIENT";
|
||||
case TCPv4:
|
||||
return "TCPv4_CLIENT";
|
||||
case TCPv6:
|
||||
return force_ipv4 ? "TCPv4_CLIENT" : "TCPv6_CLIENT";
|
||||
case TLS:
|
||||
return "TLS";
|
||||
case TLSv4:
|
||||
return "TLSv4";
|
||||
case TLSv6:
|
||||
@ -281,11 +301,20 @@ namespace openvpn {
|
||||
}
|
||||
else if (s == "named-pipe") // Windows named pipe
|
||||
ret = NamedPipe;
|
||||
else if (s.length() >= 3) // udp/tcp
|
||||
else if (s.length() >= 3) // udp/tcp/tls
|
||||
{
|
||||
const std::string s1 = s.substr(0, 3);
|
||||
const std::string s2 = s.substr(3);
|
||||
if (s2 == "" || s2 == "4" || s2 == "v4")
|
||||
if (s2 == "")
|
||||
{
|
||||
if (s1 == "udp")
|
||||
ret = UDP;
|
||||
else if (s1 == "tcp")
|
||||
ret = TCP;
|
||||
else if (s1 == "tls")
|
||||
ret = TLS;
|
||||
}
|
||||
else if (s2 == "4" || s2 == "v4")
|
||||
{
|
||||
if (s1 == "udp")
|
||||
ret = UDPv4;
|
||||
|
@ -113,7 +113,7 @@ TEST(RemoteList, CtorRemoteList)
|
||||
ASSERT_EQ(rl.get_item(0).transport_protocol, Protocol(Protocol::TCPv6));
|
||||
ASSERT_EQ(rl.get_item(1).server_host, "1.domain.invalid");
|
||||
ASSERT_EQ(rl.get_item(1).server_port, "1111");
|
||||
ASSERT_EQ(rl.get_item(1).transport_protocol, Protocol(Protocol::UDPv4));
|
||||
ASSERT_EQ(rl.get_item(1).transport_protocol, Protocol(Protocol::UDP));
|
||||
ASSERT_EQ(rl.get_item(2).server_host, "2.domain.invalid");
|
||||
ASSERT_EQ(rl.get_item(2).server_port, "8888");
|
||||
ASSERT_EQ(rl.get_item(2).transport_protocol, Protocol(Protocol::TCPv6));
|
||||
@ -234,8 +234,8 @@ TEST(RemoteList, RemoteListPreResolve)
|
||||
"remote 1.1.1.1 1111 udp\n"
|
||||
"remote 2:cafe::1 2222 tcp\n"
|
||||
"remote 3.domain.tld 3333 udp4\n"
|
||||
"remote 3.domain.tld 33333 udp6\n"
|
||||
"remote 4.domain.tld 4444 udp4\n"
|
||||
"remote 3.domain.tld 33333 udp\n"
|
||||
"remote 4.domain.tld 4444 udp6\n"
|
||||
"remote 5.noresolve.tld 5555 udp4\n"
|
||||
, nullptr);
|
||||
cfg.update_map();
|
||||
@ -277,18 +277,16 @@ TEST(RemoteList, RemoteListPreResolve)
|
||||
ASSERT_EQ(rl->get_item(1).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(1).res_addr_list->at(0)->to_string(), "2:cafe::1");
|
||||
ASSERT_EQ(rl->get_item(2).res_addr_list_defined(), true);
|
||||
ASSERT_EQ(rl->get_item(2).res_addr_list->size(), 2);
|
||||
ASSERT_EQ(rl->get_item(2).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(2).res_addr_list->at(0)->to_string(), "3.3.3.3");
|
||||
ASSERT_EQ(rl->get_item(2).res_addr_list->at(1)->to_string(), "3::3");
|
||||
ASSERT_EQ(rl->get_item(3).res_addr_list_defined(), true);
|
||||
ASSERT_EQ(rl->get_item(3).res_addr_list->size(), 2);
|
||||
ASSERT_EQ(rl->get_item(3).res_addr_list->at(0)->to_string(), "3.3.3.3");
|
||||
ASSERT_EQ(rl->get_item(3).res_addr_list->at(1)->to_string(), "3::3");
|
||||
ASSERT_EQ(rl->get_item(3).actual_host(), rl->get_item(2).actual_host());
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list_defined(), true);
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list->size(), 2);
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list->at(0)->to_string(), "4.4.4.4");
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list->at(1)->to_string(), "4::4");
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(4).res_addr_list->at(0)->to_string(), "4::4");
|
||||
|
||||
// in case it gets randomized before the other 3.domain.tld
|
||||
fake_preres.set_results("3.domain.tld", "33333", { {"3.3.3.3", 33333}, {"3::3", 33333} });
|
||||
@ -317,8 +315,23 @@ TEST(RemoteList, RemoteListPreResolve)
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->at(0)->to_string(), "2:cafe::1");
|
||||
}
|
||||
else
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->size(), 2);
|
||||
else if (rl->get_item(i).server_host[0] == '3')
|
||||
{
|
||||
if (rl->get_item(i).transport_protocol.is_ipv4())
|
||||
{
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->at(0)->to_string(), "3.3.3.3");
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->size(), 2);
|
||||
}
|
||||
}
|
||||
else if (rl->get_item(i).server_host[0] == '4')
|
||||
{
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->size(), 1);
|
||||
ASSERT_EQ(rl->get_item(i).res_addr_list->at(0)->to_string(), "4::4");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i=0; i < rl->size(); ++i)
|
||||
@ -331,8 +344,10 @@ TEST(RemoteList, RemoteListPreResolve)
|
||||
ASSERT_EQ(rl->endpoint_available(&host, &port, &proto), true);
|
||||
ASSERT_EQ(rl->get_item(i).actual_host(), host);
|
||||
ASSERT_EQ(rl->get_item(i).server_port, port);
|
||||
// proto is not yet honored by Item when adding resolver results
|
||||
//ASSERT_EQ(rl->current_transport_protocol(), proto);
|
||||
if (rl->current_transport_protocol().is_ipv4()
|
||||
|| rl->current_transport_protocol().is_ipv6()) {
|
||||
ASSERT_EQ(rl->current_transport_protocol(), proto);
|
||||
}
|
||||
|
||||
auto ep1 = fake_preres.init_endpoint();
|
||||
auto ep2 = fake_preres.init_endpoint();
|
||||
|
Loading…
Reference in New Issue
Block a user