void IPTest::test_equals(const IP &ip1, const IP &ip2) { EXPECT_EQ(ip1.dst_addr(), ip2.dst_addr()); EXPECT_EQ(ip1.src_addr(), ip2.src_addr()); EXPECT_EQ(ip1.id(), ip2.id()); EXPECT_EQ(ip1.frag_off(), ip2.frag_off()); EXPECT_EQ(ip1.tos(), ip2.tos()); EXPECT_EQ(ip1.ttl(), ip2.ttl()); EXPECT_EQ(ip1.version(), ip2.version()); EXPECT_EQ((bool)ip1.inner_pdu(), (bool)ip2.inner_pdu()); }
static bool should_intercept(const IP& ip, const RR* rr, AITF_packet *aitf) { if (!hosts.isEnabledHost(ip.dst_addr())) return false; const UDP *udp = ip.find_pdu<UDP>(); if (udp != 0) { if (udp->dport() == 11467) { const RawPDU *raw = udp->find_pdu<RawPDU>(); *aitf = AITF_packet(&raw->payload()[0], raw->payload().size()); return true; } return false; } if (rr != 0) { try { UDP udp(&rr->payload()[0], rr->payload().size()); if (udp.dport() == 11467) { const RawPDU *raw = udp.find_pdu<RawPDU>(); *aitf = AITF_packet(&raw->payload()[0], raw->payload().size()); return true; } } catch (malformed_packet e) { } } return false; }
TEST_F(IPTest, DefaultConstructor) { IP ip; EXPECT_EQ(ip.dst_addr(), "0.0.0.0"); EXPECT_EQ(ip.src_addr(), "0.0.0.0"); EXPECT_EQ(ip.version(), 4); EXPECT_EQ(ip.id(), 1); EXPECT_EQ(ip.pdu_type(), PDU::IP); }
TEST_F(PDUTest, OperatorConcat) { std::string raw_payload = "Test"; IP ip = IP("192.168.0.1") / TCP(22, 52) / RawPDU(raw_payload); EXPECT_EQ(ip.dst_addr(), "192.168.0.1"); ASSERT_TRUE(ip.inner_pdu() != NULL); TCP *tcp = ip.find_pdu<TCP>(); ASSERT_TRUE(tcp != NULL); EXPECT_EQ(tcp->dport(), 22); EXPECT_EQ(tcp->sport(), 52); ASSERT_TRUE(tcp->inner_pdu() != NULL); RawPDU *raw = tcp->find_pdu<RawPDU>(); ASSERT_TRUE(raw != NULL); ASSERT_EQ(raw->payload_size(), raw_payload.size()); EXPECT_TRUE(std::equal(raw_payload.begin(), raw_payload.end(), raw->payload().begin())); }
bool callback(const PDU &pdu) { // The packet probably looks like this: // // EthernetII / IP / UDP / RawPDU // // So we retrieve each layer, and construct a // DNS PDU from the RawPDU layer contents. EthernetII eth = pdu.rfind_pdu<EthernetII>(); IP ip = eth.rfind_pdu<IP>(); UDP udp = ip.rfind_pdu<UDP>(); DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>(); // Is it a DNS query? if(dns.type() == DNS::QUERY) { // Let's see if there's any query for an "A" record. for(const auto &query : dns.queries()) { if(query.type() == DNS::A) { // Here's one! Let's add an answer. dns.add_answer( DNS::Resource( query.dname(), "127.0.0.1", DNS::A, query.query_class(), // 777 is just a random TTL 777 ) ); } } // Have we added some answers? if(dns.answers_count() > 0) { // It's a response now dns.type(DNS::RESPONSE); // Recursion is available(just in case) dns.recursion_available(1); // Build our packet auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) / IP(ip.src_addr(), ip.dst_addr()) / UDP(udp.sport(), udp.dport()) / dns; // Send it! sender.send(pkt); } } return true; }
TEST_F(IPTest, DstIPInt) { IP ip; ip.dst_addr("192.155.32.10"); EXPECT_EQ(ip.dst_addr(), "192.155.32.10"); }
TEST_F(IPTest, DstIPString) { IP ip; string string_ip("192.155.32.10"); ip.dst_addr(string_ip); EXPECT_EQ(ip.dst_addr(), IPv4Address(string_ip)); }
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { Mode mode = ((nf_data*)data)->mode; u_int32_t id = ntohl(nfq_get_msg_packet_hdr(nfa)->packet_id); unsigned char *packet; int size = nfq_get_payload(nfa, &packet); std::vector<uint8_t> result; u_int32_t verdict = NF_ACCEPT; try { IP ip = IP(packet, size); //cout << ip.src_addr() << " -> " << ip.dst_addr() << endl; NetworkInterface interface(ip.dst_addr()); IP::address_type interface_addr = interface.addresses().ip_addr; RR *rr = ip.find_pdu<RR>(); if (mode == ROUTER) { if (rr != 0) { //cout << "Adding to existing RR" << endl; } else { create_rr(ip); rr = ip.find_pdu<RR>(); if (is_spoof && ip.src_addr() == IP::address_type("192.168.30.10")) { rr->route().push_back(RREntry(IP::address_type("192.168.100.20"), 42, 42)); } } // TODO Figure out what the magic numbers are for the source address RREntry src_hop(ip.src_addr(), 0x0, 0x0); RREntry last_hop = src_hop; if (rr != 0 && rr->route().size() >= 1) last_hop = rr->route().back(); AITF_packet aitf; if (should_intercept(ip, rr, &aitf)) { //cout << "Intercepting packet" << endl; send_AITF_message(aitf, IP::address_type("192.168.10.100")); verdict = NF_DROP; } else if (is_blocked(last_hop, ip.dst_addr()) || (is_shadow && rr->route().size() > 1 && is_blocked(src_hop, ip.dst_addr()))) { //cout << "Packet blocked" << endl; verdict = NF_DROP; } else if (hosts.isLegacyHost(ip.dst_addr())) { //cout << "Legacy host detected" << endl; if (rr != 0) { //print_route(rr->route()); strip_rr(ip, *rr); } else { //cout << "No RR table present" << endl; } } else { NetworkInterface interface(ip.dst_addr()); rr->route().push_back(RREntry(interface_addr, hash_for_destination(ip.dst_addr(), 0), hash_for_destination(ip.dst_addr(), 1))); if (rr->route().size() > rr->route_capacity()) { //cout << "RR table filled. Dropping packet." << endl; verdict = NF_DROP; } //else print_route(rr->route()); } } else if (mode == HOST) { if (rr != 0) { // Check if this is a bad packet // TODO don't hard code attacker ip addresses bool is_bad = false; try { UDP udp(&rr->payload()[0], rr->payload().size()); RawPDU* raw = udp.find_pdu<RawPDU>(); if (raw != 0) { is_bad = raw->payload()[0] == 1; } } catch (malformed_packet e) { } if (is_bad && is_victim) { if (!last_event_set) { printf("Attack detected\n"); gettimeofday(&last_event, NULL); last_event_set = true; event_delay = 500000; } else { struct timeval now; gettimeofday(&now, NULL); if ((now.tv_sec - last_event.tv_sec) * 1000000 + now.tv_usec - last_event.tv_usec > event_delay) { printf("Enforce sent\n"); print_route(rr->route()); vector<RRFilter> filters; filters.push_back(RRFilter(is_wildcard ? 1 : 0, ip.src_addr(), 0x0, 0x0)); for (int i = 0; i < rr->route().size(); i++) { const RREntry& entry = rr->route().at(i); filters.push_back(RRFilter(is_wildcard ? 1 : 0, entry.address(), entry.random_number_1(), entry.random_number_2())); } AITF_packet enforce(0, 0, 0, 1, filters, IP::address_type("192.168.10.10"), filters.size()); send_AITF_message(enforce, IP::address_type("192.168.10.100")); last_event = now; event_delay = is_aggressive ? 1000000 : 10000000; } } } //print_route(rr->route()); strip_rr(ip, *rr); } else { //cout << "No RR table present" << endl; } } result = ip.serialize(); //cout << endl; } catch (malformed_packet e) { cout << "malformed packet " << e.what() << endl; } return nfq_set_verdict(qh, id, verdict, verdict == NF_DROP ? 0 : result.size(), verdict == NF_DROP ? 0 : &result[0]); }