1

Clean up tcp (and ci scripts)

This commit is contained in:
Evan Pratten 2023-07-16 22:35:44 -04:00
parent 93c6e3af7c
commit c91f5d3b37
5 changed files with 76 additions and 108 deletions

View File

@ -14,4 +14,9 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: build
args: --release --all-features
args: --release
- uses: actions-rs/cargo@v1
with:
command: test
args: --release

View File

@ -1,12 +0,0 @@
on: [push, pull_request]
name: Clippy
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: rustup component add clippy
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features

View File

@ -6,7 +6,7 @@ use std::{
use ipnet::{Ipv4Net, Ipv6Net};
use pnet_packet::{ip::IpNextHeaderProtocols, Packet};
use crate::{into_udp, ipv4_packet, ipv6_packet, nat::xlat::translate_udp_4_to_6};
use crate::{into_tcp, into_udp, ipv4_packet, ipv6_packet, nat::xlat::translate_udp_4_to_6};
use self::{
interface::Nat64Interface,
@ -171,6 +171,20 @@ impl Nat64 {
.packet()
)))),
// Transmission Control Protocol
IpNextHeaderProtocols::Tcp => Ok(Some(IpPacket::V6(ipv6_packet!(
new_source,
new_destination,
IpNextHeaderProtocols::Tcp,
packet.get_ttl(),
xlat::translate_tcp_4_to_6(
into_tcp!(packet.payload().to_vec())?,
new_source,
new_destination
)?
.packet()
)))),
// For any protocol we don't support, just warn and drop the packet
next_level_protocol => {
log::warn!("Unsupported next level protocol: {}", next_level_protocol);
@ -194,6 +208,20 @@ impl Nat64 {
.packet()
)))),
// Transmission Control Protocol
IpNextHeaderProtocols::Tcp => Ok(Some(IpPacket::V4(ipv4_packet!(
new_source,
new_destination,
packet.get_hop_limit(),
IpNextHeaderProtocols::Tcp,
xlat::translate_tcp_6_to_4(
into_tcp!(packet.payload().to_vec())?,
new_source,
new_destination
)?
.packet()
)))),
// For any protocol we don't support, just warn and drop the packet
next_header_protocol => {
log::warn!("Unsupported next header protocol: {}", next_header_protocol);

View File

@ -5,8 +5,7 @@ mod tcp;
mod udp;
pub use icmp::{proxy_icmp_packet, IcmpProxyError};
pub use tcp::{proxy_tcp_packet, TcpProxyError};
// pub use udp::{proxy_udp_packet, UdpProxyError};
pub use tcp::{translate_tcp_4_to_6, translate_tcp_6_to_4};
pub use udp::{translate_udp_4_to_6, translate_udp_6_to_4};
#[derive(Debug, thiserror::Error)]

View File

@ -1,104 +1,52 @@
use std::net::IpAddr;
use std::net::{Ipv4Addr, Ipv6Addr};
use pnet_packet::{
ip::IpNextHeaderProtocols,
ipv4::{self, Ipv4Packet, MutableIpv4Packet},
ipv6::{Ipv6Packet, MutableIpv6Packet},
tcp::{self, MutableTcpPacket, TcpPacket},
Packet,
};
use crate::nat::packet::IpPacket;
use super::PacketTranslationError;
#[derive(Debug, thiserror::Error)]
pub enum TcpProxyError {
#[error("Packet too short. Got {0} bytes")]
PacketTooShort(usize),
/// Translate an IPv4 TCP packet into an IPv6 TCP packet (aka: recalculate checksum)
pub fn translate_tcp_4_to_6(
ipv4_tcp: TcpPacket,
new_source: Ipv6Addr,
new_dest: Ipv6Addr,
) -> Result<TcpPacket, PacketTranslationError> {
// Create a mutable clone of the IPv4 TCP packet, so it can be adapted for use in IPv6
let mut ipv6_tcp = MutableTcpPacket::owned(ipv4_tcp.packet().to_vec())
.ok_or_else(|| PacketTranslationError::InputPacketTooShort(ipv4_tcp.packet().len()))?;
// Rewrite the checksum for use in an IPv6 packet
ipv6_tcp.set_checksum(0);
ipv6_tcp.set_checksum(tcp::ipv6_checksum(
&ipv4_tcp.to_immutable(),
&new_source,
&new_dest,
));
// Return the translated packet
Ok(TcpPacket::owned(ipv6_tcp.packet().to_vec()).unwrap())
}
/// Extracts information from an original packet, and proxies TCP contents via a new source and destination
pub async fn proxy_tcp_packet<'a>(
original_packet: IpPacket<'a>,
new_source: IpAddr,
new_destination: IpAddr,
) -> Result<IpPacket, TcpProxyError> {
// Parse the original packet's payload to extract UDP data
let tcp_packet = TcpPacket::new(original_packet.get_payload())
.ok_or_else(|| TcpProxyError::PacketTooShort(original_packet.get_payload().len()))?;
log::debug!(
"Incoming TCP packet ports: {} -> {}",
tcp_packet.get_source(),
tcp_packet.get_destination()
);
log::debug!(
"Incoming TCP packet payload len: {}",
tcp_packet.payload().len()
);
/// Translate an IPv6 TCP packet into an IPv4 TCP packet (aka: recalculate checksum)
pub fn translate_tcp_6_to_4(
ipv6_tcp: TcpPacket,
new_source: Ipv4Addr,
new_dest: Ipv4Addr,
) -> Result<TcpPacket, PacketTranslationError> {
// Create a mutable clone of the IPv6 TCP packet, so it can be adapted for use in IPv4
let mut ipv4_tcp = MutableTcpPacket::owned(ipv6_tcp.packet().to_vec())
.ok_or_else(|| PacketTranslationError::InputPacketTooShort(ipv6_tcp.packet().len()))?;
// Construct a new output packet
match (&original_packet, new_source, new_destination) {
// Translate IPv4(UDP) to IPv6(UDP)
(IpPacket::V4(_), IpAddr::V6(new_source), IpAddr::V6(new_destination)) => {
// Construct translated TCP packet
let mut translated_tcp_packet =
MutableTcpPacket::owned(tcp_packet.packet().to_vec()).unwrap();
// Rewrite the checksum for use in an IPv4 packet
ipv4_tcp.set_checksum(0);
ipv4_tcp.set_checksum(tcp::ipv4_checksum(
&ipv6_tcp.to_immutable(),
&new_source,
&new_dest,
));
// Rewrite the checksum
translated_tcp_packet.set_checksum(0);
translated_tcp_packet.set_checksum(tcp::ipv6_checksum(
&translated_tcp_packet.to_immutable(),
&new_source,
&new_destination,
));
// Construct translated IP packet to wrap TCP packet
let mut output =
MutableIpv6Packet::owned(vec![0u8; 40 + translated_tcp_packet.packet().len()])
.unwrap();
output.set_version(6);
output.set_source(new_source);
output.set_destination(new_destination);
output.set_hop_limit(original_packet.get_ttl());
output.set_next_header(IpNextHeaderProtocols::Tcp);
output.set_payload_length(translated_tcp_packet.packet().len() as u16);
output.set_payload(translated_tcp_packet.packet());
Ok(IpPacket::V6(
Ipv6Packet::owned(output.to_immutable().packet().to_vec()).unwrap(),
))
}
// Translate IPv6(UDP) to IPv4(UDP)
(IpPacket::V6(_), IpAddr::V4(new_source), IpAddr::V4(new_destination)) => {
// Construct translated TCP packet
let mut translated_tcp_packet =
MutableTcpPacket::owned(tcp_packet.packet().to_vec()).unwrap();
// Rewrite the checksum
translated_tcp_packet.set_checksum(0);
translated_tcp_packet.set_checksum(tcp::ipv4_checksum(
&translated_tcp_packet.to_immutable(),
&new_source,
&new_destination,
));
// Construct translated IP packet to wrap TCP packet
let mut output =
MutableIpv4Packet::owned(vec![0u8; 20 + translated_tcp_packet.packet().len()]).unwrap();
output.set_version(4);
output.set_source(new_source);
output.set_destination(new_destination);
output.set_ttl(original_packet.get_ttl());
output.set_next_level_protocol(IpNextHeaderProtocols::Tcp);
output.set_header_length(5);
output.set_total_length(20 + translated_tcp_packet.packet().len() as u16);
output.set_payload(translated_tcp_packet.packet());
output.set_checksum(0);
output.set_checksum(ipv4::checksum(&output.to_immutable()));
Ok(IpPacket::V4(
Ipv4Packet::owned(output.to_immutable().packet().to_vec()).unwrap(),
))
}
_ => unreachable!(),
}
// Return the translated packet
Ok(TcpPacket::owned(ipv4_tcp.packet().to_vec()).unwrap())
}