Skip to content

Commit

Permalink
Merge pull request #3 from sndyuk/feature/encrypt_tcpip
Browse files Browse the repository at this point in the history
Encrypt TcpIp packet
  • Loading branch information
sndyuk authored Jun 7, 2023
2 parents f1727bc + b5c4cc6 commit b10f42d
Show file tree
Hide file tree
Showing 14 changed files with 765 additions and 429 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ The node is going to run on the new sandbox network `rimnet_2`.
2. Knock to the peer node from the new node.
It will only accept the incomming request from the peer node(10.0.0.4) to the source node(10.0.0.3).
```sh
$ cargo build -p cli && sudo ip netns exec rimnet_1 target/debug/cli knock-request --public-ipv4 10.0.254.1 --target-public-ipv4 10.0.254.2
$ cargo build -p cli && sudo ip netns exec rimnet_1 target/debug/cli knock-request --public-ipv4 10.0.254.1 --target-public-ipv4 10.0.254.2 --target-private-ipv4 10.0.0.4
```

Opposite as well.
```sh
$ cargo build -p cli && sudo ip netns exec rimnet_2 target/debug/cli knock-request --public-ipv4 10.0.254.2 --target-public-ipv4 10.0.254.1
$ cargo build -p cli && sudo ip netns exec rimnet_2 target/debug/cli knock-request --public-ipv4 10.0.254.2 --target-public-ipv4 10.0.254.1 --target-private-ipv4 10.0.0.4
...
[Inbound / incomming] Session established
```
Expand Down
1 change: 1 addition & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ async fn knock_request(

let packet = gateway::packet::PacketBuilder::new()?
.protocol(Protocol::KnockRequest)?
.source("0.0.0.0".parse::<Ipv4Addr>()?)?
.add_payload(knock_request_packet.as_ref())?
.build()?;

Expand Down
12 changes: 8 additions & 4 deletions lib/src/gateway/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,17 @@ pub async fn send(
packet: &packet::Packet<impl AsRef<[u8]>>,
to_addr: &SocketAddr,
) -> Result<()> {
let msg_len = packet.total_len() as usize;
let send_len = sock.send_to(packet.as_ref(), to_addr).await?;
if send_len != msg_len {
send_raw(sock, packet.as_ref(), to_addr).await
}

pub async fn send_raw(sock: &UdpSocket, buf: impl AsRef<[u8]>, to_addr: &SocketAddr) -> Result<()> {
let buf = buf.as_ref();
let send_len = sock.send_to(buf, to_addr).await?;
if send_len != buf.len() {
return Err(anyhow!(
"could not send all data. actual message length={}, expected={}",
send_len,
msg_len
buf.len()
));
} else {
log::trace!("messge sent to {:?}", sock);
Expand Down
36 changes: 7 additions & 29 deletions lib/src/gateway/packet/handshake.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::*;
use std::{fmt, net::Ipv4Addr};

pub const HEADER_FIX_LEN: usize = 13;
pub const HEADER_FIX_LEN: usize = 9;

#[derive(Copy, Clone)]
pub struct Handshake<B> {
Expand All @@ -12,7 +12,6 @@ impl<B: AsRef<[u8]>> fmt::Debug for Handshake<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("rimnet::packet::Handshake")
.field("header_len", &self.header_len())
.field("private_ipv4", &self.private_ipv4())
.field("nonce", &self.nonce())
.field("public_ipv4", &self.public_ipv4())
.field("public_port", &self.public_port())
Expand All @@ -36,30 +35,21 @@ impl<B: AsRef<[u8]>> Handshake<B> {
self.buffer.as_ref()[0]
}

pub fn private_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[1],
self.buffer.as_ref()[2],
self.buffer.as_ref()[3],
self.buffer.as_ref()[4],
)
}

pub fn nonce(&self) -> u16 {
((self.buffer.as_ref()[5] as u16) << 8) | (self.buffer.as_ref()[6] as u16)
((self.buffer.as_ref()[1] as u16) << 8) | (self.buffer.as_ref()[2] as u16)
}

pub fn public_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[7],
self.buffer.as_ref()[8],
self.buffer.as_ref()[9],
self.buffer.as_ref()[10],
self.buffer.as_ref()[3],
self.buffer.as_ref()[4],
self.buffer.as_ref()[5],
self.buffer.as_ref()[6],
)
}

pub fn public_port(&self) -> u16 {
((self.buffer.as_ref()[11] as u16) << 8) | (self.buffer.as_ref()[12] as u16)
((self.buffer.as_ref()[7] as u16) << 8) | (self.buffer.as_ref()[8] as u16)
}

pub fn public_key(&self) -> &[u8] {
Expand All @@ -74,7 +64,6 @@ impl<B: AsRef<[u8]>> Handshake<B> {

#[derive(Debug)]
pub struct HandshakePacketBuilder {
private_ipv4: Option<Ipv4Addr>,
nonce: u16,
public_ipv4: Option<Ipv4Addr>,
public_port: u16,
Expand All @@ -84,7 +73,6 @@ pub struct HandshakePacketBuilder {
impl HandshakePacketBuilder {
pub fn new() -> Result<Self> {
Ok(HandshakePacketBuilder {
private_ipv4: None,
nonce: 0,
public_ipv4: None,
public_port: 0,
Expand All @@ -93,16 +81,12 @@ impl HandshakePacketBuilder {
}

pub fn build(self) -> Result<Handshake<Vec<u8>>> {
let private_ipv4 = self
.private_ipv4
.ok_or(anyhow!("private_ipv4 is rquired"))?;
let public_ipv4 = self.public_ipv4.ok_or(anyhow!("public_ipv4 is rquired"))?;
let public_key = self.public_key.ok_or(anyhow!("public_key is rquired"))?;
let header_len = (HEADER_FIX_LEN + public_key.len()) as u8;
Ok(Handshake::unchecked(
[
&[header_len] as &[u8],
&private_ipv4.octets(),
&[(self.nonce >> 8) as u8, (self.nonce & 0b11111111) as u8] as &[u8],
&public_ipv4.octets(),
&[
Expand All @@ -123,12 +107,6 @@ impl Default for HandshakePacketBuilder {
}

impl HandshakePacketBuilder {
pub fn private_ipv4(mut self, value: Ipv4Addr) -> Result<Self> {
self.private_ipv4 = Some(value);

Ok(self)
}

pub fn nonce(mut self, value: u16) -> Result<Self> {
self.nonce = value;

Expand Down
133 changes: 133 additions & 0 deletions lib/src/gateway/packet/handshake_accept.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use anyhow::*;
use std::{fmt, net::Ipv4Addr};

pub const HEADER_FIX_LEN: usize = 9;

#[derive(Copy, Clone)]
pub struct HandshakeAccept<B> {
buffer: B,
}

impl<B: AsRef<[u8]>> fmt::Debug for HandshakeAccept<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("rimnet::packet::HandshakeAccept")
.field("header_len", &self.header_len())
.field("nonce", &self.nonce())
.field("public_ipv4", &self.public_ipv4())
.field("public_port", &self.public_port())
.field("public_key", &base64::encode(&self.public_key()))
.finish()
}
}

impl<B: AsRef<[u8]>> AsRef<[u8]> for HandshakeAccept<B> {
fn as_ref(&self) -> &[u8] {
&self.buffer.as_ref()
}
}

impl<B: AsRef<[u8]>> HandshakeAccept<B> {
pub fn unchecked(buffer: B) -> HandshakeAccept<B> {
HandshakeAccept { buffer }
}

pub fn header_len(&self) -> u8 {
self.buffer.as_ref()[0]
}

pub fn nonce(&self) -> u16 {
((self.buffer.as_ref()[1] as u16) << 8) | (self.buffer.as_ref()[2] as u16)
}

pub fn public_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[3],
self.buffer.as_ref()[4],
self.buffer.as_ref()[5],
self.buffer.as_ref()[6],
)
}

pub fn public_port(&self) -> u16 {
((self.buffer.as_ref()[7] as u16) << 8) | (self.buffer.as_ref()[8] as u16)
}

pub fn public_key(&self) -> &[u8] {
let header_len = self.header_len() as usize;
let len = header_len - HEADER_FIX_LEN;
unsafe {
let ptr = self.buffer.as_ref().as_ptr().add(HEADER_FIX_LEN);
std::slice::from_raw_parts(ptr, len)
}
}
}

#[derive(Debug)]
pub struct HandshakeAcceptPacketBuilder {
nonce: u16,
public_ipv4: Option<Ipv4Addr>,
public_port: u16,
public_key: Option<Vec<u8>>,
}

impl HandshakeAcceptPacketBuilder {
pub fn new() -> Result<Self> {
Ok(HandshakeAcceptPacketBuilder {
nonce: 0,
public_ipv4: None,
public_port: 0,
public_key: None,
})
}

pub fn build(self) -> Result<HandshakeAccept<Vec<u8>>> {
let public_ipv4 = self.public_ipv4.ok_or(anyhow!("public_ipv4 is rquired"))?;
let public_key = self.public_key.ok_or(anyhow!("public_key is rquired"))?;
let header_len = (HEADER_FIX_LEN + public_key.len()) as u8;
Ok(HandshakeAccept::unchecked(
[
&[header_len] as &[u8],
&[(self.nonce >> 8) as u8, (self.nonce & 0b11111111) as u8] as &[u8],
&public_ipv4.octets(),
&[
(self.public_port >> 8) as u8,
(self.public_port & 0b11111111) as u8,
] as &[u8],
public_key.as_ref(),
]
.concat(),
))
}
}

impl Default for HandshakeAcceptPacketBuilder {
fn default() -> Self {
HandshakeAcceptPacketBuilder::new().unwrap()
}
}

impl HandshakeAcceptPacketBuilder {
pub fn nonce(mut self, value: u16) -> Result<Self> {
self.nonce = value;

Ok(self)
}

pub fn public_ipv4(mut self, value: Ipv4Addr) -> Result<Self> {
self.public_ipv4 = Some(value);

Ok(self)
}

pub fn public_port(mut self, value: u16) -> Result<Self> {
self.public_port = value;

Ok(self)
}

pub fn public_key(mut self, value: impl AsRef<[u8]>) -> Result<Self> {
self.public_key = Some(value.as_ref().to_vec());

Ok(self)
}
}
36 changes: 7 additions & 29 deletions lib/src/gateway/packet/knock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::*;
use std::{fmt, net::Ipv4Addr};

pub const HEADER_FIX_LEN: usize = 13;
pub const HEADER_FIX_LEN: usize = 9;

#[derive(Copy, Clone)]
pub struct Knock<B> {
Expand All @@ -11,7 +11,6 @@ pub struct Knock<B> {
impl<B: AsRef<[u8]>> fmt::Debug for Knock<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("rimnet::packet::Knock")
.field("private_ipv4", &self.private_ipv4())
.field("nonce", &self.nonce())
.field("public_ipv4", &self.public_ipv4())
.field("public_port", &self.public_port())
Expand All @@ -35,30 +34,21 @@ impl<B: AsRef<[u8]>> Knock<B> {
self.buffer.as_ref()[0]
}

pub fn private_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[1],
self.buffer.as_ref()[2],
self.buffer.as_ref()[3],
self.buffer.as_ref()[4],
)
}

pub fn nonce(&self) -> u16 {
((self.buffer.as_ref()[5] as u16) << 8) | (self.buffer.as_ref()[6] as u16)
((self.buffer.as_ref()[1] as u16) << 8) | (self.buffer.as_ref()[2] as u16)
}

pub fn public_ipv4(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[7],
self.buffer.as_ref()[8],
self.buffer.as_ref()[9],
self.buffer.as_ref()[10],
self.buffer.as_ref()[3],
self.buffer.as_ref()[4],
self.buffer.as_ref()[5],
self.buffer.as_ref()[6],
)
}

pub fn public_port(&self) -> u16 {
((self.buffer.as_ref()[11] as u16) << 8) | (self.buffer.as_ref()[12] as u16)
((self.buffer.as_ref()[7] as u16) << 8) | (self.buffer.as_ref()[8] as u16)
}

pub fn public_key(&self) -> impl AsRef<[u8]> {
Expand All @@ -73,7 +63,6 @@ impl<B: AsRef<[u8]>> Knock<B> {

#[derive(Debug)]
pub struct KnockPacketBuilder {
private_ipv4: Option<Ipv4Addr>,
nonce: u16,
public_ipv4: Option<Ipv4Addr>,
public_port: u16,
Expand All @@ -83,7 +72,6 @@ pub struct KnockPacketBuilder {
impl KnockPacketBuilder {
pub fn new() -> Result<Self> {
Ok(KnockPacketBuilder {
private_ipv4: None,
nonce: 0,
public_ipv4: None,
public_port: 0,
Expand All @@ -92,16 +80,12 @@ impl KnockPacketBuilder {
}

pub fn build(self) -> Result<Knock<Vec<u8>>> {
let private_ipv4 = self
.private_ipv4
.ok_or(anyhow!("private_ipv4 is rquired"))?;
let public_ipv4 = self.public_ipv4.ok_or(anyhow!("public_ipv4 is rquired"))?;
let public_key = self.public_key.ok_or(anyhow!("public_key is rquired"))?;
let header_len = (HEADER_FIX_LEN + public_key.len()) as u8;
Ok(Knock::unchecked(
[
&[header_len] as &[u8],
&private_ipv4.octets(),
&[(self.nonce >> 8) as u8, (self.nonce & 0b11111111) as u8] as &[u8],
&public_ipv4.octets(),
&[
Expand All @@ -122,12 +106,6 @@ impl Default for KnockPacketBuilder {
}

impl KnockPacketBuilder {
pub fn private_ipv4(mut self, value: Ipv4Addr) -> Result<Self> {
self.private_ipv4 = Some(value);

Ok(self)
}

pub fn nonce(mut self, value: u16) -> Result<Self> {
self.nonce = value;

Expand Down
Loading

0 comments on commit b10f42d

Please sign in to comment.