Datenpakete erstellen, analysieren und manipulieren. Diese Kiste bietet Tools, mit denen sie mithilfe einer intuitiven Schnittstelle auf hoher Ebene problemlos mit Datenpaketen arbeiten können. Wenn Sie Funktionen oder Verbesserungen anfordern möchten, öffnen Sie bitte einfach ein Problem, um auch Fehler zu melden.
Bitte beachten Sie, dass alle Typ -Anmerkungen in dieser Dokumentation, z. B. let data: Vec<u8> = packet.into_vec(); , werden nur für Klarheit hinzugefügt und sind in Ihrem Code nicht erforderlich.
Schritt 1
Importieren Sie die entsprechenden Teile des Pakets und erstellen Sie eine neue Paketstruktur, um sie zu bevölkern. Es gibt zwei Methoden zum Erstellen eines neuen Pakets, Methode 1 setzt die Kapazität des internen Puffers auf die entsprechende Länge für die angegebenen Protokolle. Die Methode 2 erstellt nur ein völlig leeres Paket mit dem internen Pufferkapazitätssatz auf 0.
extern crate packet_crafter;
use packet_crafter::{
//import sub-modules
headers,
protocol_numbers,
ethertype_numbers,
//import data types
Packet,
Protocol
};
fn main() {
// method 1 (preferred)
let mut new_packet = Packet::new(
vec![
Protocol::ETH,
Protocol::IP,
Protocol::TCP
]
);
// method 2
let mut new_packet = Packet::new_empty();
Schritt 2
Erstellen Sie die Header und fügen Sie sie in das Paket hinzu. Hier gehen wir mit der Paketstruktur in Methode 1 von Schritt 1, welches Ethernet> IP> TCP
new_packet.add_header(
headers::EthernetHeader::new(
[6,5,4,3,2,1], // source mac address
[1,2,3,4,5,6], // destination mac address
ethertype_numbers::ETHERTYPE_IPV4
)
);
new_packet.add_header(
headers::IpHeader::new(
[192, 168, 1, 128], // source IP
[192, 168, 1, 38], // destination IP
Protocol::TCP // next protocol
)
);
new_packet.add_header(
headers::TcpHeader::new(
3838, // source port
3838 // destination port
)
);
Schritt 3
Dieser Schritt ist möglicherweise nicht immer erforderlich, in Fällen wie ICMP -Echos, in denen keine Daten vorhanden sind, da nur die Header gelesen werden. In vielen Fällen möchten Sie jedoch wahrscheinlich einige Nutzlastdaten hinzufügen. Auch hier gibt es zwei Möglichkeiten, dies zu tun. Methode 1 überschreibt die existierenden Nutzlastdaten (wenn es sich um ein neues Paket handelt, gibt es ohnehin keine. Wenn es sich jedoch um ein Paket handelt, das aus Rohdaten analysiert wurde, kann es einige geben) und Methode 2 wird die vorhandenen Nutzlastdaten angehängt. Beachten Sie das Fehlen des .collect() in Methode 2. Der Code würde immer noch damit funktionieren, es ist jedoch nicht erforderlich. Sie werden sehen, warum, wenn Sie sich die Funktionssignatur in der Quelle ansehen.
// method 1
new_packet.set_payload("Hello, world!".bytes().collect());
// method 2
new_packet.extend_payload("Hello, world!".bytes());
Schritt 4
Die Daten sind jetzt fertig, daher müssen wir nur das Paket backen. Hier werden Prüfsummenfelder und Längenfelder wie die im IP -Header besiedelten Felder (siehe diese DOC -Seite, um eine Erklärung zu erhalten, warum ich mich entschieden habe, diese zu berechnen, obwohl das Betriebssystem sie wahrscheinlich überschreiben wird)
let data: Vec<u8> = new_packet.into_vec();
}
Denken Sie immer daran, dass &Vec<u8> in Funktionen erwartet werden kann &[u8] :)
Das Parsen eines Pakets wird sehr einfach gemacht, solange das Paket entweder mit dem IP -Header oder dem Ethernet II -Header beginnt:
extern crate packet_crafter;
use packet_crafter::Packet;
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let parsed_packet: Result<Packet, packet_crafter::ParseError> = Packet::parse(raw_data);
}
Hinweis: Für IPv6 -Pakete wurde das Parsen noch nicht implementiert
Nehmen wir an, wir haben das Paket gerade analysiert, das im Beispiel für das neue Paket erstellen wird. Es handelt sich also um ein ETH> IP> TCP -Paket, und wir möchten den Desination -Port des TCP -Feldes sowie die Ziel -IP -IP aktualisieren:
// imports elided
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let mut packet = Packet::parse(raw_data).unwrap();
let mut tcp_header = packet.get_tcp_header().unwrap();
tcp_header.set_dst_port(21);
let mut ip_header = packet.get_ip_header().unwrap();
ip_header.set_dst_ip([192, 168, 1, 84]);
packet.update_header(ip_header);
// packet is now good to go, so make it and then send it:
let data = packet.into_vec();
your_function_to_send_packet_down_socket(&data);
}