Skip to content

Commit 747cf65

Browse files
committed
Add initial pcap analysis
1 parent ec6f9be commit 747cf65

File tree

15 files changed

+498
-194
lines changed

15 files changed

+498
-194
lines changed

.github/workflows/tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
steps:
1818
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
1919
- uses: actions-rs/toolchain@b2417cde72dcf67f306c0ae8e0828a81bf0b189f # v1.0.6
20+
- if: matrix.os == 'ubuntu-24.04'
21+
run: sudo apt-get install -y libpcap-dev
2022
- name: Install hack
2123
run: cargo +stable install --git https://github.com/taiki-e/cargo-hack.git cargo-hack --rev c0b517b9eefa27cdaf27cca5f1b186c00ef1af47 --locked
2224
- run: cargo hack test --each-feature ${{ matrix.packages }}
@@ -29,6 +31,8 @@ jobs:
2931
steps:
3032
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
3133
- uses: actions-rs/toolchain@b2417cde72dcf67f306c0ae8e0828a81bf0b189f # v1.0.6
34+
- if: matrix.os == 'ubuntu-24.04'
35+
run: sudo apt-get install -y libpcap-dev
3236
- run: CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER='sudo -E' cargo test -- --ignored
3337

3438
crypto-bench:

Cargo.lock

Lines changed: 110 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

neptun/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ default = []
1515
device = ["socket2", "thiserror"]
1616
# mocks std::time::Instant with mock_instant
1717
mock-instant = ["mock_instant"]
18+
xray = []
1819

1920
[dependencies]
2021
base64 = "0.13"

neptun/src/noise/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,41 @@ impl Tunn {
331331
self.handle_verified_packet(packet, dst)
332332
}
333333

334+
#[cfg(feature = "xray")]
335+
pub fn decrypt<'a>(
336+
&mut self,
337+
datagram: &[u8],
338+
dst: &'a mut [u8],
339+
) -> Result<&'a [u8], WireGuardError> {
340+
let packet = Tunn::parse_incoming_packet(datagram)?;
341+
match packet {
342+
Packet::PacketData(p) => {
343+
let r_idx = p.receiver_idx as usize;
344+
let idx = r_idx % N_SESSIONS;
345+
346+
// Get the (probably) right session
347+
let decapsulated_packet = {
348+
let session = self.sessions[idx].as_ref();
349+
let session = session.ok_or_else(|| {
350+
tracing::trace!(
351+
message = "No current session available",
352+
remote_idx = r_idx
353+
);
354+
WireGuardError::NoCurrentSession
355+
})?;
356+
session.decrypt_data_packet(p, dst)?
357+
};
358+
359+
match self.validate_decapsulated_packet(decapsulated_packet) {
360+
TunnResult::WriteToTunnelV4(p, _) => Ok(p),
361+
TunnResult::Err(err) => Err(err),
362+
_ => Err(WireGuardError::UnexpectedPacket),
363+
}
364+
}
365+
_ => Err(WireGuardError::WrongPacketType),
366+
}
367+
}
368+
334369
pub(crate) fn handle_verified_packet<'a>(
335370
&mut self,
336371
packet: Packet,

neptun/src/noise/session.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,41 @@ impl Session {
273273
let counter_validator = self.receiving_key_counter.lock();
274274
(counter_validator.next, counter_validator.receive_cnt)
275275
}
276+
277+
#[cfg(feature = "xray")]
278+
pub fn decrypt_data_packet<'a>(
279+
&self,
280+
packet: PacketData,
281+
dst: &'a mut [u8],
282+
) -> Result<&'a mut [u8], WireGuardError> {
283+
let ct_len = packet.encrypted_encapsulated_packet.len();
284+
if dst.len() < ct_len {
285+
// This is a very incorrect use of the library, therefore panic and not error
286+
panic!("The destination buffer is too small");
287+
}
288+
let decrypt_key = if packet.receiver_idx == self.receiving_index {
289+
&self.receiver
290+
} else if packet.receiver_idx == self.sending_index {
291+
&self.sender
292+
} else {
293+
return Err(WireGuardError::WrongIndex);
294+
};
295+
296+
let ret = {
297+
let mut nonce = [0u8; 12];
298+
nonce[4..12].copy_from_slice(&packet.counter.to_le_bytes());
299+
dst[..ct_len].copy_from_slice(packet.encrypted_encapsulated_packet);
300+
decrypt_key
301+
.open_in_place(
302+
Nonce::assume_unique_for_key(nonce),
303+
Aad::from(&[]),
304+
&mut dst[..ct_len],
305+
)
306+
.map_err(|_| WireGuardError::InvalidAeadTag)?
307+
};
308+
309+
Ok(ret)
310+
}
276311
}
277312

278313
#[inline(always)]

xray/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ clap = { version = "4.5", features = ["derive"] }
1111
color-eyre = "0.6"
1212
csv = "1.3.1"
1313
curve25519-dalek = "4.1"
14+
pcap = "2.2"
1415
pnet = "0.35"
1516
rand = "0.8.5"
17+
serde = { version = "1.0", features = ["derive"] }
1618
thiserror = "1.0"
1719
tokio = { version = "1.41", features = ["macros", "rt-multi-thread", "time", "net", "sync"] }
1820
x25519-dalek = "2.0"
1921

2022
[dependencies.neptun]
2123
version = "0.6.0"
2224
path = "../neptun"
23-
features = ["device"]
25+
features = ["device", "xray"]

xray/Pipfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ name = "pypi"
66
[packages]
77
ruff = "==0.8"
88
matplotlib = "==3.9"
9-
scapy = "==2.6"
109

1110
[dev-packages]
1211

0 commit comments

Comments
 (0)