Add fingerprint field to Bridgeline
This commit is contained in:
parent
a206917e92
commit
362996c4f7
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
@ -320,7 +331,7 @@ impl BridgeAuth {
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {:?}",
|
||||||
|
|
Loading…
Reference in New Issue