mejores google configurar cambiar c++ tcp boost-asio impersonation arp

c++ - google - mejores dns



En Boost ASIO, ¿cómo puedo configurar la dirección IP de origen para suplantar la dirección IP de otro servidor? (2)

Tengo un programa de servidor C ++ Boost basado en ASIO y me gustaría poder establecer la dirección IP de origen utilizada por TCP a la de otro servidor. Sé que uno puede leer las direcciones IP de origen y de destino, pero presumiblemente también se pueden configurar.

Presumiblemente, si configuro la dirección IP origen "incorrecta" en el código C ++, habrá cierta interacción con la pila de red. ¿La pila de la red no volverá a establecer la dirección IP de origen a la salida, incluso si el código de C ++ es correcto? ¿Es la forma correcta de hacerlo escribir código C ++ ASIO para elegir una interfaz de red virtual específica? ¿Uno que está configurado con la dirección IP estática "incorrecta"? Lo he visto antes como una forma de controlar la dirección IP de origen. ¿Es eso lo que tengo que hacer en su lugar?

Me pregunto cuáles serían las consecuencias de esto. Tener dos máquinas con la misma dirección IP estática configurada podría hacer que el servidor "normal" deje de funcionar por completo, lo que sería malo.

Tengo puertos de Windows y Linux de mi servidor que puedo usar en caso de que el código propuesto funcione en un sistema operativo y no en el otro. Actualmente me inclino por Kali Linux ya que puedo "arpspoof" el servidor principal y lo apago por un tiempo.


Use la llamada de bind para asignar la dirección IP y el puerto de origen.

Si no llamas a bind antes de connect las selecciones del sistema operativo y vincula la interfaz para ti usando la tabla de enrutamiento.

La dirección IP debe ser la dirección de una de las interfaces de su host. En otras palabras, no puede falsificar su IP de origen utilizando la llamada de bind .


Se puede establecer la dirección IP de origen en una dirección arbitraria en los datos de salida mediante la construcción manual de los encabezados de la capa de transporte y la red, y luego el envío de los encabezados y la carga útil deseada a un socket bruto . El uso de sockets sin formato puede requerir permisos elevados, o puede ser deshabilitado o restringido por el kernel, como en algunas plataformas de Microsoft. Además, debido al handshake de tres vías de TCP y los números de secuencia impredecibles, la eficacia del segmento TCP falsificado, fuera de posibles ataques de restablecimiento de TCP , es cuestionable.

El enrutamiento es un tema diferente y depende de los diversos enrutadores y configuraciones. Por ejemplo, los dispositivos pueden realizar filtros de salida y paquetes de entrega con una dirección de origen que el dispositivo no puede validar. Además, los efectos de un conflicto de direcciones IP pueden variar, pero a menudo da como resultado una conexión intermitente.

Boost.Asio proporciona una basic_raw_socket<Protocol> que espera que un tipo cumpla con el requisito de tipo de protocolo . Por ejemplo, a continuación se muestra el inicio o un protocolo en raw :

struct raw { typedef boost::asio::ip::basic_endpoint<raw> endpoint; int type() const { return SOCK_RAW; } int protocol() const { return IPPROTO_RAW; } int family() const { return PF_INET; } }; boost::asio::basic_raw_socket<raw> socket;

Al tratar con sockets sin formato, la dificultad a menudo no está en el uso de Boost.Asio, sino que más bien tiene que implementar el protocolo de cable de red y transporte. A continuación se muestra un ejemplo mínimo completo en el que traté de mantenerlo lo más simple posible creando un protocolo sin raw y usando basic_raw_socket para enviar un mensaje UDP:

#include <algorithm> #include <iostream> #include <boost/array.hpp> #include <boost/asio.hpp> #include <boost/cstdint.hpp> /// @brief raw socket provides the protocol for raw socket. class raw { public: ///@brief The type of a raw endpoint. typedef boost::asio::ip::basic_endpoint<raw> endpoint; ///@brief The raw socket type. typedef boost::asio::basic_raw_socket<raw> socket; ///@brief The raw resolver type. typedef boost::asio::ip::basic_resolver<raw> resolver; ///@brief Construct to represent the IPv4 RAW protocol. static raw v4() { return raw(IPPROTO_RAW, PF_INET); } ///@brief Construct to represent the IPv6 RAW protocol. static raw v6() { return raw(IPPROTO_RAW, PF_INET6); } ///@brief Default constructor. explicit raw() : protocol_(IPPROTO_RAW), family_(PF_INET) {} ///@brief Obtain an identifier for the type of the protocol. int type() const { return SOCK_RAW; } ///@brief Obtain an identifier for the protocol. int protocol() const { return protocol_; } ///@brief Obtain an identifier for the protocol family. int family() const { return family_; } ///@brief Compare two protocols for equality. friend bool operator==(const raw& p1, const raw& p2) { return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_; } /// Compare two protocols for inequality. friend bool operator!=(const raw& p1, const raw& p2) { return !(p1 == p2); } private: explicit raw(int protocol_id, int protocol_family) : protocol_(protocol_id), family_(protocol_family) {} int protocol_; int family_; }; ///@ brief Mockup ipv4_header for with no options. // // IPv4 wire format: // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-------+-------+-------+-------+-------+-------+-------+------+ --- // |version|header | type of | total length in bytes | ^ // | (4) | length| service | | | // +-------+-------+-------+-------+-------+-------+-------+------+ | // | identification |flags| fragment offset | | // +-------+-------+-------+-------+-------+-------+-------+------+ 20 bytes // | time to live | protocol | header checksum | | // +-------+-------+-------+-------+-------+-------+-------+------+ | // | source IPv4 address | | // +-------+-------+-------+-------+-------+-------+-------+------+ | // | destination IPv4 address | v // +-------+-------+-------+-------+-------+-------+-------+------+ --- // / options (if any) / // +-------+-------+-------+-------+-------+-------+-------+------+ class ipv4_header { public: ipv4_header() { std::fill(buffer_.begin(), buffer_.end(), 0); } void version(boost::uint8_t value) { buffer_[0] = (value << 4) | (buffer_[0] & 0x0F); } void header_length(boost::uint8_t value) { buffer_[0] = (value & 0x0F) | (buffer_[0] & 0xF0); } void type_of_service(boost::uint8_t value) { buffer_[1] = value; } void total_length(boost::uint16_t value) { encode16(2, value); } void identification(boost::uint16_t value) { encode16(4, value); } void dont_fragment(bool value) { buffer_[6] ^= (-value ^ buffer_[6]) & 0x40; } void more_fragments(bool value) { buffer_[6] ^= (-value ^ buffer_[6]) & 0x20; } void fragment_offset(boost::uint16_t value) { // Preserve flags. auto flags = static_cast<uint16_t>(buffer_[6] & 0xE0) << 8; encode16(6, (value & 0x1FFF) | flags); } void time_to_live(boost::uint8_t value) { buffer_[8] = value; } void protocol(boost::uint8_t value) { buffer_[9] = value; } void checksum(boost::uint16_t value) { encode16(10, value); } void source_address(boost::asio::ip::address_v4 value) { auto bytes = value.to_bytes(); std::copy(bytes.begin(), bytes.end(), &buffer_[12]); } void destination_address(boost::asio::ip::address_v4 value) { auto bytes = value.to_bytes(); std::copy(bytes.begin(), bytes.end(), &buffer_[16]); } public: std::size_t size() const { return buffer_.size(); } const boost::array<uint8_t, 20>& data() const { return buffer_; } private: void encode16(boost::uint8_t index, boost::uint16_t value) { buffer_[index] = (value >> 8) & 0xFF; buffer_[index + 1] = value & 0xFF; } boost::array<uint8_t, 20> buffer_; }; void calculate_checksum(ipv4_header& header) { // Zero out the checksum. header.checksum(0); // Checksum is the 16-bit one''s complement of the one''s complement sum of // all 16-bit words in the header. // Sum all 16-bit words. auto data = header.data(); auto sum = std::accumulate<boost::uint16_t*, boost::uint32_t>( reinterpret_cast<boost::uint16_t*>(&data[0]), reinterpret_cast<boost::uint16_t*>(&data[0] + data.size()), 0); // Fold 32-bit into 16-bits. while (sum >> 16) { sum = (sum & 0xFFFF) + (sum >> 16); } header.checksum(~sum); } ///@brief Mockup IPv4 UDP header. // // UDP wire format: // // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-------+-------+-------+-------+-------+-------+-------+------+ --- // | source port | destination port | ^ // +-------+-------+-------+-------+-------+-------+-------+------+ 8 bytes // | length | checksum | v // +-------+-------+-------+-------+-------+-------+-------+------+ --- // / data (if any) / // +-------+-------+-------+-------+-------+-------+-------+------+ class udp_header { public: udp_header() { std::fill(buffer_.begin(), buffer_.end(), 0); } void source_port(boost::uint16_t value) { encode16(0, value); } void destination_port(boost::uint16_t value) { encode16(2, value); } void length(boost::uint16_t value) { encode16(4, value); } void checksum(boost::uint16_t value) { encode16(6, value); } public: std::size_t size() const { return buffer_.size(); } const boost::array<uint8_t, 8>& data() const { return buffer_; } private: void encode16(boost::uint8_t index, boost::uint16_t value) { buffer_[index] = (value >> 8) & 0xFF; buffer_[index + 1] = value & 0xFF; } boost::array<uint8_t, 8> buffer_; }; int main() { boost::asio::io_service io_service; // Create all I/O objects. boost::asio::ip::udp::socket receiver(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)); boost::asio::basic_raw_socket<raw> sender(io_service, raw::endpoint(raw::v4(), 0)); const auto receiver_endpoint = receiver.local_endpoint(); // Craft a UDP message with a payload ''hello'' coming from // 8.8.8.8:54321 const boost::asio::ip::udp::endpoint spoofed_endpoint( boost::asio::ip::address_v4::from_string("8.8.8.8"), 54321); const std::string payload = "hello"; // Create the UDP header. udp_header udp; udp.source_port(spoofed_endpoint.port()); udp.destination_port(receiver_endpoint.port()); udp.length(udp.size() + payload.size()); // Header + Payload udp.checksum(0); // Optioanl for IPv4 // Create the IPv4 header. ipv4_header ip; ip.version(4); // IPv4 ip.header_length(ip.size() / 4); // 32-bit words ip.type_of_service(0); // Differentiated service code point auto total_length = ip.size() + udp.size() + payload.size(); ip.total_length(total_length); // Entire message. ip.identification(0); ip.dont_fragment(true); ip.more_fragments(false); ip.fragment_offset(0); ip.time_to_live(4); ip.source_address(spoofed_endpoint.address().to_v4()); ip.destination_address(receiver_endpoint.address().to_v4()); ip.protocol(IPPROTO_UDP); calculate_checksum(ip); // Gather up all the buffers and send through the raw socket. boost::array<boost::asio::const_buffer, 3> buffers = {{ boost::asio::buffer(ip.data()), boost::asio::buffer(udp.data()), boost::asio::buffer(payload) }}; auto bytes_transferred = sender.send_to(buffers, raw::endpoint(receiver_endpoint.address(), receiver_endpoint.port())); assert(bytes_transferred == total_length); // Read on the reciever. std::vector<char> buffer(payload.size(), ''/0''); boost::asio::ip::udp::endpoint sender_endpoint; bytes_transferred = receiver.receive_from( boost::asio::buffer(buffer), sender_endpoint); // Verify. assert(bytes_transferred == payload.size()); assert(std::string(buffer.begin(), buffer.end()) == payload); assert(spoofed_endpoint == sender_endpoint); // Print endpoints. std::cout << "Actual sender endpoint: " << sender.local_endpoint() << "/n" "Receiver endpoint: " << receiver.local_endpoint() << "/n" "Receiver''s remote endpoint: " << sender_endpoint << std::endl; }

Salida:

$ sudo ./a.out Actual sender endpoint: 0.0.0.0:255 Receiver endpoint: 0.0.0.0:44806 Receiver''s remote endpoint: 8.8.8.8:54321

Como se indica en la salida, aunque el punto extremo del remitente verdadero es 0.0.0.0:255 , el receptor cree que el punto extremo del remitente es 8.8.8.8:54321 .