Skip to content

Commit

Permalink
(xray) Add bidirectional testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Mathias Peters committed Jan 13, 2025
1 parent 72bbf6b commit ab2479e
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 43 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ jobs:
run: |
pipenv run python run.py --wg native --ascii --save-output --test-type crypto --count 10000
pipenv run python run.py --wg native --ascii --save-output --test-type plaintext --count 10000
pipenv run python run.py --wg native --ascii --save-output --test-type bidir --count 10000
pipenv run python run.py --wg neptun --ascii --save-output --test-type crypto --count 10000 --disable-drop-privileges
pipenv run python run.py --wg neptun --ascii --save-output --test-type plaintext --count 10000 --disable-drop-privileges
pipenv run python run.py --wg neptun --ascii --save-output --test-type bidir --count 10000 --disable-drop-privileges
- name: Results
working-directory: xray/results
run: |
Expand Down
4 changes: 1 addition & 3 deletions xray/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The application is executed with the `run.py` script. I takes some arguments, al

- **--wg <adapter type>**: which adapter type to use, accepts one of `neptun`, `native`, `wggo` and `boringtun`. Default is `neptun`

- **--test_type <test type>**: which kind of test to run, accepts `crypto` (to send packets from the crypto socket to the plaintext socket) and `plaintext` (to send packets from the plaintext socket to the crypto socket). Default is `crypto`
- **--test_type <test type>**: which kind of test to run, accepts `crypto` (to send packets from the crypto socket to the plaintext socket), `plaintext` (to send packets from the plaintext socket to the crypto socket), and `bidir` (to send packets in both directions). Default is `crypto`

- **--count <number of packets>**: How many packets to send. Default is 10

Expand All @@ -77,6 +77,4 @@ The application is executed with the `run.py` script. I takes some arguments, al

## Known issues

- The analysis of pcaps is quite limited right now because it doesn't decrypt the packets (this is being worked on)

- There are multiple inefficiencies that could potentially impact the test results, the main one being not reusing buffers when creating and sending packets. Each packet that gets constructed allocates a new buffer when they could all reuse the same one
3 changes: 3 additions & 0 deletions xray/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def from_str(s):
class TestType(Enum):
Crypto = 1
Plaintext = 2
Bidir = 3

def __str__(self):
return self.name.lower()
Expand All @@ -52,6 +53,8 @@ def from_str(s):
return TestType.Crypto
if s.lower() == "plaintext":
return TestType.Plaintext
if s.lower() == "bidir":
return TestType.Bidir
raise Exception(f"'{s}' is not a valid test type")


Expand Down
30 changes: 14 additions & 16 deletions xray/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ impl EventLoop {
packet_dst,
send_index,
} => {
if send_index > 0 && send_index % (self.cli_args.packet_count / 10) as u64 == 0 {
println!("[Crypto] Sending packet with index {send_index}");
}
let (packet, payload) = prepare_packet(send_index)?;
self.packets.push(packet);

Expand All @@ -125,17 +122,22 @@ impl EventLoop {
.send_packet(sock_dst, packet_dst, &payload)
.await?;
self.can_send = !matches!(sr, SendType::HandshakeInitiation);

if send_index % (self.cli_args.packet_count / 10) as u64 == 0 {
println!("{} packets sent", send_index + 1);
}
}
TestCmd::SendPlaintext { dst, send_index } => {
if send_index > 0 && send_index % (self.cli_args.packet_count / 10) as u64 == 0 {
println!("[Plaintext] Sending packet with index {send_index}");
}
let (packet, payload) = prepare_packet(send_index)?;
self.packets.push(packet);

self.plaintext_client
.send_packet(dst, dst, &payload)
.await?;

if send_index % (self.cli_args.packet_count / 10) as u64 == 0 {
println!("{} packets sent", send_index + 1);
}
}
}
Ok(())
Expand All @@ -153,12 +155,10 @@ impl EventLoop {
}
RecvType::Data { length: bytes_read } => {
if bytes_read == Packet::send_size() {
if self.recv_counter > 0
&& self.recv_counter % (self.cli_args.packet_count / 10) == 0
{
println!("[Crypto] Received {} packets", self.recv_counter);
}
self.recv_counter += 1;
if (self.recv_counter - 1) % (self.cli_args.packet_count / 10) == 0 {
println!("{} packets recevied", self.recv_counter);
}
let send_index = u64::from_le_bytes(
self.crypto_buf[0..8]
.try_into()
Expand All @@ -183,12 +183,10 @@ impl EventLoop {
) -> XRayResult<()> {
if let RecvType::Data { length: bytes_read } = rt {
if bytes_read == Packet::send_size() {
if self.recv_counter > 0
&& self.recv_counter % (self.cli_args.packet_count / 10) == 0
{
println!("[Plaintext] Received {} packets", self.recv_counter);
}
self.recv_counter += 1;
if (self.recv_counter - 1) % (self.cli_args.packet_count / 10) == 0 {
println!("{} packets received", self.recv_counter);
}
let send_index = u64::from_le_bytes(
self.plaintext_buf[0..8]
.try_into()
Expand Down
50 changes: 26 additions & 24 deletions xray/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct CliArgs {
#[arg(
long,
default_value_t = TestType::Crypto,
value_parser = clap::builder::PossibleValuesParser::new(["crypto", "plaintext"])
value_parser = clap::builder::PossibleValuesParser::new(["crypto", "plaintext", "bidir"])
.map(|s| s.parse::<TestType>().unwrap()),
)]
test_type: TestType,
Expand Down Expand Up @@ -123,25 +123,27 @@ async fn main() -> EyreResult<()> {

println!("Starting {test_type} test with {packet_count} packets");
for i in 0..packet_count {
match test_type {
TestType::Crypto => {
cmd_tx
.send(TestCmd::SendEncrypted {
sock_dst: WG_ADDR,
packet_dst: PLAINTEXT_ADDR,
send_index: i as u64,
})
.await?
}
TestType::Plaintext => {
cmd_tx
.send(TestCmd::SendPlaintext {
dst: CRYPTO_ADDR,
send_index: i as u64,
})
.await?
}
}
let cmd = match test_type {
TestType::Crypto => TestCmd::SendEncrypted {
sock_dst: WG_ADDR,
packet_dst: PLAINTEXT_ADDR,
send_index: i as u64,
},
TestType::Plaintext => TestCmd::SendPlaintext {
dst: CRYPTO_ADDR,
send_index: i as u64,
},
TestType::Bidir if i % 2 == 0 => TestCmd::SendEncrypted {
sock_dst: WG_ADDR,
packet_dst: PLAINTEXT_ADDR,
send_index: i as u64,
},
TestType::Bidir => TestCmd::SendPlaintext {
dst: CRYPTO_ADDR,
send_index: i as u64,
},
};
cmd_tx.send(cmd).await?;
}
cmd_tx.send(TestCmd::Done).await?;
let mut event_loop = task.await.expect("Awaiting task should be successful")?;
Expand All @@ -157,16 +159,16 @@ async fn main() -> EyreResult<()> {
continue;
}
match (test_type, p.src.port(), p.dst.port()) {
(TestType::Crypto, CRYPTO_PORT, WG_PORT) => {
(tt, CRYPTO_PORT, WG_PORT) if !matches!(tt, TestType::Plaintext) => {
packets[p.send_index as usize].pre_wg_ts = Some(p.ts)
}
(TestType::Crypto, CRYPTO_PORT, PLAINTEXT_PORT) => {
(tt, CRYPTO_PORT, PLAINTEXT_PORT) if !matches!(tt, TestType::Plaintext) => {
packets[p.send_index as usize].post_wg_ts = Some(p.ts)
}
(TestType::Plaintext, PLAINTEXT_PORT, CRYPTO_PORT) => {
(tt, PLAINTEXT_PORT, CRYPTO_PORT) if !matches!(tt, TestType::Crypto) => {
packets[p.send_index as usize].pre_wg_ts = Some(p.ts)
}
(TestType::Plaintext, WG_PORT, CRYPTO_PORT) => {
(tt, WG_PORT, CRYPTO_PORT) if !matches!(tt, TestType::Crypto) => {
packets[p.send_index as usize].post_wg_ts = Some(p.ts)
}
params => println!("Unexpected pcap packet found: {params:?}"),
Expand Down
3 changes: 3 additions & 0 deletions xray/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ impl std::str::FromStr for Wg {
pub enum TestType {
Crypto,
Plaintext,
Bidir,
}

impl std::fmt::Display for TestType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Crypto => "crypto",
Self::Plaintext => "plaintext",
Self::Bidir => "bidir",
};
s.fmt(f)
}
Expand All @@ -96,6 +98,7 @@ impl std::str::FromStr for TestType {
match s {
"crypto" => Ok(Self::Crypto),
"plaintext" => Ok(Self::Plaintext),
"bidir" => Ok(Self::Bidir),
_ => Err(format!("Unsupported test type '{s}'")),
}
}
Expand Down

0 comments on commit ab2479e

Please sign in to comment.