Make datagram SPTPS key exchange more robust.
Similar to old style key exchange requests, keep track of whether a key exchange is already in progress and how long it took. If no key is known yet or if key exchange takes too long, (re)start a new key exchange.
This commit is contained in:
parent
b99af2f813
commit
bb6b97ce34
4 changed files with 47 additions and 29 deletions
|
@ -234,6 +234,10 @@ static void check_reachability(void) {
|
|||
/* TODO: only clear status.validkey if node is unreachable? */
|
||||
|
||||
n->status.validkey = false;
|
||||
if(n->status.sptps) {
|
||||
sptps_stop(&n->sptps);
|
||||
n->status.waitingforkey = false;
|
||||
}
|
||||
n->last_req_key = 0;
|
||||
|
||||
n->maxmtu = MTU;
|
||||
|
|
|
@ -389,39 +389,48 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
|
|||
}
|
||||
|
||||
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
|
||||
if(n->status.sptps) {
|
||||
uint8_t type = 0;
|
||||
int offset = 0;
|
||||
|
||||
if(!(origpkt->data[12] | origpkt->data[13])) {
|
||||
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len);
|
||||
return;
|
||||
if(!n->status.validkey) {
|
||||
logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
|
||||
if(!n->status.waitingforkey)
|
||||
send_req_key(n);
|
||||
else if(n->last_req_key + 10 < time(NULL)) {
|
||||
sptps_stop(&n->sptps);
|
||||
n->status.waitingforkey = false;
|
||||
send_req_key(n);
|
||||
}
|
||||
}
|
||||
|
||||
if(routing_mode == RMODE_ROUTER)
|
||||
offset = 14;
|
||||
else
|
||||
type = PKT_MAC;
|
||||
uint8_t type = 0;
|
||||
int offset = 0;
|
||||
|
||||
if(origpkt->len < offset)
|
||||
return;
|
||||
|
||||
vpn_packet_t outpkt;
|
||||
|
||||
if(n->outcompression) {
|
||||
int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression);
|
||||
if(len < 0) {
|
||||
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
|
||||
} else if(len < origpkt->len - offset) {
|
||||
outpkt.len = len + offset;
|
||||
origpkt = &outpkt;
|
||||
type |= PKT_COMPRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset);
|
||||
if(!(origpkt->data[12] | origpkt->data[13])) {
|
||||
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len);
|
||||
return;
|
||||
}
|
||||
|
||||
if(routing_mode == RMODE_ROUTER)
|
||||
offset = 14;
|
||||
else
|
||||
type = PKT_MAC;
|
||||
|
||||
if(origpkt->len < offset)
|
||||
return;
|
||||
|
||||
vpn_packet_t outpkt;
|
||||
|
||||
if(n->outcompression) {
|
||||
int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression);
|
||||
if(len < 0) {
|
||||
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
|
||||
} else if(len < origpkt->len - offset) {
|
||||
outpkt.len = len + offset;
|
||||
origpkt = &outpkt;
|
||||
type |= PKT_COMPRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset);
|
||||
return;
|
||||
}
|
||||
|
||||
static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||
|
@ -620,6 +629,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
|
|||
|
||||
if(type == SPTPS_HANDSHAKE) {
|
||||
from->status.validkey = true;
|
||||
from->status.waitingforkey = false;
|
||||
logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
typedef struct node_status_t {
|
||||
unsigned int unused_active:1; /* 1 if active (not used for nodes) */
|
||||
unsigned int validkey:1; /* 1 if we currently have a valid key for him */
|
||||
unsigned int unused_waitingforkey:1; /* 1 if we already sent out a request */
|
||||
unsigned int waitingforkey:1; /* 1 if we already sent out a request */
|
||||
unsigned int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
|
||||
unsigned int reachable:1; /* 1 if this node is reachable in the graph */
|
||||
unsigned int indirect:1; /* 1 if this node is not directly reachable by us */
|
||||
|
|
|
@ -116,6 +116,8 @@ bool send_req_key(node_t *to) {
|
|||
snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name);
|
||||
sptps_stop(&to->sptps);
|
||||
to->status.validkey = false;
|
||||
to->status.waitingforkey = true;
|
||||
to->last_req_key = time(NULL);
|
||||
to->incompression = myself->incompression;
|
||||
return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record);
|
||||
}
|
||||
|
@ -172,6 +174,8 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
|
|||
snprintf(label, sizeof label, "tinc UDP key expansion %s %s", from->name, myself->name);
|
||||
sptps_stop(&from->sptps);
|
||||
from->status.validkey = false;
|
||||
from->status.waitingforkey = true;
|
||||
from->last_req_key = time(NULL);
|
||||
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record);
|
||||
sptps_receive_data(&from->sptps, buf, len);
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue