Add fingerprint field to Bridgeline

This commit is contained in:
onyinyang 2023-04-03 11:47:11 -04:00
parent a206917e92
commit 362996c4f7
No known key found for this signature in database
GPG Key ID: 156A6435430C2036
3 changed files with 39 additions and 19 deletions

View File

@ -25,7 +25,7 @@ use std::convert::TryInto;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
/// Each bridge information line is serialized into this many bytes /// Each bridge information line is serialized into this many bytes
pub const BRIDGE_BYTES: usize = 300; pub const BRIDGE_BYTES: usize = 260;
/// The max number of bridges per bucket /// The max number of bridges per bucket
pub const MAX_BRIDGES_PER_BUCKET: usize = 3; pub const MAX_BRIDGES_PER_BUCKET: usize = 3;
@ -44,10 +44,13 @@ pub struct BridgeLine {
pub addr: [u8; 16], pub addr: [u8; 16],
/// port /// port
pub port: u16, pub port: u16,
/// fingerprint
#[serde_as(as = "[_; 40]")]
pub fingerprint: [u8; 40],
/// other protocol information, including pluggable transport, /// other protocol information, including pluggable transport,
/// public key, etc. /// public key, etc.
#[serde_as(as = "[_; BRIDGE_BYTES - 18]")] #[serde_as(as = "[_; BRIDGE_BYTES - 58]")]
pub info: [u8; BRIDGE_BYTES - 18], pub info: [u8; BRIDGE_BYTES - 58],
} }
/// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the /// A bucket contains MAX_BRIDGES_PER_BUCKET bridges plus the
@ -70,7 +73,8 @@ impl Default for BridgeLine {
Self { Self {
addr: [0; 16], addr: [0; 16],
port: 0, port: 0,
info: [0; BRIDGE_BYTES - 18], fingerprint: [0; 40],
info: [0; BRIDGE_BYTES - 58],
} }
} }
} }
@ -81,7 +85,8 @@ impl BridgeLine {
let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES]; let mut res: [u8; BRIDGE_BYTES] = [0; BRIDGE_BYTES];
res[0..16].copy_from_slice(&self.addr); res[0..16].copy_from_slice(&self.addr);
res[16..18].copy_from_slice(&self.port.to_be_bytes()); res[16..18].copy_from_slice(&self.port.to_be_bytes());
res[18..].copy_from_slice(&self.info); res[18..58].copy_from_slice(&self.fingerprint);
res[58..].copy_from_slice(&self.info);
res res
} }
/// Decode a BridgeLine from a byte array /// Decode a BridgeLine from a byte array
@ -89,7 +94,8 @@ impl BridgeLine {
let mut res: Self = Default::default(); let mut res: Self = Default::default();
res.addr.copy_from_slice(&data[0..16]); res.addr.copy_from_slice(&data[0..16]);
res.port = u16::from_be_bytes(data[16..18].try_into().unwrap()); res.port = u16::from_be_bytes(data[16..18].try_into().unwrap());
res.info.copy_from_slice(&data[18..]); res.fingerprint.copy_from_slice(&data[18..58]);
res.info.copy_from_slice(&data[58..]);
res res
} }
/// Encode a bucket to a byte array, including a Bucket Reachability /// Encode a bucket to a byte array, including a Bucket Reachability
@ -188,13 +194,14 @@ impl BridgeLine {
let ports: [u16; 4] = [443, 4433, 8080, 43079]; let ports: [u16; 4] = [443, 4433, 8080, 43079];
let portidx = (rng.next_u32() % 4) as usize; let portidx = (rng.next_u32() % 4) as usize;
res.port = ports[portidx]; res.port = ports[portidx];
let mut fingerprint: [u8; 20] = [0; 20]; let mut fingerprint: [u8; 40] = [0; 40];
rng.fill_bytes(&mut fingerprint);
let mut cert: [u8; 52] = [0; 52]; let mut cert: [u8; 52] = [0; 52];
rng.fill_bytes(&mut fingerprint); rng.fill_bytes(&mut fingerprint);
res.fingerprint[0..40].copy_from_slice(&fingerprint);
rng.fill_bytes(&mut cert); rng.fill_bytes(&mut cert);
let infostr: String = format!( let infostr: String = format!(
"obfs4 {} cert={} iat-mode=0", "obfs4 cert={}, iat-mode=0",
hex_fmt::HexFmt(fingerprint),
base64::encode_config(cert, base64::STANDARD_NO_PAD) base64::encode_config(cert, base64::STANDARD_NO_PAD)
); );
res.info[..infostr.len()].copy_from_slice(infostr.as_bytes()); res.info[..infostr.len()].copy_from_slice(infostr.as_bytes());

View File

@ -309,6 +309,17 @@ impl BridgeAuth {
self.bridge_table.spares.insert(bnum); self.bridge_table.spares.insert(bnum);
} }
pub fn sync_table(&mut self) {
// Create a hashtable (?) of bridges in the lox distributor from new resources
// accept the hashtable and recreate the bridge table from the hash table here
// using existing reachable bridges, other table checks and placements from existing bridge table
// If bridges are in reachable bridges, put them in the table with their Vec
// How to check for bridges that aren't there/are extra?
// After going through the update, make sure bridges in the table are the same and deal with discrepencies
// This will be the bad/annoying part
}
// Update the details of a bridge in the bridge table. This assumes that the IP and Port // Update the details of a bridge in the bridge table. This assumes that the IP and Port
// of a given bridge remains the same and thus can be updated. // of a given bridge remains the same and thus can be updated.
// First we must retrieve the list of reachable bridges, then we must search for any matching our partial key // First we must retrieve the list of reachable bridges, then we must search for any matching our partial key
@ -316,11 +327,11 @@ impl BridgeAuth {
// Returns true if the bridge has successfully updated // Returns true if the bridge has successfully updated
pub fn bridge_update(&mut self, bridge: &BridgeLine) -> bool { pub fn bridge_update(&mut self, bridge: &BridgeLine) -> bool {
let mut res: bool = false; //default False to assume that update failed let mut res: bool = false; //default False to assume that update failed
//Needs to be updated since bridge will only match on some fields. //Needs to be updated since bridge will only match on some fields.
let reachable_bridges = self.bridge_table.reachable.clone(); let reachable_bridges = self.bridge_table.reachable.clone();
for reachable_bridge in reachable_bridges { for reachable_bridge in reachable_bridges {
if reachable_bridge.0.addr == bridge.addr && reachable_bridge.0.port == bridge.port { if reachable_bridge.0.fingerprint == bridge.fingerprint {
println!( println!(
"Bridge from table: {:?} has same IP and Port as bridge {:?}!", "Bridge from table: {:?} has same IP and Port as bridge {:?}!",
reachable_bridge.0, bridge reachable_bridge.0, bridge
@ -342,6 +353,9 @@ impl BridgeAuth {
!= reachable_bridge.0 != reachable_bridge.0
); );
} }
res = true;
} else {
return res;
} }
// We must also remove the old bridge from the reachable bridges table // We must also remove the old bridge from the reachable bridges table
// and add the new bridge // and add the new bridge
@ -349,7 +363,7 @@ impl BridgeAuth {
self.bridge_table self.bridge_table
.reachable .reachable
.insert(*bridge, reachable_bridge.1); .insert(*bridge, reachable_bridge.1);
res = true; return res;
} }
} }

View File

@ -615,30 +615,29 @@ fn test_update_bridge() {
// Created changed info for bridgeline to be updated to // Created changed info for bridgeline to be updated to
let updated_info = bucket[0]; let updated_info = bucket[0];
let infostr: String = format!( let infostr: String = format!(
"type={} blocked_in={:?} protocol={} fingerprint={} distribution={}", "type={} blocked_in={:?} protocol={} distribution={}",
"obfs2 test bridge".to_string(), "obfs2 test bridge".to_string(),
{}, {},
"obfs2".to_string(), "obfs2".to_string(),
"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD".to_string(),
"moat".to_string(), "moat".to_string(),
); );
let mut updated_info_bytes: [u8; BRIDGE_BYTES - 18] = [0; BRIDGE_BYTES - 18]; let mut updated_info_bytes: [u8; BRIDGE_BYTES - 58] = [0; BRIDGE_BYTES - 58];
updated_info_bytes[..infostr.len()].copy_from_slice(infostr.as_bytes()); updated_info_bytes[..infostr.len()].copy_from_slice(infostr.as_bytes());
let updated_bridgeline = BridgeLine { let updated_bridgeline = BridgeLine {
addr: bridgeline_to_update.addr, addr: bridgeline_to_update.addr,
port: bridgeline_to_update.port, port: bridgeline_to_update.port,
fingerprint: bridgeline_to_update.fingerprint,
info: updated_info_bytes, info: updated_info_bytes,
}; };
assert!( assert!(
updated_bridgeline.addr == bridgeline_to_update.addr, updated_bridgeline.fingerprint == bridgeline_to_update.fingerprint,
"Bridge entering the bridgepool {:?} did not have the same IP as the updating bridge {:?}", "Bridge entering the bridgepool {:?} did not have the same fingerprint as the updating bridge {:?}",
bridgeline_to_update, bridgeline_to_update,
updated_bridgeline.addr updated_bridgeline.fingerprint
); );
assert!(updated_bridgeline.port == bridgeline_to_update.port, "Bridge entering the bridgepool {:?} did not have the same port as the updating bridge {:?}", bridgeline_to_update, updated_bridgeline.port);
assert!(updated_bridgeline.info != bridgeline_to_update.info); assert!(updated_bridgeline.info != bridgeline_to_update.info);
println!( println!(
"Bridge entering the bridgepool {:?} has different info than the updating bridge {:?}", "Bridge entering the bridgepool {:?} has different info than the updating bridge {:?}",