aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/packets.h1
-rw-r--r--src/peer.h3
-rw-r--r--src/receive.c29
-rw-r--r--src/send.c42
-rw-r--r--src/timers.c33
-rw-r--r--src/timers.h2
6 files changed, 44 insertions, 66 deletions
diff --git a/src/packets.h b/src/packets.h
index f2ce2b7..035c548 100644
--- a/src/packets.h
+++ b/src/packets.h
@@ -31,6 +31,7 @@ void packet_send_keepalive(struct wireguard_peer *peer);
void packet_send_handshake_initiation(struct wireguard_peer *peer);
void packet_send_handshake_response(struct wireguard_peer *peer);
void packet_send_handshake_cookie(struct wireguard_device *wg, struct sk_buff *initiating_skb, void *data, size_t data_len, __le32 sender_index);
+void packet_send_handshake_initiation_ratelimited(struct wireguard_peer *peer);
void packet_queue_send_handshake_initiation(struct wireguard_peer *peer);
void packet_process_queued_handshake_packets(struct work_struct *work);
diff --git a/src/peer.h b/src/peer.h
index 6eb6224..306f9b3 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -29,11 +29,12 @@ struct wireguard_peer {
struct cookie latest_cookie;
struct hlist_node pubkey_hash;
uint64_t rx_bytes, tx_bytes;
- struct timer_list timer_retransmit_handshake, timer_delay_handshake, timer_send_keepalive, timer_new_handshake, timer_kill_ephemerals, timer_persistent_keepalive;
+ struct timer_list timer_retransmit_handshake, timer_send_keepalive, timer_new_handshake, timer_kill_ephemerals, timer_persistent_keepalive;
unsigned int timer_handshake_attempts;
unsigned long persistent_keepalive_interval;
bool timer_need_another_keepalive;
bool need_resend_queue;
+ bool sent_lastminute_handshake;
struct timeval walltime_last_handshake;
struct sk_buff_head tx_packet_queue;
struct kref refcount;
diff --git a/src/receive.c b/src/receive.c
index 58a0086..6dda410 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -123,7 +123,6 @@ static void receive_handshake_packet(struct wireguard_device *wg, void *data, si
return;
}
net_dbg_ratelimited("Receiving handshake initiation from peer %Lu (%pISpfsc)\n", peer->internal_id, &addr);
- timers_handshake_received(peer);
update_latest_addr(peer, skb);
packet_send_handshake_response(peer);
break;
@@ -139,10 +138,10 @@ static void receive_handshake_packet(struct wireguard_device *wg, void *data, si
return;
}
net_dbg_ratelimited("Receiving handshake response from peer %Lu (%pISpfsc)\n", peer->internal_id, &addr);
- timers_handshake_received(peer);
if (noise_handshake_begin_session(&peer->handshake, &peer->keypairs, true)) {
timers_ephemeral_key_created(peer);
timers_handshake_complete(peer);
+ peer->sent_lastminute_handshake = false;
packet_send_queue(peer);
}
break;
@@ -179,6 +178,26 @@ void packet_process_queued_handshake_packets(struct work_struct *work)
}
}
+static void keep_key_fresh(struct wireguard_peer *peer)
+{
+ struct noise_keypair *keypair;
+ bool send = false;
+ if (peer->sent_lastminute_handshake)
+ return;
+
+ rcu_read_lock();
+ keypair = rcu_dereference(peer->keypairs.current_keypair);
+ if (likely(keypair && keypair->sending.is_valid) && keypair->i_am_the_initiator &&
+ unlikely(time_is_before_eq_jiffies64(keypair->sending.birthdate + REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT)))
+ send = true;
+ rcu_read_unlock();
+
+ if (send) {
+ peer->sent_lastminute_handshake = true;
+ packet_send_handshake_initiation_ratelimited(peer);
+ }
+}
+
struct packet_cb {
u8 ds;
};
@@ -198,8 +217,12 @@ static void receive_data_packet(struct sk_buff *skb, struct wireguard_peer *peer
wg = peer->device;
dev = netdev_pub(wg);
- if (unlikely(used_new_key))
+ if (unlikely(used_new_key)) {
+ peer->sent_lastminute_handshake = false;
packet_send_queue(peer);
+ }
+
+ keep_key_fresh(peer);
/* A packet with length 0 is a keepalive packet */
if (unlikely(!skb->len)) {
diff --git a/src/send.c b/src/send.c
index 90d5d14..a7d505d 100644
--- a/src/send.c
+++ b/src/send.c
@@ -31,6 +31,12 @@ void packet_send_handshake_initiation(struct wireguard_peer *peer)
}
}
+void packet_send_handshake_initiation_ratelimited(struct wireguard_peer *peer)
+{
+ if (time_is_before_jiffies64(peer->last_sent_handshake + REKEY_TIMEOUT))
+ packet_queue_send_handshake_initiation(peer);
+}
+
void packet_send_handshake_response(struct wireguard_peer *peer)
{
struct message_handshake_response packet;
@@ -68,12 +74,6 @@ void packet_queue_send_handshake_initiation(struct wireguard_peer *peer)
peer_put(peer); /* If the work was already queued, we want to drop the extra reference */
}
-static inline void ratelimit_packet_send_handshake_initiation(struct wireguard_peer *peer)
-{
- if (time_is_before_jiffies64(peer->last_sent_handshake + REKEY_TIMEOUT))
- packet_queue_send_handshake_initiation(peer);
-}
-
void packet_send_handshake_cookie(struct wireguard_device *wg, struct sk_buff *initiating_skb, void *data, size_t data_len, __le32 sender_index)
{
struct message_handshake_cookie packet;
@@ -90,30 +90,18 @@ void packet_send_handshake_cookie(struct wireguard_device *wg, struct sk_buff *i
static inline void keep_key_fresh(struct wireguard_peer *peer)
{
struct noise_keypair *keypair;
+ bool send = false;
rcu_read_lock();
keypair = rcu_dereference(peer->keypairs.current_keypair);
- if (unlikely(!keypair || !keypair->sending.is_valid)) {
- rcu_read_unlock();
- return;
- }
+ if (likely(keypair && keypair->sending.is_valid) &&
+ (unlikely(atomic64_read(&keypair->sending.counter.counter) > REKEY_AFTER_MESSAGES) ||
+ (keypair->i_am_the_initiator && unlikely(time_is_before_eq_jiffies64(keypair->sending.birthdate + REKEY_AFTER_TIME)))))
+ send = true;
+ rcu_read_unlock();
- if (atomic64_read(&keypair->sending.counter.counter) > REKEY_AFTER_MESSAGES ||
- time_is_before_eq_jiffies64(keypair->sending.birthdate + REKEY_AFTER_TIME)) {
- rcu_read_unlock();
- /* The initiator can try it immediately, but the responder has to wait a bit,
- * to prevent the thundering herd effect. */
- if (keypair->i_am_the_initiator)
- ratelimit_packet_send_handshake_initiation(peer);
- else {
- /* If it's going to be dead soon, we rekey early. */
- if (time_is_before_eq_jiffies64(keypair->sending.birthdate + REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT))
- timers_delay_handshake(peer, REKEY_TIMEOUT / 2);
- else /* Otherwise rekey at the usual staggered delay. */
- timers_delay_handshake(peer, REKEY_TIMEOUT / 2 + REKEY_TIMEOUT * 2);
- }
- } else
- rcu_read_unlock();
+ if (send)
+ packet_send_handshake_initiation_ratelimited(peer);
}
void packet_send_keepalive(struct wireguard_peer *peer)
@@ -233,7 +221,7 @@ int packet_send_queue(struct wireguard_peer *peer)
case -ENOKEY:
/* ENOKEY means that we don't have a valid session for the peer, which
* means we should initiate a session, and then requeue everything. */
- ratelimit_packet_send_handshake_initiation(peer);
+ packet_send_handshake_initiation_ratelimited(peer);
goto requeue;
case -EBUSY:
/* EBUSY happens when the parallel workers are all filled up, in which
diff --git a/src/timers.c b/src/timers.c
index 7002e54..300becb 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -11,7 +11,6 @@
* Timer for initiating new handshake if we have sent a packet but after have not received one (even empty) for `(KEEPALIVE_TIMEOUT + REKEY_TIMEOUT)` ms
* Timer for zeroing out all ephemeral keys after `(REJECT_AFTER_TIME * 3)` ms if no new keys have been received
* Timer for, if enabled, sending an empty authenticated packet every user-specified seconds
- * Timer for starting a new handshake based on a delay
*/
/* This rounds the time down to the closest power of two of the closest quarter second. */
@@ -59,12 +58,6 @@ static void expired_new_handshake(unsigned long ptr)
packet_queue_send_handshake_initiation(peer);
}
-static void expired_delay_handshake(unsigned long ptr)
-{
- struct wireguard_peer *peer = (struct wireguard_peer *)ptr;
- packet_queue_send_handshake_initiation(peer);
-}
-
static void expired_kill_ephemerals(unsigned long ptr)
{
struct wireguard_peer *peer = (struct wireguard_peer *)ptr;
@@ -126,38 +119,20 @@ void timers_any_authenticated_packet_received(struct wireguard_peer *peer)
/* Should be called after a handshake initiation message is sent. */
void timers_handshake_initiated(struct wireguard_peer *peer)
{
- if (likely(peer->timer_delay_handshake.data))
- del_timer(&peer->timer_delay_handshake);
if (likely(peer->timer_send_keepalive.data))
del_timer(&peer->timer_send_keepalive);
if (likely(peer->timer_retransmit_handshake.data))
mod_timer(&peer->timer_retransmit_handshake, slack_time(jiffies + REKEY_TIMEOUT + HZ / 4));
}
-/* Should be called after a handshake message of any kind is received. */
-void timers_handshake_received(struct wireguard_peer *peer)
-{
- if (likely(peer->timer_delay_handshake.data))
- del_timer(&peer->timer_delay_handshake);
-}
-
/* Should be called after a handshake response message is received and processed. */
void timers_handshake_complete(struct wireguard_peer *peer)
{
- if (likely(peer->timer_delay_handshake.data))
- del_timer(&peer->timer_delay_handshake);
if (likely(peer->timer_retransmit_handshake.data))
del_timer(&peer->timer_retransmit_handshake);
peer->timer_handshake_attempts = 0;
}
-/* Should be called in order to initiate a handshake a little bit in the future. */
-void timers_delay_handshake(struct wireguard_peer *peer, unsigned int delay)
-{
- if (likely(peer->timer_delay_handshake.data) && !timer_pending(&peer->timer_delay_handshake))
- mod_timer(&peer->timer_delay_handshake, jiffies + delay);
-}
-
/* Should be called after an ephemeral key is created, which is before sending a handshake response or after receiving a handshake response. */
void timers_ephemeral_key_created(struct wireguard_peer *peer)
{
@@ -179,10 +154,6 @@ void timers_init_peer(struct wireguard_peer *peer)
peer->timer_retransmit_handshake.function = expired_retransmit_handshake;
peer->timer_retransmit_handshake.data = (unsigned long)peer;
- init_timer(&peer->timer_delay_handshake);
- peer->timer_delay_handshake.function = expired_delay_handshake;
- peer->timer_delay_handshake.data = (unsigned long)peer;
-
init_timer(&peer->timer_send_keepalive);
peer->timer_send_keepalive.function = expired_send_keepalive;
peer->timer_send_keepalive.data = (unsigned long)peer;
@@ -208,10 +179,6 @@ void timers_uninit_peer(struct wireguard_peer *peer)
del_timer(&peer->timer_retransmit_handshake);
peer->timer_retransmit_handshake.data = 0;
}
- if (peer->timer_delay_handshake.data) {
- del_timer(&peer->timer_delay_handshake);
- peer->timer_delay_handshake.data = 0;
- }
if (peer->timer_send_keepalive.data) {
del_timer(&peer->timer_send_keepalive);
peer->timer_send_keepalive.data = 0;
diff --git a/src/timers.h b/src/timers.h
index 349bdab..b6f80fd 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -13,9 +13,7 @@ void timers_data_sent(struct wireguard_peer *peer);
void timers_data_received(struct wireguard_peer *peer);
void timers_any_authenticated_packet_received(struct wireguard_peer *peer);
void timers_handshake_initiated(struct wireguard_peer *peer);
-void timers_handshake_received(struct wireguard_peer *peer);
void timers_handshake_complete(struct wireguard_peer *peer);
-void timers_delay_handshake(struct wireguard_peer *peer, unsigned int delay);
void timers_ephemeral_key_created(struct wireguard_peer *peer);
void timers_any_authenticated_packet_traversal(struct wireguard_peer *peer);