int main(int argc, char* argv[]) { if (argc != 2) { cout << "Usage: " << argv[0] << " <interface>" << endl; return 1; } try { // Construct the sniffer configuration object SnifferConfiguration config; // Only capture TCP traffic sent from/to port 80 config.set_filter("tcp port 80"); // Construct the sniffer we'll use Sniffer sniffer(argv[1], config); cout << "Starting capture on interface " << argv[1] << endl; // Now construct the stream follower StreamFollower follower; // We just need to specify the callback to be executed when a new // stream is captured. In this stream, you should define which callbacks // will be executed whenever new data is sent on that stream // (see on_new_connection) follower.new_stream_callback(&on_new_connection); // Now start capturing. Every time there's a new packet, call // follower.process_packet sniffer.sniff_loop([&](Packet& packet) { follower.process_packet(packet); return true; }); } catch (exception& ex) { cerr << "Error: " << ex.what() << endl; return 1; } }
TEST_F(FlowTest, StreamFollower_FINClosesStream) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::FIN | TCP::ACK); stream.process_packet(server_packet); EXPECT_EQ(Flow::FIN_SENT, stream.server_flow().state()); EXPECT_FALSE(stream.is_finished()); IP client_packet = IP("4.3.2.1", "1.2.3.4") / TCP(25, 22); client_packet.rfind_pdu<TCP>().flags(TCP::FIN | TCP::ACK); stream.process_packet(client_packet); EXPECT_EQ(Flow::FIN_SENT, stream.client_flow().state()); EXPECT_TRUE(stream.is_finished()); }
TEST_F(FlowTest, StreamFollower_CleanupWorks) { using std::placeholders::_1; bool timed_out = false; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); follower.stream_termination_callback([&](Stream&, StreamFollower::TerminationReason reason) { timed_out = (reason == StreamFollower::TIMEOUT); }); packets[2].rfind_pdu<IP>().src_addr("6.6.6.6"); auto base_time = duration_cast<Stream::timestamp_type>(system_clock::now().time_since_epoch()); Packet packet1(packets[0], base_time); Packet packet2(packets[1], base_time + seconds(50)); Packet packet3(packets[2], base_time + minutes(10)); follower.process_packet(packet1); Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(base_time, stream.create_time()); follower.process_packet(packet2); follower.process_packet(packet3); // At this point, it should be cleaned up EXPECT_THROW( follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25), stream_not_found ); EXPECT_TRUE(timed_out); }
TEST_F(FlowTest, StreamFollower_FollowStream) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); ordering_info_type chunks = split_payload(payload, 5); vector<EthernetII> chunk_packets = chunks_to_packets(30 /*initial_seq*/, chunks, payload); set_endpoints(chunk_packets, "1.2.3.4", 22, "4.3.2.1", 25); packets.insert(packets.end(), chunk_packets.begin(), chunk_packets.end()); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } EXPECT_EQ(chunk_packets.size(), stream_client_payload_chunks.size()); EXPECT_EQ(payload, merge_chunks(stream_client_payload_chunks)); }
TEST_F(FlowTest, AckNumbersAreCorrect) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); // Server's ACK number is 9898 packets[1].rfind_pdu<TCP>().ack_seq(9898); // Client's ACK number is 1717 packets[2].rfind_pdu<TCP>().ack_seq(1717); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(1717U, stream.client_flow().ack_tracker().ack_number()); EXPECT_EQ(9898U, stream.server_flow().ack_tracker().ack_number()); }
TEST_F(FlowTest, StreamFollower_ThreeWayHandshake) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); packets[0].src_addr("00:01:02:03:04:05"); packets[0].dst_addr("05:04:03:02:01:00"); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); Stream::timestamp_type ts(10000); Stream::timestamp_type create_time = ts; for (size_t i = 0; i < packets.size(); ++i) { if (i != 0) { ts += milliseconds(100); } Packet packet(packets[i], duration_cast<microseconds>(ts)); follower.process_packet(packet); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(Flow::ESTABLISHED, stream.client_flow().state()); EXPECT_EQ(Flow::SYN_SENT, stream.server_flow().state()); EXPECT_EQ(30U, stream.client_flow().sequence_number()); EXPECT_EQ(60U, stream.server_flow().sequence_number()); EXPECT_EQ(IPv4Address("4.3.2.1"), stream.client_flow().dst_addr_v4()); EXPECT_EQ(25, stream.client_flow().dport()); EXPECT_EQ(IPv4Address("1.2.3.4"), stream.server_flow().dst_addr_v4()); EXPECT_EQ(22, stream.server_flow().dport()); EXPECT_EQ(IPv4Address("1.2.3.4"), stream.client_addr_v4()); EXPECT_EQ(IPv4Address("4.3.2.1"), stream.server_addr_v4()); EXPECT_EQ(HWAddress<6>("00:01:02:03:04:05"), stream.client_hw_addr()); EXPECT_EQ(HWAddress<6>("05:04:03:02:01:00"), stream.server_hw_addr()); EXPECT_EQ(22, stream.client_port()); EXPECT_EQ(25, stream.server_port()); EXPECT_EQ(create_time, stream.create_time()); EXPECT_EQ(ts, stream.last_seen()); IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::ACK); follower.process_packet(server_packet); EXPECT_EQ(Flow::ESTABLISHED, stream.server_flow().state()); EXPECT_EQ(61U, stream.server_flow().sequence_number()); }
TEST_F(FlowTest, StreamFollower_StreamIsRemovedWhenFinished) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } IP server_packet = IP("1.2.3.4", "4.3.2.1") / TCP(22, 25); server_packet.rfind_pdu<TCP>().flags(TCP::RST); follower.process_packet(server_packet); // We shouldn't be able to find it EXPECT_THROW( follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25), stream_not_found ); }
TEST_F(FlowTest, StreamFollower_TCPOptions) { using std::placeholders::_1; vector<EthernetII> packets = three_way_handshake(29, 60, "1.2.3.4", 22, "4.3.2.1", 25); // Client's mss is 1220 packets[0].rfind_pdu<TCP>().mss(1220); // Server's mss is 1460 packets[1].rfind_pdu<TCP>().mss(1460); // Server supports SACK packets[1].rfind_pdu<TCP>().sack_permitted(); StreamFollower follower; follower.new_stream_callback(bind(&FlowTest::on_new_stream, this, _1)); for (size_t i = 0; i < packets.size(); ++i) { follower.process_packet(packets[i]); } Stream& stream = follower.find_stream(IPv4Address("1.2.3.4"), 22, IPv4Address("4.3.2.1"), 25); EXPECT_EQ(1220, stream.client_flow().mss()); EXPECT_EQ(1460, stream.server_flow().mss()); EXPECT_FALSE(stream.client_flow().sack_permitted()); EXPECT_TRUE(stream.server_flow().sack_permitted()); }