mirror of
				https://github.com/edera-dev/krata.git
				synced 2025-11-03 23:29:39 +00:00 
			
		
		
		
	network: implement proper IPv6 networking
This commit is contained in:
		@ -114,7 +114,7 @@ impl NetworkBackend {
 | 
			
		||||
        let proxy = Box::new(ProxyNatHandlerFactory::new());
 | 
			
		||||
        let ipv4 = IpCidr::from_str(&self.ipv4)
 | 
			
		||||
            .map_err(|_| anyhow!("failed to parse ipv4 cidr: {}", self.ipv4))?;
 | 
			
		||||
        let ipv6 = IpCidr::from_str(&self.ipv4)
 | 
			
		||||
        let ipv6 = IpCidr::from_str(&self.ipv6)
 | 
			
		||||
            .map_err(|_| anyhow!("failed to parse ipv6 cidr: {}", self.ipv6))?;
 | 
			
		||||
        let addresses: Vec<IpCidr> = vec![ipv4, ipv6];
 | 
			
		||||
        let mut kdev =
 | 
			
		||||
 | 
			
		||||
@ -21,15 +21,15 @@ use tokio::{
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum IcmpProtocol {
 | 
			
		||||
    Icmp4,
 | 
			
		||||
    Icmp6,
 | 
			
		||||
    Icmpv4,
 | 
			
		||||
    Icmpv6,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IcmpProtocol {
 | 
			
		||||
    pub fn to_socket_protocol(&self) -> RawSocketProtocol {
 | 
			
		||||
        match self {
 | 
			
		||||
            IcmpProtocol::Icmp4 => RawSocketProtocol::Icmpv4,
 | 
			
		||||
            IcmpProtocol::Icmp6 => RawSocketProtocol::Icmpv6,
 | 
			
		||||
            IcmpProtocol::Icmpv4 => RawSocketProtocol::Icmpv4,
 | 
			
		||||
            IcmpProtocol::Icmpv6 => RawSocketProtocol::Icmpv6,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -88,7 +88,7 @@ impl IcmpClient {
 | 
			
		||||
            let packet = &buffer[0..size];
 | 
			
		||||
 | 
			
		||||
            let (token, reply) = match protocol {
 | 
			
		||||
                IcmpProtocol::Icmp4 => {
 | 
			
		||||
                IcmpProtocol::Icmpv4 => {
 | 
			
		||||
                    let sliced = match SlicedPacket::from_ip(packet) {
 | 
			
		||||
                        Ok(sliced) => sliced,
 | 
			
		||||
                        Err(error) => {
 | 
			
		||||
@ -126,7 +126,7 @@ impl IcmpClient {
 | 
			
		||||
                    (token, reply)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                IcmpProtocol::Icmp6 => {
 | 
			
		||||
                IcmpProtocol::Icmpv6 => {
 | 
			
		||||
                    let Ok(icmpv6) = Icmpv6Slice::from_slice(packet) else {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,8 @@ use async_trait::async_trait;
 | 
			
		||||
use etherparse::Ethernet2Slice;
 | 
			
		||||
use etherparse::Icmpv4Header;
 | 
			
		||||
use etherparse::Icmpv4Type;
 | 
			
		||||
use etherparse::Icmpv6Header;
 | 
			
		||||
use etherparse::Icmpv6Type;
 | 
			
		||||
use etherparse::IpNumber;
 | 
			
		||||
use etherparse::IpPayloadSlice;
 | 
			
		||||
use etherparse::Ipv4Slice;
 | 
			
		||||
@ -220,6 +222,11 @@ impl NatRouter {
 | 
			
		||||
                    .await?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            IpNumber::IPV6_ICMP => {
 | 
			
		||||
                self.process_icmpv6(data, ether, source_addr, dest_addr, ipv6.payload())
 | 
			
		||||
                    .await?;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _ => {}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -295,6 +302,31 @@ impl NatRouter {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn process_icmpv6<'a>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        data: &'a [u8],
 | 
			
		||||
        ether: &Ethernet2Slice<'a>,
 | 
			
		||||
        source_addr: IpAddress,
 | 
			
		||||
        dest_addr: IpAddress,
 | 
			
		||||
        payload: &IpPayloadSlice<'a>,
 | 
			
		||||
    ) -> Result<()> {
 | 
			
		||||
        let (header, _) = Icmpv6Header::from_slice(payload.payload)?;
 | 
			
		||||
        let Icmpv6Type::EchoRequest(_) = header.icmp_type else {
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        };
 | 
			
		||||
        let source = IpEndpoint::new(source_addr, 0);
 | 
			
		||||
        let dest = IpEndpoint::new(dest_addr, 0);
 | 
			
		||||
        let key = NatKey {
 | 
			
		||||
            protocol: NatKeyProtocol::Icmp,
 | 
			
		||||
            client_mac: EthernetAddress(ether.source()),
 | 
			
		||||
            local_mac: EthernetAddress(ether.destination()),
 | 
			
		||||
            client_ip: source,
 | 
			
		||||
            external_ip: dest,
 | 
			
		||||
        };
 | 
			
		||||
        self.process_nat(data, key).await?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn process_nat(&mut self, data: &[u8], key: NatKey) -> Result<()> {
 | 
			
		||||
        for cidr in &self.local_cidrs {
 | 
			
		||||
            if cidr.contains_addr(&key.external_ip.addr) {
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,10 @@ impl ProxyIcmpHandler {
 | 
			
		||||
        context: NatHandlerContext,
 | 
			
		||||
        rx_receiver: Receiver<Vec<u8>>,
 | 
			
		||||
    ) -> Result<()> {
 | 
			
		||||
        let client = IcmpClient::new(IcmpProtocol::Icmp4)?;
 | 
			
		||||
        let client = IcmpClient::new(match context.key.external_ip.addr {
 | 
			
		||||
            IpAddress::Ipv4(_) => IcmpProtocol::Icmpv4,
 | 
			
		||||
            IpAddress::Ipv6(_) => IcmpProtocol::Icmpv6,
 | 
			
		||||
        })?;
 | 
			
		||||
        tokio::spawn(async move {
 | 
			
		||||
            if let Err(error) = ProxyIcmpHandler::process(client, rx_receiver, context).await {
 | 
			
		||||
                warn!("processing of icmp proxy failed: {}", error);
 | 
			
		||||
@ -157,7 +160,7 @@ impl ProxyIcmpHandler {
 | 
			
		||||
        ipv6: &Ipv6Slice<'_>,
 | 
			
		||||
        client: &IcmpClient,
 | 
			
		||||
    ) -> Result<()> {
 | 
			
		||||
        if ipv6.header().next_header() != IpNumber::ICMP {
 | 
			
		||||
        if ipv6.header().next_header() != IpNumber::IPV6_ICMP {
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user