Skip to content

fix: connection stability improvements for production issues #1648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
aider_stdlib_map.md

# Local tools and notes
.local-tools/

### Rust ###
# Generated by Cargo
# will have compiled files and executables
Expand Down
6 changes: 3 additions & 3 deletions apps/freenet-ping/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions apps/freenet-ping/test-prod-logs/config/gateways.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[[gateways]]
public_key = "/home/ian/code/freenet/freenet-core/main/apps/freenet-ping/test-prod-logs/data/secrets/public.vega.gw.pem"

[gateways.address]
hostname = "vega.locut.us:31337"

[[gateways]]
public_key = "/home/ian/code/freenet/freenet-core/main/apps/freenet-ping/test-prod-logs/data/secrets/public.ziggy.gw.pem"

[gateways.address]
hostname = "technic.locut.us:31337"
Binary file added apps/freenet-ping/test-prod-logs/data/_EVENT_LOG
Binary file not shown.
Empty file.
Binary file not shown.
Empty file.
Binary file added apps/freenet-ping/test-prod-logs/data/db/db
Binary file not shown.
Empty file.
Empty file.
Empty file.
Empty file.
14 changes: 14 additions & 0 deletions apps/freenet-ping/test-prod-logs/data/secrets/public.vega.gw.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3ZECtEbAcxfvnpweDHiV
OtHvHtyYE5omuNWn3AHyNHPyFMRWd/LAF4l7Q0WunjL4uAXUws1U2OBroW+Rw91C
753kUtecaCelU2f4dLOfz7hIcbFL+A9w4Qzwc3bLUqTKmfASmqVX9qXP1SE4ZAKQ
VxgS/9dVNBEo6wvLkrCNvq2LVQvWslEJb+0QKKbUPrFmYVnweiNGCmP6dqL37u5d
C1jsuE72TaJ7FSj+hWFja3gl6o+Wz/Bw+9qbByUOchD7LtQ//9zl4Xb9lHjyUJ4V
+Tmhg2EiKy3EFEUWILB391cLR3YSzS6B4kw/PptZ/L/TSWUsZH33QiGnAw56jNBW
cFw3TIlQu3PvZWcttyD2dDO6tqZDusI2YHh8hyAb9Z5N8px1jlfHPpK6qHEqhB9N
XjrkD2lTuRbB55UurZ5L2ajvysIjqOOtYDPcLRZHk8YjvxrYmMIk17GKE/6YI01h
+QcqcYxcBCBv0ME9WL3ohKvWTziHVNfrcWYebISHhpc4F/CHbaj2O4bs4I9a9aXV
INlmFHVprCl7UYI7lb4BHWu0tYxsy3oZeLG7ARWffRsz3L2aRHbtqgthSu6X7yYL
YB/qWjUmIE0cAszAULCjbynplZNtwJT324+77DPD85+N9nTrS+Po8T2xJ8pCweu+
5LUJQ0Jh+QPJeIQ2TzA7RSUCAwEAAQ==
-----END PUBLIC KEY-----
14 changes: 14 additions & 0 deletions apps/freenet-ping/test-prod-logs/data/secrets/public.ziggy.gw.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArpQ/xgxqczEpsNaKtBdh
MmhiocOjfNimI6rD5cTYfMAsahKS0ElY6leXzNBgsZYLGxYPKqkrODPxpttejD9v
fdcOaN1QNW+Rl85BSf5DlBxeBdC2NTMeadC207RZOdD12pdEdIz1W1nS/PGlDqRq
Kh2LPSmuT9Kqxzk1PMO7HuIgMvQVpLBJiFnQMWJ4+meHINtI8vOkbYjLqoE2yrSK
GSapQ/zptsjzzB4Jd0Rm/OV5qT7SF14yhv+XVhPy2gw/lJmhcIDw2rCEBe7hPbDX
E+p9jCgGMi0HWN8QeSDTapY9hlFy4dzXW5xK0ySrGUAp1kcPDdwqA2npa3oJlVDZ
TstAMDt3RhdfrrwfmdQefvygBUIAlAk69y1FvNGEOO9TcikQjDaJdfQSP9V0qTEV
BsKNpkX7VHgG1i8Cc6c7JlDyeHSB+3TXSfO9esYcAFxjwx1SbyInHBMpYG/iYoX+
jGqQLJVMV6EasQ5xgryW2jTD4pBjkcrlgz0KKUlCg0cMTafaOpTrnaTHjmWYIP2c
KKxVR2Iu+cPdNPvFeywr2mF2Bz7I4cRxJOVhwupDH7XaWf8gfMMvIlsr2f2ChQzc
gRCVduKEeMp1bcuKisSbJnFIluVOgJ3MZJi7RS+0W31dkePWtJYP0eXgdlHtDVV6
scCTSgvaL0QFtu7+5ds0qqkCAwEAAQ==
-----END PUBLIC KEY-----
4 changes: 4 additions & 0 deletions crates/core/src/transport/connection_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ impl<S: Socket> UdpPacketsListener<S> {
inbound_symmetric_key: inbound_key,
inbound_symmetric_key_bytes: inbound_key_bytes,
my_address: None,
transport_secret_key: secret,
};

let inbound_conn = InboundRemoteConnection {
Expand Down Expand Up @@ -842,6 +843,8 @@ impl<S: Socket> UdpPacketsListener<S> {
inbound_symmetric_key_bytes:
inbound_sym_key_bytes,
my_address: Some(my_address),
transport_secret_key: transport_secret_key
.clone(),
},
InboundRemoteConnection {
inbound_packet_sender: inbound_sender,
Expand Down Expand Up @@ -907,6 +910,7 @@ impl<S: Socket> UdpPacketsListener<S> {
inbound_symmetric_key: inbound_sym_key,
inbound_symmetric_key_bytes: inbound_sym_key_bytes,
my_address: None,
transport_secret_key: transport_secret_key.clone(),
},
InboundRemoteConnection {
inbound_packet_sender: inbound_sender,
Expand Down
89 changes: 81 additions & 8 deletions crates/core/src/transport/peer_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::time::Duration;
use std::{collections::HashMap, time::Instant};

use crate::transport::connection_handler::NAT_TRAVERSAL_MAX_ATTEMPTS;
use crate::transport::crypto::TransportSecretKey;
use crate::transport::packet_data::UnknownEncryption;
use crate::transport::sent_packet_tracker::MESSAGE_CONFIRMATION_TIMEOUT;
use aes_gcm::Aes128Gcm;
Expand Down Expand Up @@ -47,6 +48,7 @@ pub(crate) struct RemoteConnection {
pub(super) inbound_symmetric_key: Aes128Gcm,
pub(super) inbound_symmetric_key_bytes: [u8; 16],
pub(super) my_address: Option<SocketAddr>,
pub(super) transport_secret_key: TransportSecretKey,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
Expand Down Expand Up @@ -144,9 +146,11 @@ impl PeerConnection {
outbound_symmetric_key: Aes128Gcm,
inbound_symmetric_key: Aes128Gcm,
) -> PeerConnectionMock {
use crate::transport::crypto::TransportKeypair;
use parking_lot::Mutex;
let (outbound_packets, outbound_packets_recv) = mpsc::channel(1);
let (inbound_packet_sender, inbound_packet_recv) = mpsc::channel(1);
let keypair = TransportKeypair::new();
let remote = RemoteConnection {
outbound_packets,
outbound_symmetric_key,
Expand All @@ -157,6 +161,7 @@ impl PeerConnection {
inbound_symmetric_key,
inbound_symmetric_key_bytes: [1; 16],
my_address: Some(my_address),
transport_secret_key: keypair.secret,
};
(
Self::new(remote),
Expand All @@ -172,9 +177,11 @@ impl PeerConnection {
outbound_symmetric_key: Aes128Gcm,
inbound_symmetric_key: Aes128Gcm,
) -> RemoteConnectionMock {
use crate::transport::crypto::TransportKeypair;
use parking_lot::Mutex;
let (outbound_packets, outbound_packets_recv) = mpsc::channel(1);
let (inbound_packet_sender, inbound_packet_recv) = mpsc::channel(1);
let keypair = TransportKeypair::new();
(
RemoteConnection {
outbound_packets,
Expand All @@ -186,6 +193,7 @@ impl PeerConnection {
inbound_symmetric_key,
inbound_symmetric_key_bytes: [1; 16],
my_address: Some(my_address),
transport_secret_key: keypair.secret,
},
inbound_packet_sender,
outbound_packets_recv,
Expand Down Expand Up @@ -215,14 +223,8 @@ impl PeerConnection {
// listen for incoming messages or receipts or wait until is time to do anything else again
let mut resend_check = Some(tokio::time::sleep(tokio::time::Duration::from_millis(10)));

#[cfg(debug_assertions)]
const KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(2);
#[cfg(not(debug_assertions))]
const KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(20);
#[cfg(debug_assertions)]
const KILL_CONNECTION_AFTER: Duration = Duration::from_secs(6);
#[cfg(not(debug_assertions))]
const KILL_CONNECTION_AFTER: Duration = Duration::from_secs(60);
const KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(10);
const KILL_CONNECTION_AFTER: Duration = Duration::from_secs(30);

let mut keep_alive = tokio::time::interval(KEEP_ALIVE_INTERVAL);
keep_alive.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
Expand All @@ -236,14 +238,85 @@ impl PeerConnection {
inbound = self.remote_conn.inbound_packet_recv.recv() => {
let packet_data = inbound.ok_or(TransportError::ConnectionClosed(self.remote_addr()))?;
last_received = std::time::Instant::now();

// Debug logging for 256-byte packets
if packet_data.data().len() == 256 {
tracing::warn!(
remote = ?self.remote_conn.remote_addr,
packet_bytes = ?&packet_data.data()[..32], // First 32 bytes
packet_len = packet_data.data().len(),
"Received 256-byte packet"
);
}

let Ok(decrypted) = packet_data.try_decrypt_sym(&self.remote_conn.inbound_symmetric_key).inspect_err(|error| {
tracing::warn!(
%error,
remote = ?self.remote_conn.remote_addr,
inbound_key = ?self.remote_conn.inbound_symmetric_key_bytes,
packet_len = packet_data.data().len(),
packet_first_bytes = ?&packet_data.data()[..std::cmp::min(32, packet_data.data().len())],
"Failed to decrypt packet, might be an intro packet or a partial packet"
);
}) else {
// Check if this is a 256-byte RSA intro packet
if packet_data.data().len() == 256 {
tracing::info!(
remote = ?self.remote_conn.remote_addr,
"Attempting to decrypt potential RSA intro packet"
);

// Try to decrypt as RSA intro packet
match self.remote_conn.transport_secret_key.decrypt(packet_data.data()) {
Ok(_decrypted_intro) => {
tracing::info!(
remote = ?self.remote_conn.remote_addr,
"Successfully decrypted RSA intro packet, sending ACK"
);

// Send ACK response for intro packet
let ack_packet = SymmetricMessage::ack_ok(
&self.remote_conn.outbound_symmetric_key,
self.remote_conn.inbound_symmetric_key_bytes,
self.remote_conn.remote_addr,
);

if let Ok(ack) = ack_packet {
if let Err(send_err) = self.remote_conn
.outbound_packets
.send((self.remote_conn.remote_addr, ack.data().into()))
.await
{
tracing::warn!(
remote = ?self.remote_conn.remote_addr,
error = ?send_err,
"Failed to send ACK for intro packet"
);
} else {
tracing::info!(
remote = ?self.remote_conn.remote_addr,
"Successfully sent ACK for intro packet"
);
}
} else {
tracing::warn!(
remote = ?self.remote_conn.remote_addr,
"Failed to create ACK packet for intro"
);
}

// Continue to next packet
continue;
}
Err(rsa_err) => {
tracing::debug!(
remote = ?self.remote_conn.remote_addr,
error = ?rsa_err,
"256-byte packet is not a valid RSA intro packet"
);
}
}
}
let now = Instant::now();
if let Some(first_failure_time) = self.first_failure_time {
if now.duration_since(first_failure_time) <= FAILURE_TIME_WINDOW {
Expand Down
Loading
Loading