mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-04 05:31:32 +00:00
network: start work on NAT implementation
This commit is contained in:
@ -1,36 +1,75 @@
|
||||
use crate::raw_socket::{AsyncRawSocket, RawSocket};
|
||||
use crate::chandev::ChannelDevice;
|
||||
use crate::nat::NatRouter;
|
||||
use crate::proxynat::ProxyNatHandlerFactory;
|
||||
use crate::raw_socket::AsyncRawSocket;
|
||||
use advmac::MacAddr6;
|
||||
use anyhow::{anyhow, Result};
|
||||
use futures::channel::oneshot;
|
||||
use futures::{try_join, TryStreamExt};
|
||||
use ipstack::stream::IpStackStream;
|
||||
use log::{debug, warn};
|
||||
use futures::TryStreamExt;
|
||||
use log::warn;
|
||||
use smoltcp::iface::{Config, Interface, SocketSet};
|
||||
use smoltcp::time::Instant;
|
||||
use smoltcp::wire::{HardwareAddress, IpCidr};
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use tokio::net::TcpStream;
|
||||
use udp_stream::UdpStream;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::select;
|
||||
use tokio::sync::mpsc::{channel, Receiver};
|
||||
|
||||
pub trait NetworkSlice {
|
||||
async fn run(&self) -> Result<()>;
|
||||
#[derive(Clone)]
|
||||
pub struct NetworkBackend {
|
||||
network: String,
|
||||
interface: String,
|
||||
}
|
||||
|
||||
pub struct NetworkBackend {
|
||||
pub interface: String,
|
||||
local: LocalNetworkSlice,
|
||||
internet: InternetNetworkSlice,
|
||||
enum NetworkStackSelect<'a> {
|
||||
Receive(&'a [u8]),
|
||||
Send(Option<Vec<u8>>),
|
||||
}
|
||||
|
||||
struct NetworkStack<'a> {
|
||||
tx: Receiver<Vec<u8>>,
|
||||
kdev: AsyncRawSocket,
|
||||
udev: ChannelDevice,
|
||||
interface: Interface,
|
||||
sockets: SocketSet<'a>,
|
||||
router: NatRouter,
|
||||
}
|
||||
|
||||
impl NetworkStack<'_> {
|
||||
async fn poll(&mut self, receive_buffer: &mut [u8]) -> Result<()> {
|
||||
let what = select! {
|
||||
x = self.tx.recv() => NetworkStackSelect::Send(x),
|
||||
x = self.kdev.read(receive_buffer) => NetworkStackSelect::Receive(&receive_buffer[0..x?]),
|
||||
};
|
||||
|
||||
match what {
|
||||
NetworkStackSelect::Send(packet) => {
|
||||
if let Some(packet) = packet {
|
||||
self.kdev.write_all(&packet).await?
|
||||
}
|
||||
}
|
||||
|
||||
NetworkStackSelect::Receive(packet) => {
|
||||
if let Err(error) = self.router.process(packet).await {
|
||||
warn!("router failed to process packet: {}", error);
|
||||
}
|
||||
|
||||
self.udev.rx = Some(packet.to_vec());
|
||||
let timestamp = Instant::now();
|
||||
self.interface
|
||||
.poll(timestamp, &mut self.udev, &mut self.sockets);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkBackend {
|
||||
pub fn new(network: &str, interface: &str) -> Result<Self> {
|
||||
Ok(Self {
|
||||
network: network.to_string(),
|
||||
interface: interface.to_string(),
|
||||
local: LocalNetworkSlice::new(network, interface)?,
|
||||
internet: InternetNetworkSlice::new(interface)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -56,116 +95,41 @@ impl NetworkBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<()> {
|
||||
try_join!(self.local.run(), self.internet.run()).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct LocalNetworkSlice {
|
||||
network: String,
|
||||
interface: String,
|
||||
}
|
||||
|
||||
impl LocalNetworkSlice {
|
||||
fn new(network: &str, interface: &str) -> Result<Self> {
|
||||
Ok(Self {
|
||||
network: network.to_string(),
|
||||
interface: interface.to_string(),
|
||||
})
|
||||
pub async fn run(&self) -> Result<()> {
|
||||
let mut stack = self.create_network_stack()?;
|
||||
let mut buffer = vec![0u8; 1500];
|
||||
loop {
|
||||
stack.poll(&mut buffer).await?;
|
||||
}
|
||||
}
|
||||
|
||||
fn run_blocking(&self) -> Result<()> {
|
||||
fn create_network_stack(&self) -> Result<NetworkStack> {
|
||||
let proxy = Box::new(ProxyNatHandlerFactory::new());
|
||||
let address = IpCidr::from_str(&self.network)
|
||||
.map_err(|_| anyhow!("failed to parse cidr: {}", self.network))?;
|
||||
let addresses: Vec<IpCidr> = vec![address];
|
||||
let mut socket = RawSocket::new(&self.interface)?;
|
||||
let kdev = AsyncRawSocket::bind(&self.interface)?;
|
||||
let (sender, receiver) = channel::<Vec<u8>>(4);
|
||||
let mut udev = ChannelDevice::new(1500, sender);
|
||||
let mac = MacAddr6::random();
|
||||
let mac = HardwareAddress::Ethernet(smoltcp::wire::EthernetAddress(mac.to_array()));
|
||||
let mac = smoltcp::wire::EthernetAddress(mac.to_array());
|
||||
let nat = NatRouter::new(proxy, mac);
|
||||
let mac = HardwareAddress::Ethernet(mac);
|
||||
let config = Config::new(mac);
|
||||
let mut iface = Interface::new(config, &mut socket, Instant::now());
|
||||
let mut iface = Interface::new(config, &mut udev, Instant::now());
|
||||
iface.update_ip_addrs(|addrs| {
|
||||
addrs
|
||||
.extend_from_slice(&addresses)
|
||||
.expect("failed to set ip addresses");
|
||||
});
|
||||
|
||||
let mut sockets = SocketSet::new(vec![]);
|
||||
let fd = socket.as_raw_fd();
|
||||
loop {
|
||||
let timestamp = Instant::now();
|
||||
iface.poll(timestamp, &mut socket, &mut sockets);
|
||||
smoltcp::phy::wait(fd, iface.poll_delay(timestamp, &sockets))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkSlice for LocalNetworkSlice {
|
||||
async fn run(&self) -> Result<()> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let me = self.clone();
|
||||
thread::spawn(move || {
|
||||
let _ = tx.send(me.run_blocking());
|
||||
});
|
||||
rx.await?
|
||||
}
|
||||
}
|
||||
|
||||
struct InternetNetworkSlice {
|
||||
interface: String,
|
||||
}
|
||||
|
||||
impl InternetNetworkSlice {
|
||||
pub fn new(interface: &str) -> Result<Self> {
|
||||
Ok(Self {
|
||||
interface: interface.to_string(),
|
||||
let sockets = SocketSet::new(vec![]);
|
||||
Ok(NetworkStack {
|
||||
tx: receiver,
|
||||
kdev,
|
||||
udev,
|
||||
interface: iface,
|
||||
sockets,
|
||||
router: nat,
|
||||
})
|
||||
}
|
||||
|
||||
async fn process_stream(stream: IpStackStream) {
|
||||
match stream {
|
||||
IpStackStream::Tcp(mut tcp) => {
|
||||
debug!("tcp: {}", tcp.peer_addr());
|
||||
if let Ok(mut stream) = TcpStream::connect(tcp.peer_addr()).await {
|
||||
let _ = tokio::io::copy_bidirectional(&mut tcp, &mut stream).await;
|
||||
} else {
|
||||
warn!("failed to connect to tcp address: {}", tcp.peer_addr());
|
||||
}
|
||||
}
|
||||
|
||||
IpStackStream::Udp(mut udp) => {
|
||||
debug!("udp: {}", udp.peer_addr());
|
||||
if let Ok(mut stream) = UdpStream::connect(udp.peer_addr()).await {
|
||||
let _ = tokio::io::copy_bidirectional(&mut stream, &mut udp).await;
|
||||
} else {
|
||||
warn!("failed to connect to udp address: {}", udp.peer_addr());
|
||||
}
|
||||
}
|
||||
|
||||
IpStackStream::UnknownTransport(u) => {
|
||||
debug!("unknown transport: {}", u.dst_addr());
|
||||
}
|
||||
|
||||
IpStackStream::UnknownNetwork(packet) => {
|
||||
debug!("unknown network: {:?}", packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkSlice for InternetNetworkSlice {
|
||||
async fn run(&self) -> Result<()> {
|
||||
let mut config = ipstack::IpStackConfig::default();
|
||||
config.mtu(1500);
|
||||
config.tcp_timeout(std::time::Duration::from_secs(60));
|
||||
config.udp_timeout(std::time::Duration::from_secs(10));
|
||||
|
||||
let socket = AsyncRawSocket::bind(&self.interface)?;
|
||||
let mut stack = ipstack::IpStack::new(config, socket);
|
||||
|
||||
while let Ok(stream) = stack.accept().await {
|
||||
tokio::spawn(InternetNetworkSlice::process_stream(stream));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user