|
From: its_Giaan (C. Review) <ge...@op...> - 2025-09-29 09:36:52
|
Attention is currently required from: flichtenheld, its_Giaan.
Hello cron2, flichtenheld, plaisthos,
I'd like you to reexamine a change. Please visit
http://gerrit.openvpn.net/c/openvpn/+/1089?usp=email
to look at the new patch set (#3).
Change subject: multipeer: introduce asymmetric peer-id
......................................................................
multipeer: introduce asymmetric peer-id
In order to achieve a multipeer functionality, peers now
use separate IDs for sending (tx_peer_id) and receiving
(rx_peer_id).
Each peer announces its own ID through pushing peer-info
using 'ID=7f1' hex format so identification can still
happen even if IP/port changes.
In P2P mode, peer switch to using the announced IDs after
mutual exchange.
In P2MP mode, clients always announce their ID, and servers
can optionally respond with their own to enable the same
behavior.
Change-Id: I0a13ee90b6706acf20eabcee3bab3f2dff639bf9
Signed-off-by: Gianmarco De Gregori <gia...@ma...>
---
M src/openvpn/dco.c
M src/openvpn/init.c
M src/openvpn/misc.c
M src/openvpn/multi.c
M src/openvpn/push.c
M src/openvpn/push_util.c
M src/openvpn/ssl.c
M src/openvpn/ssl_common.h
M src/openvpn/ssl_ncp.c
M src/openvpn/ssl_util.c
M src/openvpn/ssl_util.h
11 files changed, 104 insertions(+), 41 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/89/1089/3
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
index 6afc680..eb600f0 100644
--- a/src/openvpn/dco.c
+++ b/src/openvpn/dco.c
@@ -514,14 +514,15 @@
c->c2.tls_multi->dco_peer_id = -1;
}
#endif
- int ret = dco_new_peer(&c->c1.tuntap->dco, multi->peer_id, sock->sd, NULL,
- proto_is_dgram(sock->info.proto) ? remoteaddr : NULL, NULL, NULL);
+ int ret = dco_new_peer(&c->c1.tuntap->dco, multi->rx_peer_id, sock->sd, NULL,
+ proto_is_dgram(sock->info.proto) ? remoteaddr : NULL,
+ NULL, NULL);
if (ret < 0)
{
return ret;
}
- c->c2.tls_multi->dco_peer_id = multi->peer_id;
+ c->c2.tls_multi->dco_peer_id = multi->rx_peer_id;
return 0;
}
@@ -596,7 +597,7 @@
{
struct context *c = &mi->context;
- int peer_id = c->c2.tls_multi->peer_id;
+ int peer_id = c->c2.tls_multi->rx_peer_id;
struct sockaddr *remoteaddr, *localaddr = NULL;
struct sockaddr_storage local = { 0 };
const socket_descriptor_t sd = c->c2.link_sockets[0]->sd;
@@ -667,8 +668,7 @@
if (addrtype == MR_ADDR_IPV6)
{
#if defined(_WIN32)
- dco_win_add_iroute_ipv6(&c->c1.tuntap->dco, addr->v6.addr, addr->netbits,
- c->c2.tls_multi->peer_id);
+ dco_win_add_iroute_ipv6(&c->c1.tuntap->dco, addr->v6.addr, addr->netbits, c->c2.tls_multi->rx_peer_id);
#else
net_route_v6_add(&m->top.net_ctx, &addr->v6.addr, addr->netbits,
&mi->context.c2.push_ifconfig_ipv6_local, c->c1.tuntap->actual_name, 0,
@@ -678,8 +678,7 @@
else if (addrtype == MR_ADDR_IPV4)
{
#if defined(_WIN32)
- dco_win_add_iroute_ipv4(&c->c1.tuntap->dco, addr->v4.addr, addr->netbits,
- c->c2.tls_multi->peer_id);
+ dco_win_add_iroute_ipv4(&c->c1.tuntap->dco, addr->v4.addr, addr->netbits, c->c2.tls_multi->rx_peer_id);
#else
in_addr_t dest = htonl(addr->v4.addr);
net_route_v4_add(&m->top.net_ctx, &dest, addr->netbits, &mi->context.c2.push_ifconfig_local,
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index f8a0fee..fa841b9 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2223,7 +2223,7 @@
if (o->use_peer_id)
{
- buf_printf(&out, ", peer-id: %d", o->peer_id);
+ buf_printf(&out, ", rx_peer-id: %u, tx_peer-id: %u", c->c2.tls_multi->rx_peer_id, c->c2.tls_multi->tx_peer_id);
}
#ifdef USE_COMP
@@ -2702,7 +2702,7 @@
{
msg(D_PUSH_DEBUG, "OPTIONS IMPORT: peer-id set");
c->c2.tls_multi->use_peer_id = true;
- c->c2.tls_multi->peer_id = c->options.peer_id;
+ c->c2.tls_multi->tx_peer_id = c->options.peer_id;
}
/* process (potentially) pushed options */
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index caf4725..91ab391 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -765,7 +765,8 @@
{
chomp(line);
if (validate_peer_info_line(line)
- && (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0))
+ && (strncmp(line, "IV_", 3) == 0 || strncmp(line, "UV_", 3) == 0
+ || strncmp(line, "ID", 2) == 0))
{
msg(M_INFO, "peer info: %s", line);
env_set_add(es, line);
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index 2863ff1..bc8cc7b 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -453,7 +453,7 @@
if (mi->context.c2.tls_multi && check_debug_level(D_DCO_DEBUG)
&& dco_enabled(&mi->context.options))
{
- buf_printf(&out, " peer-id=%d", mi->context.c2.tls_multi->peer_id);
+ buf_printf(&out, " rx_peer-id=%d", mi->context.c2.tls_multi->rx_peer_id);
}
return BSTR(&out);
}
@@ -628,9 +628,9 @@
}
#endif
- if (mi->context.c2.tls_multi->peer_id != MAX_PEER_ID)
+ if (mi->context.c2.tls_multi->rx_peer_id != MAX_PEER_ID)
{
- m->instances[mi->context.c2.tls_multi->peer_id] = NULL;
+ m->instances[mi->context.c2.tls_multi->rx_peer_id] = NULL;
}
schedule_remove_entry(m->schedule, (struct schedule_entry *)mi);
@@ -949,8 +949,7 @@
#else
sep,
#endif
- sep,
- mi->context.c2.tls_multi ? mi->context.c2.tls_multi->peer_id : UINT32_MAX,
+ sep, mi->context.c2.tls_multi ? mi->context.c2.tls_multi->rx_peer_id : UINT32_MAX,
sep, translate_cipher_name_to_openvpn(mi->context.options.ciphername));
}
gc_free(&gc);
@@ -1756,6 +1755,17 @@
{
tls_multi->use_peer_id = true;
o->use_peer_id = true;
+ uint32_t peer_id = extract_asymmetric_peer_id(peer_info);
+ if (peer_id)
+ {
+ tls_multi->tx_peer_id = peer_id;
+ tls_multi->use_asymmetric_peer_id = true;
+ }
+ else
+ {
+ /*Client has no asymmetric peer-id capability */
+ tls_multi->tx_peer_id = tls_multi->rx_peer_id;
+ }
}
else if (dco_enabled(o))
{
@@ -3153,12 +3163,12 @@
* has, so we disallow it. This can happen if a DCO netlink notification
* gets lost and we miss a floating step.
*/
- if (m1->peer_id == m2->peer_id)
+ if (m1->rx_peer_id == m2->rx_peer_id)
{
msg(M_WARN,
"disallowing peer %" PRIu32 " (%s) from floating to "
"its own address (%s)",
- m1->peer_id, tls_common_name(mi->context.c2.tls_multi, false),
+ m1->rx_peer_id, tls_common_name(mi->context.c2.tls_multi, false),
mroute_addr_print(&mi->real, &gc));
goto done;
}
@@ -3171,9 +3181,10 @@
}
msg(D_MULTI_MEDIUM, "peer %" PRIu32 " (%s) floated from %s to %s",
- mi->context.c2.tls_multi->peer_id, tls_common_name(mi->context.c2.tls_multi, false),
- mroute_addr_print_ex(&mi->real, MAPF_SHOW_FAMILY, &gc),
- mroute_addr_print_ex(&real, MAPF_SHOW_FAMILY, &gc));
+ mi->context.c2.tls_multi->rx_peer_id,
+ tls_common_name(mi->context.c2.tls_multi, false),
+ mroute_addr_print(&mi->real, &gc),
+ print_link_socket_actual(&m->top.c2.from, &gc));
/* remove old address from hash table before changing address */
ASSERT(hash_remove(m->hash, &mi->real));
@@ -4159,7 +4170,7 @@
{
if (!m->instances[i])
{
- mi->context.c2.tls_multi->peer_id = i;
+ mi->context.c2.tls_multi->rx_peer_id = i;
m->instances[i] = mi;
break;
}
@@ -4167,7 +4178,7 @@
/* should not really end up here, since multi_create_instance returns null
* if amount of clients exceeds max_clients */
- ASSERT(mi->context.c2.tls_multi->peer_id < m->max_clients);
+ ASSERT(mi->context.c2.tls_multi->rx_peer_id < m->max_clients);
}
/**************************************************************************/
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index e7fc50c..d9e5803 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -659,9 +659,10 @@
print_in_addr_t(c->c2.push_ifconfig_remote_netmask, 0, gc));
}
- if (tls_multi->use_peer_id)
+ if (tls_multi->use_peer_id && !tls_multi->use_asymmetric_peer_id)
{
- push_option_fmt(gc, push_list, M_USAGE, "peer-id %d", tls_multi->peer_id);
+ push_option_fmt(gc, push_list, M_USAGE, "peer-id %d",
+ tls_multi->rx_peer_id);
}
/*
* If server uses --auth-gen-token and we have an auth token
diff --git a/src/openvpn/push_util.c b/src/openvpn/push_util.c
index 9138bdb..b5d8a57 100644
--- a/src/openvpn/push_util.c
+++ b/src/openvpn/push_util.c
@@ -175,14 +175,14 @@
if (process_incoming_push_update(c, pull_permission_mask(c), option_types_found, &msgs[i], true) == PUSH_MSG_ERROR)
{
msg(M_WARN, "Failed to process push update message sent to client ID: %u",
- c->c2.tls_multi ? c->c2.tls_multi->peer_id : UINT32_MAX);
+ c->c2.tls_multi ? c->c2.tls_multi->rx_peer_id : UINT32_MAX);
continue;
}
c->options.push_option_types_found |= *option_types_found;
if (!options_postprocess_pull(&c->options, c->c2.es))
{
msg(M_WARN, "Failed to post-process push update message sent to client ID: %u",
- c->c2.tls_multi ? c->c2.tls_multi->peer_id : UINT32_MAX);
+ c->c2.tls_multi ? c->c2.tls_multi->rx_peer_id : UINT32_MAX);
}
}
return true;
@@ -264,7 +264,7 @@
if (!send_single_push_update(&curr_mi->context, msgs, &option_types_found))
{
msg(M_CLIENT, "ERROR: Peer ID: %u has not been updated",
- curr_mi->context.c2.tls_multi ? curr_mi->context.c2.tls_multi->peer_id : UINT32_MAX);
+ curr_mi->context.c2.tls_multi ? curr_mi->context.c2.tls_multi->rx_peer_id : UINT32_MAX);
continue;
}
if (option_types_found & OPT_P_UP)
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 34036f2..fc22287 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -1175,7 +1175,9 @@
/* get command line derived options */
ret->opt = *tls_options;
ret->dco_peer_id = -1;
- ret->peer_id = MAX_PEER_ID;
+ ret->use_asymmetric_peer_id = false;
+ ret->rx_peer_id = MAX_PEER_ID;
+ ret->tx_peer_id = MAX_PEER_ID;
return ret;
}
@@ -1880,7 +1882,7 @@
* @return true if no error was encountered
*/
static bool
-push_peer_info(struct buffer *buf, struct tls_session *session)
+push_peer_info(struct buffer *buf, struct tls_session *session, uint32_t peer_id)
{
struct gc_arena gc = gc_new();
bool ret = false;
@@ -1974,6 +1976,11 @@
buf_printf(&out, "IV_PROTO=%d\n", iv_proto);
+ if (peer_id != MAX_PEER_ID)
+ {
+ buf_printf(&out, "ID=%x\n", peer_id);
+ }
+
if (session->opt->push_peer_info_detail > 1)
{
/* push compression status */
@@ -2154,7 +2161,20 @@
}
}
- if (!push_peer_info(buf, session))
+ /* Calculate the asymmetric peer-id */
+ if (multi->rx_peer_id == MAX_PEER_ID && session->opt->mode != MODE_SERVER)
+ {
+ uint8_t peerid[3];
+ srand((unsigned)time(NULL));
+ for (int i = 0; i < 3; i++)
+ {
+ peerid[i] = rand();
+ }
+
+ multi->rx_peer_id = (peerid[0] << 16) + (peerid[1] << 8) + peerid[2];
+ multi->use_asymmetric_peer_id = true;
+ }
+ if (!push_peer_info(buf, session, multi->rx_peer_id))
{
goto error;
}
@@ -4006,8 +4026,8 @@
msg(D_TLS_DEBUG, __func__);
ASSERT(ks);
-
- peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF));
+ peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24
+ | (multi->tx_peer_id & 0xFFFFFF));
ASSERT(buf_write_prepend(buf, &peer, 4));
}
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index de89d30..c9818d4 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -697,8 +697,10 @@
#define AUTH_TOKEN_VALID_EMPTYUSER (1 << 2)
/* For P_DATA_V2 */
- uint32_t peer_id;
+ uint32_t rx_peer_id;
+ uint32_t tx_peer_id;
bool use_peer_id;
+ bool use_asymmetric_peer_id;
char *remote_ciphername; /**< cipher specified in peer's config file */
bool remote_usescomp; /**< remote announced comp-lzo in OCC string */
diff --git a/src/openvpn/ssl_ncp.c b/src/openvpn/ssl_ncp.c
index 790e50f..0f0d6bb 100644
--- a/src/openvpn/ssl_ncp.c
+++ b/src/openvpn/ssl_ncp.c
@@ -406,6 +406,7 @@
{
/* will return 0 if peer_info is null */
const unsigned int iv_proto_peer = extract_iv_proto(multi->peer_info);
+ const unsigned int tx_peer_id = extract_asymmetric_peer_id(multi->peer_info);
/* The other peer does not support P2P NCP */
if (!(iv_proto_peer & IV_PROTO_NCP_P2P))
@@ -416,9 +417,15 @@
if (iv_proto_peer & IV_PROTO_DATA_V2)
{
multi->use_peer_id = true;
- multi->peer_id = 0x76706e; /* 'v' 'p' 'n' */
+ multi->use_asymmetric_peer_id = true;
+ multi->rx_peer_id = 0x76706e; /* 'v' 'p' 'n' */
+ multi->tx_peer_id = 0x76706e; /* 'v' 'p' 'n' */
}
+ if (tx_peer_id)
+ {
+ multi->tx_peer_id = tx_peer_id;
+ }
if (iv_proto_peer & IV_PROTO_CC_EXIT_NOTIFY)
{
session->opt->crypto_flags |= CO_USE_CC_EXIT_NOTIFY;
@@ -458,7 +465,7 @@
}
else
{
- multi->peer_id = (peerid[0] << 16) + (peerid[1] << 8) + peerid[2];
+ multi->rx_peer_id = (peerid[0] << 16) + (peerid[1] << 8) + peerid[2];
}
}
}
@@ -500,11 +507,13 @@
common_cipher = BSTR(&out);
}
- msg(D_TLS_DEBUG_LOW,
- "P2P mode NCP negotiation result: "
- "TLS_export=%d, DATA_v2=%d, peer-id %d, epoch=%d, cipher=%s",
- (bool)(session->opt->crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT), multi->use_peer_id,
- multi->peer_id, (bool)(session->opt->crypto_flags & CO_EPOCH_DATA_KEY_FORMAT),
+ msg(D_TLS_DEBUG_LOW, "P2P mode NCP negotiation result: "
+ "TLS_export=%d, DATA_v2=%d, rx-peer-id %d, tx-peer-id %d, epoch=%d, cipher=%s",
+ (bool)(session->opt->crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT),
+ multi->use_peer_id,
+ multi->rx_peer_id,
+ multi->tx_peer_id,
+ (bool)(session->opt->crypto_flags & CO_EPOCH_DATA_KEY_FORMAT),
common_cipher);
gc_free(&gc);
diff --git a/src/openvpn/ssl_util.c b/src/openvpn/ssl_util.c
index 50e8c03..655497e 100644
--- a/src/openvpn/ssl_util.c
+++ b/src/openvpn/ssl_util.c
@@ -72,6 +72,24 @@
return 0;
}
+uint32_t
+extract_asymmetric_peer_id(const char *peer_info)
+{
+ const char *optstr = peer_info ? strstr(peer_info, "ID=") : NULL;
+ if (optstr)
+ {
+ uint32_t peer_id = 0;
+ int r = sscanf(optstr, "ID=%x", &peer_id);
+ {
+ if (r == 1 && peer_id >= 0)
+ {
+ return peer_id;
+ }
+ }
+ }
+ return 0;
+}
+
const char *
options_string_compat_lzo(const char *options, struct gc_arena *gc)
{
diff --git a/src/openvpn/ssl_util.h b/src/openvpn/ssl_util.h
index 007ed69..56e4d26 100644
--- a/src/openvpn/ssl_util.h
+++ b/src/openvpn/ssl_util.h
@@ -53,6 +53,8 @@
*/
unsigned int extract_iv_proto(const char *peer_info);
+uint32_t extract_asymmetric_peer_id(const char *peer_info);
+
/**
* Takes a locally produced OCC string for TLS server mode and modifies as
* if the option comp-lzo was enabled. This is to send a client in
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1089?usp=email
To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I0a13ee90b6706acf20eabcee3bab3f2dff639bf9
Gerrit-Change-Number: 1089
Gerrit-PatchSet: 3
Gerrit-Owner: its_Giaan <gia...@ma...>
Gerrit-Reviewer: cron2 <ge...@gr...>
Gerrit-Reviewer: flichtenheld <fr...@li...>
Gerrit-Reviewer: plaisthos <arn...@rf...>
Gerrit-CC: openvpn-devel <ope...@li...>
Gerrit-Attention: its_Giaan <gia...@ma...>
Gerrit-Attention: flichtenheld <fr...@li...>
Gerrit-MessageType: newpatchset
|