From e23ba3ae8aae1b900791fd2c3a04afacbff5eeef Mon Sep 17 00:00:00 2001 From: kyechou Date: Sun, 30 Oct 2022 23:58:39 -0500 Subject: [PATCH] Skip packets with invalid protocol states (#21) Such as middlebox as an endpoint resetting or reconnecting to devices --- src/emulation.cpp | 168 ++++++++++++++++++------------------- src/lib/net.cpp | 3 +- src/process/forwarding.cpp | 3 + src/protocols.hpp | 30 +++---- 4 files changed, 105 insertions(+), 99 deletions(-) diff --git a/src/emulation.cpp b/src/emulation.cpp index 8ed632a0..0ad7a77d 100644 --- a/src/emulation.cpp +++ b/src/emulation.cpp @@ -95,6 +95,90 @@ void Emulation::teardown() { stop_listener = false; } +void Emulation::reset_offsets() { + this->seq_offsets.clear(); + this->port_offsets.clear(); +} + +void Emulation::apply_offsets(Packet &pkt) const { + // Skip any non-TCP packets + if (!PS_IS_TCP(pkt.get_proto_state())) { + return; + } + + // Skip if this middlebox is not an endpoint + if (!this->emulated_mb->has_ip(pkt.get_dst_ip())) { + return; + } + + EmuPktKey key(pkt.get_src_ip(), pkt.get_src_port()); + + // Apply seq offset to the ack number + uint32_t seq_offset = 0; + auto i = this->seq_offsets.find(key); + if (i != this->seq_offsets.end()) { + seq_offset = i->second; + } + pkt.set_ack(pkt.get_ack() + seq_offset); + + // Apply port offset to the dst port number + uint16_t port_offset = 0; + auto j = this->port_offsets.find(key); + if (j != this->port_offsets.end()) { + port_offset = j->second; + } + pkt.set_dst_port(pkt.get_dst_port() + port_offset); +} + +void Emulation::update_offsets(std::list &pkts) { + for (auto &pkt : pkts) { + this->update_offsets(pkt); + } +} + +void Emulation::update_offsets(Packet &pkt) { + // Skip any non-TCP packets + if (!PS_IS_TCP(pkt.get_proto_state())) { + return; + } + + // Skip if this middlebox is not an endpoint + if (!this->emulated_mb->has_ip(pkt.get_src_ip())) { + return; + } + + EmuPktKey key(pkt.get_dst_ip(), pkt.get_dst_port()); + uint16_t flags = pkt.get_proto_state() & (~0x800U); + + // Update seq offset + if (flags == TH_SYN || flags == (TH_SYN | TH_ACK)) { + this->seq_offsets[key] = pkt.get_seq(); + pkt.set_seq(0); + } else { + uint32_t offset = 0; + auto i = this->seq_offsets.find(key); + if (i != this->seq_offsets.end()) { + offset = i->second; + } + pkt.set_seq(pkt.get_seq() - offset); + } + + // Update (src) port offset + if (flags == TH_SYN) { + if (pkt.get_src_port() >= 1024) { + this->port_offsets[key] = pkt.get_src_port() - DYNAMIC_PORT; + pkt.set_src_port(DYNAMIC_PORT); + } + } else { + uint16_t offset = 0; + auto i = this->port_offsets.find(key); + if (i != this->port_offsets.end()) { + offset = i->second; + } + pkt.set_src_port(pkt.get_src_port() - offset); + } +} + Middlebox *Emulation::get_mb() const { return emulated_mb; } @@ -228,87 +312,3 @@ std::list Emulation::send_pkt(const Packet &pkt) { this->update_offsets(pkts); return pkts; } - -void Emulation::reset_offsets() { - this->seq_offsets.clear(); - this->port_offsets.clear(); -} - -void Emulation::apply_offsets(Packet &pkt) const { - // Skip any non-TCP packets - if (!PS_IS_TCP(pkt.get_proto_state())) { - return; - } - - // Skip if this middlebox is not an endpoint - if (!this->emulated_mb->has_ip(pkt.get_dst_ip())) { - return; - } - - EmuPktKey key(pkt.get_src_ip(), pkt.get_src_port()); - - // Apply seq offset to the ack number - uint32_t seq_offset = 0; - auto i = this->seq_offsets.find(key); - if (i != this->seq_offsets.end()) { - seq_offset = i->second; - } - pkt.set_ack(pkt.get_ack() + seq_offset); - - // Apply port offset to the dst port number - uint16_t port_offset = 0; - auto j = this->port_offsets.find(key); - if (j != this->port_offsets.end()) { - port_offset = j->second; - } - pkt.set_dst_port(pkt.get_dst_port() + port_offset); -} - -void Emulation::update_offsets(std::list &pkts) { - for (auto &pkt : pkts) { - this->update_offsets(pkt); - } -} - -void Emulation::update_offsets(Packet &pkt) { - // Skip any non-TCP packets - if (!PS_IS_TCP(pkt.get_proto_state())) { - return; - } - - // Skip if this middlebox is not an endpoint - if (!this->emulated_mb->has_ip(pkt.get_src_ip())) { - return; - } - - EmuPktKey key(pkt.get_dst_ip(), pkt.get_dst_port()); - uint16_t flags = pkt.get_proto_state() & (~0x800U); - - // Update seq offset - if (flags == TH_SYN || flags == (TH_SYN | TH_ACK)) { - this->seq_offsets[key] = pkt.get_seq(); - pkt.set_seq(0); - } else { - uint32_t offset = 0; - auto i = this->seq_offsets.find(key); - if (i != this->seq_offsets.end()) { - offset = i->second; - } - pkt.set_seq(pkt.get_seq() - offset); - } - - // Update (src) port offset - if (flags == TH_SYN) { - if (pkt.get_src_port() >= 1024) { - this->port_offsets[key] = pkt.get_src_port() - DYNAMIC_PORT; - pkt.set_src_port(DYNAMIC_PORT); - } - } else { - uint16_t offset = 0; - auto i = this->port_offsets.find(key); - if (i != this->port_offsets.end()) { - offset = i->second; - } - pkt.set_src_port(pkt.get_src_port() - offset); - } -} diff --git a/src/lib/net.cpp b/src/lib/net.cpp index 54c9a214..e64a48bc 100644 --- a/src/lib/net.cpp +++ b/src/lib/net.cpp @@ -595,7 +595,8 @@ void Net::process_proto_state(Packet &pkt) const { } else if (pkt.get_proto_state() > old_proto_state) { pkt.set_next_phase(true); } else { - Logger::error("Invalid protocol state"); + Logger::warn("Invalid protocol state"); + pkt.set_proto_state(PS_INVALID); } } } diff --git a/src/process/forwarding.cpp b/src/process/forwarding.cpp index 47582fdf..94029094 100644 --- a/src/process/forwarding.cpp +++ b/src/process/forwarding.cpp @@ -363,6 +363,9 @@ void ForwardingProcess::update_model_from_pkts( Net::get().identify_conn(recv_pkt); Net::get().process_proto_state(recv_pkt); + if (recv_pkt.get_proto_state() == PS_INVALID) { + continue; + } Net::get().check_seq_ack(recv_pkt); Logger::info("Received packet " + recv_pkt.to_string()); diff --git a/src/protocols.hpp b/src/protocols.hpp index ce13894c..eb0df5d7 100644 --- a/src/protocols.hpp +++ b/src/protocols.hpp @@ -18,22 +18,24 @@ static inline std::string proto_str(int n) { /* * Protocol state */ +// TODO: Make this an enum class // Note that for TCP four-way termination handshake, we assume that the second // (ACK) and third (FIN) steps are always set within the same packet. -#define PS_TCP_INIT_1 0 // TCP 3-way handshake SYN -#define PS_TCP_INIT_2 1 // TCP 3-way handshake SYN/ACK -#define PS_TCP_INIT_3 2 // TCP 3-way handshake ACK -#define PS_TCP_L7_REQ 3 // TCP L7 request -#define PS_TCP_L7_REQ_A 4 // TCP L7 request ACK -#define PS_TCP_L7_REP 5 // TCP L7 reply -#define PS_TCP_L7_REP_A 6 // TCP L7 reply ACK -#define PS_TCP_TERM_1 7 // TCP termination FIN/ACK -#define PS_TCP_TERM_2 8 // TCP termination FIN/ACK -#define PS_TCP_TERM_3 9 // TCP termination ACK -#define PS_UDP_REQ 10 // UDP request -#define PS_UDP_REP 11 // UDP reply -#define PS_ICMP_ECHO_REQ 12 // ICMP echo request -#define PS_ICMP_ECHO_REP 13 // ICMP echo reply +#define PS_INVALID 0 +#define PS_TCP_INIT_1 1 // TCP 3-way handshake SYN +#define PS_TCP_INIT_2 2 // TCP 3-way handshake SYN/ACK +#define PS_TCP_INIT_3 3 // TCP 3-way handshake ACK +#define PS_TCP_L7_REQ 4 // TCP L7 request +#define PS_TCP_L7_REQ_A 5 // TCP L7 request ACK +#define PS_TCP_L7_REP 6 // TCP L7 reply +#define PS_TCP_L7_REP_A 7 // TCP L7 reply ACK +#define PS_TCP_TERM_1 8 // TCP termination FIN/ACK +#define PS_TCP_TERM_2 9 // TCP termination FIN/ACK +#define PS_TCP_TERM_3 10 // TCP termination ACK +#define PS_UDP_REQ 11 // UDP request +#define PS_UDP_REP 12 // UDP reply +#define PS_ICMP_ECHO_REQ 13 // ICMP echo request +#define PS_ICMP_ECHO_REP 14 // ICMP echo reply #define PS_IS_REQUEST_DIR(x) \ ((x) == PS_TCP_INIT_1 || (x) == PS_TCP_INIT_3 || (x) == PS_TCP_L7_REQ || \