I am working on C project where I have to capture the packets,encrypt and forward it. Scenario is client A (windows) sends data to client B(windows) and in between there is a server (ubuntu) where my application runs as LAN (encrypt)& WAN(decrypt). For testing purpose (only ecrypt part LAN)I am running it on a single system (unbuntu) sending text from one terminal to another terminal using netcat. Now I able to capture the text and encrypts it as well but it does not forward the encrypted data instead it forwards the actual text to other terminal. When I put debugging points I found out that the moment I send the text from source it instantly receives at the destination while my code which also capture the text is still in processing mode. It seems like that it creates a copy of it, one which forwards it directly to other terminal and other one which my application captures. Can anyone please guide me how I can I stop it sending to the destination and force it to forward the encrypted data. I want the packet to go through my application encrypts it and then forward the encrypted data. I took help from chatgpt and it is telling me that it is related with iptables, now I am not familiar with it so I followed the examples given by chatgpt but that doesnot worked.I have remove few part due the word count.LAN code that capture data encrypts it and forward it.
#define LOG_ERROR(format, ...) fprintf(logFile, (format), ##__VA_ARGS__); fflush(logFile)#define BUFF_SIZE 65536void calculate_transport_checksum(unsigned char* transport_segment, struct iphdr* iph, int segment_len);int total_len = 0, send_len;static const unsigned char aes_key[] = "0123456789abcdef0123456789abcdef"; unsigned char aes_iv[] = "abcdef9876543210";struct pseudo_header { u_int32_t source_address; u_int32_t dest_address; u_int8_t placeholder; u_int8_t protocol; u_int16_t tcp_length;};void debug_print_packet_size(unsigned int packet_size, int buffer_size) { printf("Reported IP packet size: %u bytes, Buffer size: %d bytes\n", packet_size, buffer_size);}int set_promiscuous_mode(char *interface_name, int sock, int enable) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, interface_name, IFNAMSIZ - 1); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { LOG_ERROR("Error in SIOCGIFFLAGS for %s: %s\n", interface_name, strerror(errno)); return -1; } if (enable) { ifr.ifr_flags |= IFF_PROMISC; } else { ifr.ifr_flags &= ~IFF_PROMISC; } if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { LOG_ERROR("Error in SIOCSIFFLAGS for %s: %s\n", interface_name, strerror(errno)); return -1; } LOG_ERROR("Promiscuous mode %s on interface %s\n", enable ? "enabled" : "disabled", interface_name); fflush(logFile); return 0;}void get_eth_index() { struct ifreq if_idx; memset(&if_idx, 0, sizeof(if_idx)); strncpy(if_idx.ifr_name, "enp0s31f6", IFNAMSIZ - 1); int temp_sock = socket(AF_INET, SOCK_DGRAM, 0); if(temp_sock < 0) { perror("Error opening socket for getting interface index"); return; } if (ioctl(temp_sock, SIOCGIFINDEX, &if_idx) < 0){ LOG_ERROR("Error in SIOCGIFINDEX: %s\n", strerror(errno)); }else{ printf("Interface index: %d\n", if_idx.ifr_ifindex); } close(temp_sock); }void get_mac() { int fd; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, "enp0s31f6", IFNAMSIZ-1); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket(AF_INET, SOCK_DGRAM, 0) failed"); return; } if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { perror("SIOCGIFHWADDR ioctl error"); close(fd); return; } close(fd); printf("MAC = %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", (unsigned char)ifr.ifr_hwaddr.sa_data[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1], (unsigned char)ifr.ifr_hwaddr.sa_data[2], (unsigned char)ifr.ifr_hwaddr.sa_data[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4], (unsigned char)ifr.ifr_hwaddr.sa_data[5]); printf("ethernet packaging start ... \n"); struct ethhdr *eth = (struct ethhdr *)(sendbuff); eth->h_dest[0] = WAN_MAC0; eth->h_dest[1] = WAN_MAC1; eth->h_dest[2] = WAN_MAC2; eth->h_dest[3] = WAN_MAC3; eth->h_dest[4] = WAN_MAC4; eth->h_dest[5] = WAN_MAC5; eth->h_source[0] = CLIENT_A_MAC0; eth->h_source[1] = CLIENT_A_MAC1; eth->h_source[2] = CLIENT_A_MAC2; eth->h_source[3] = CLIENT_A_MAC3; eth->h_source[4] = CLIENT_A_MAC4; eth->h_source[5] = CLIENT_A_MAC5; eth->h_proto = htons(ETH_P_IP); printf("ethernet packaging done.\n"); total_len += sizeof(struct ethhdr);}void get_icmp() { struct icmphdr *icmp = (struct icmphdr *)(sendbuff + sizeof(struct iphdr) + sizeof(struct ethhdr)); icmp->type = ICMP_ECHO; icmp->code = 0; icmp->un.echo.id = htons(1234); icmp->un.echo.sequence = htons(1); icmp->checksum = 0; total_len += sizeof(struct icmphdr);}unsigned short calculate_checksum(unsigned short* ptr, int nbytes) { long sum; unsigned short oddbyte; short answer; sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } if (nbytes == 1) { oddbyte = 0; *((u_char*)&oddbyte) = *(u_char*)ptr; sum += oddbyte; } sum = (sum >> 16) + (sum & 0xffff); sum = sum + (sum >> 16); answer = (short)~sum; return answer;}void get_ip() { int temp_sock = socket(AF_INET, SOCK_DGRAM, 0); if (temp_sock < 0) { perror("Error opening temp socket for getting IP address"); return; } memset(&ifreq_ip, 0, sizeof(ifreq_ip)); strncpy(ifreq_ip.ifr_name, "enp0s31f6", IFNAMSIZ-1); if (ioctl(temp_sock, SIOCGIFADDR, &ifreq_ip) < 0) { perror("SIOCGIFADDR ioctl error"); } else { printf("%s\n", inet_ntoa(((struct sockaddr_in *)&(ifreq_ip.ifr_addr))->sin_addr)); } close(temp_sock); struct iphdr *iph = (struct iphdr *)(sendbuff + sizeof(struct ethhdr)); iph->ihl = 5; iph->version = 4; iph->tos = 16; iph->id = htons(10201); iph->ttl = 64; iph->protocol = IPPROTO_ICMP; iph->saddr = inet_addr(inet_ntoa((((struct sockaddr_in *)&(ifreq_ip.ifr_addr))->sin_addr))); iph->daddr = inet_addr("192.168.10.16"); unsigned short checksum = calculate_checksum((unsigned short *)(sendbuff + sizeof(struct ethhdr)), (sizeof(struct iphdr) / 2)); fprintf(logFile, "Calculated IP checksum: 0x%04x\n", checksum); fflush(logFile); total_len += sizeof(struct iphdr); get_icmp(); iph->tot_len = htons(total_len - sizeof(struct ethhdr)); iph->check = htons(calculate_checksum((unsigned short *)(sendbuff + sizeof(struct ethhdr)), sizeof(struct iphdr) / 2));}void enable_iptables_rules() { system("sudo iptables -t nat -A POSTROUTING -o enp0s31f6 -j MASQUERADE"); system("sudo iptables -A FORWARD -i enp0s31f6 -o enp0s31f6 -m state --state RELATED,ESTABLISHED -j ACCEPT"); system("sudo iptables -A FORWARD -i enp0s31f6 -o enp0s31f6 -j ACCEPT"); }void enable_ip_forwarding() { int fd; char path[] = "/proc/sys/net/ipv4/ip_forward"; fd = open(path, O_WRONLY); if (fd == -1) { perror("Error opening /proc/sys/net/ipv4/ip_forward"); } if (write(fd, "1", 1) == -1) { perror("Error writing to /proc/sys/net/ipv4/ip_forward"); exit(EXIT_FAILURE); } close(fd); printf("IP forwarding enabled.\n");}void remove_iptables_drop_rule() { system("sudo iptables -D OUTPUT -p icmp --icmp-type echo-request -d 192.168.10.16 -j DROP"); system("sudo iptables -D OUTPUT -p tcp --dport 1234 -d 192.168.10.16 -j DROP"); system("sudo iptables -D OUTPUT -p udp --dport 1234 -d 192.168.10.16 -j DROP");}void setup_iptables_drop_rule() { system("sudo iptables -A OUTPUT -p icmp --icmp-type echo-request -d 192.168.10.16 -j DROP"); system("sudo iptables -A OUTPUT -p tcp --dport 1234 -j DROP"); system("sudo iptables -A OUTPUT -p udp --dport 1234 -j DROP");}void handle_signal(int signal) { printf("Signal received: %d\n", signal); remove_iptables_drop_rule(); if (set_promiscuous_mode("enp0s31f6", sock_raw, 0) < 0) { fprintf(stderr, "Failed to disable promiscuous mode for interface %s\n", "enp0s31f6"); } else { printf("Promiscuous mode disabled on interface %s\n", "enp0s31f6"); } fclose(logFile); close(sock_raw); free(sendbuff); exit(signal);}void setup_signal_handling() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handle_signal; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGQUIT, &sa, NULL);}int main() { setup_signal_handling(); enable_iptables_rules(); enable_ip_forwarding(); setup_iptables_drop_rule(); logFile = fopen("logfile.txt", "w"); if (logFile == NULL) { perror("Failed to open log file"); exit(EXIT_FAILURE); } int raw_socket; ssize_t data_size; unsigned char *buffer = (unsigned char *)malloc(BUFF_SIZE); char *interface_name = "enp0s31f6"; if (buffer == NULL) { perror("Failed to allocate memory for buffer"); exit(EXIT_FAILURE); } raw_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if(raw_socket < 0) { printf("Error: %s\n", strerror(errno)); fclose(logFile); exit(EXIT_FAILURE); } if (set_promiscuous_mode(interface_name, raw_socket, 1) < 0) { close(raw_socket); fclose(logFile); exit(EXIT_FAILURE); } printf("Promiscuous mode enabled on interface %s\n", interface_name); if (!buffer) { perror("Memory allocation failed for buffer"); set_promiscuous_mode("enp0s31f6", raw_socket, 0); close(raw_socket); fclose(logFile); exit(EXIT_FAILURE); } sendbuff = (unsigned char *)malloc(4096); if (sendbuff == NULL) { perror("Failed to allocate memory for sendbuff"); close(raw_socket); free(buffer); return 1; } memset(sendbuff, 0, 4096); get_eth_index(); get_mac(); get_ip(); struct sockaddr_ll sadr_ll; sadr_ll.sll_ifindex = ifreq_i.ifr_ifindex; sadr_ll.sll_halen = ETH_ALEN; sadr_ll.sll_addr[0] = CLIENT_B_MAC0; sadr_ll.sll_addr[1] = CLIENT_B_MAC1; sadr_ll.sll_addr[2] = CLIENT_B_MAC2; sadr_ll.sll_addr[3] = CLIENT_B_MAC3; sadr_ll.sll_addr[4] = CLIENT_B_MAC4; sadr_ll.sll_addr[5] = CLIENT_B_MAC5; printf("Packet capture started...\n"); while(1) { data_size = recvfrom(raw_socket, buffer, 65536, 0, NULL, NULL); if(data_size < 0) { LOG_ERROR("Recvfrom error, code: %s\n", strerror(errno)); break; } LOG_ERROR("Received packet size: %zd bytes\n", data_size); process_packet(buffer, data_size); } if (set_promiscuous_mode(interface_name, raw_socket, 0) < 0) { fprintf(stderr, "Failed to disable promiscuous mode for interface %s\n", interface_name); } else { printf("Promiscuous mode disabled on interface %s\n", interface_name); } fclose(logFile); close(raw_socket); free(buffer); free(sendbuff); return 0;}void handle_packet(int protocol, unsigned char* buffer, int size) { struct iphdr* iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); int ip_header_len = iph->ihl * 4; printf("Handling packet with protocol: %d\n", protocol); switch (protocol) { case IPPROTO_ICMP: { printf("ICMP packet processing\n"); struct icmphdr* icmph = (struct icmphdr*)(buffer + sizeof(struct ethhdr) + ip_header_len); printf("ICMP Type: %d, Code: %d\n", icmph->type, icmph->code); break; } case IPPROTO_TCP: { printf("TCP packet processing\n"); struct tcphdr* tcph = (struct tcphdr*)(buffer + sizeof(struct ethhdr) + ip_header_len); printf("TCP Source Port: %u, Destination Port: %u\n", ntohs(tcph->source), ntohs(tcph->dest)); break; } case IPPROTO_UDP: { printf("UDP packet processing\n"); struct udphdr* udph = (struct udphdr*)(buffer + sizeof(struct ethhdr) + ip_header_len); printf("UDP Source Port: %u, Destination Port: %u\n", ntohs(udph->source), ntohs(udph->dest)); break; } default: printf("Other protocol: %d\n", protocol); break; }}void process_packet(unsigned char* buffer, int size) { printf("Size of packet received: %d\n", size); if (size < sizeof(struct ethhdr)) { printf("Packet too small to contain Ethernet header\n"); return; } struct ethhdr *eth = (struct ethhdr*)buffer; if (ntohs(eth->h_proto) != ETH_P_IP) { printf("Non-IP packet received, protocol: 0x%04x\n", ntohs(eth->h_proto)); return; } struct iphdr* iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); int ip_header_len = iph->ihl * 4; printf("IP header length: %d\n", ip_header_len); if (size < sizeof(struct ethhdr) + sizeof(struct iphdr)) { printf("Packet too small to contain IP header\n"); return; } printf("Packet protocol: %u\n", iph->protocol); switch (iph->protocol) { case IPPROTO_ICMP: handle_icmp_packet(buffer, size); break; case IPPROTO_TCP: handle_tcp_packet(buffer, size); break; case IPPROTO_UDP: handle_udp_packet(buffer, size); break; default: printf("Non-ICMP/TCP/UDP packet, protocol: %d\n", iph->protocol); break; } int protocol = iph->protocol; printf("Packet protocol: %d\n", protocol); printf("Packet captured, size: %d bytes, protocol: %d\n", size, iph->protocol); unsigned int transport_header_len = 0; if (iph->ihl < 5 || ip_header_len > size - sizeof(struct ethhdr)) { printf("Invalid IP header length: %d\n", iph->ihl); return; } int total_length = ntohs(iph->tot_len); if (total_length > size- sizeof(struct ethhdr)) { printf("Error: IP total length (%u) is greater than the actual packet size (%d).\n", total_length, size - sizeof(struct ethhdr)); return; } if (ip_header_len > total_length) { printf("Error: IP header length is greater than the total length reported in the IP header. Possible error in packet formation.\n"); return; } printf("Packet captured, size: %d bytes, protocol: %d\n", size, iph->protocol); if ((ntohs(iph->frag_off) & 0x1FFF) != 0) { LOG_ERROR("Fragmented packet received, skipping.\n"); printf("Fragmented packet received, skipping.\n"); return; } if (size < (int)sizeof(struct iphdr)) { printf("Received packet size too small to contain an IP header\n"); return; } if (iph->protocol == IPPROTO_ICMP || iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) { printf("Packet captured, Protocol: %d, Size: %d bytes\n", iph->protocol, size); } else { printf("Non-ICMP/TCP/UDP packet. Protocol number: %d\n", iph->protocol); return; } int payload_len = 0; unsigned char* payload = NULL; unsigned char* encrypted_payload = NULL; unsigned char* new_packet; int new_packet_size; if (!RAND_bytes(aes_iv, sizeof(aes_iv))) { LOG_ERROR("Failed to generate IV\n"); //fprintf(stderr, "Failed to generate IV\n"); return; } if (!filter_packet(buffer, size)) { printf("Packet filtered out.\n"); return; } if (iph->protocol == IPPROTO_TCP) { struct tcphdr *tcph = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + iph->ihl * 4); if (ntohs(tcph->source) != 1234 && ntohs(tcph->dest) != 1234) return; transport_header_len = tcph->doff * 4; } else if (iph->protocol == IPPROTO_UDP) { struct udphdr *udph = (struct udphdr *)(buffer + sizeof(struct ethhdr) + iph->ihl * 4); transport_header_len = sizeof(struct udphdr); } else if (iph->protocol == IPPROTO_ICMP) { struct icmphdr *icmph = (struct icmphdr *)(buffer + sizeof(struct ethhdr) + iph->ihl * 4); transport_header_len = sizeof(struct icmphdr); } struct tcphdr *tcph = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + iph->ihl * 4); if (ntohs(tcph->source) != 1234 && ntohs(tcph->dest) != 1234) return; printf("Netcat packet captured, size: %d bytes\n", size); if (extract_payload(buffer, size, &payload, &payload_len) != 0) { printf("Failed to extract payload\n"); return; } printf("Original payload (text received by netcat):\n"); for (int i = 0; i < payload_len; i++) { printf("%c", payload[i]); } printf("\n"); encrypted_payload = (unsigned char*)malloc(payload_len); if (!encrypted_payload) { printf("Failed to allocate memory for encrypted payload"); return; } int encrypted_payload_len = encrypt_payload(payload, payload_len, encrypted_payload); if (encrypted_payload_len < 0) { printf("Encryption failed\n"); free(encrypted_payload); return; } printf("Encrypted payload:\n"); for (int i = 0; i < encrypted_payload_len; i++) { printf("%02x ", encrypted_payload[i]); } printf("\n"); memcpy(buffer + sizeof(struct ethhdr) + ip_header_len + transport_header_len, encrypted_payload, encrypted_payload_len); free(encrypted_payload); encrypted_payload = NULL; iph->tot_len = htons(ip_header_len + transport_header_len + encrypted_payload_len); iph->check = 0; iph->check = calculate_checksum((unsigned short*)iph, iph->ihl * 4); if (iph->protocol == IPPROTO_TCP) { struct tcphdr *tcph = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + iph->ihl * 4); tcph->check = 0; calculate_transport_checksum((unsigned char*)tcph, iph, transport_header_len + encrypted_payload_len); } else if (iph->protocol == IPPROTO_UDP) { struct udphdr *udph = (struct udphdr *)(buffer + sizeof(struct ethhdr) + ip_header_len); udph->check = 0; calculate_transport_checksum((unsigned char*)udph, iph, sizeof(struct udphdr) + encrypted_payload_len); } else if (iph->protocol == IPPROTO_ICMP) { struct icmphdr *icmph = (struct icmphdr *)(buffer + ip_header_len); memcpy(icmph + 1, encrypted_payload, encrypted_payload_len); iph->tot_len = htons(ip_header_len + sizeof(struct icmphdr) + encrypted_payload_len); } printf("Payload encrypted: New size %d\n", encrypted_payload_len); LOG_ERROR("Encrypted payload length: %d\n", encrypted_payload_len); reconstruct_packet(buffer, size); LOG_ERROR("Packet reconstructed with new total length: %d\n", ntohs(iph->tot_len)); printf("Buffer content before forwarding:\n"); for (int i = 0; i < 20; i++) { printf("%02x ", buffer[i]); } printf("\n"); remove_iptables_drop_rule(); printf("IPTables rules removed, forwarding packet...\n"); forward_packet(buffer, ntohs(iph->tot_len) + sizeof(struct ethhdr)); free(encrypted_payload); encrypted_payload = NULL;}int filter_packet(const unsigned char *buffer, int bufsize) { struct iphdr *ip_header = (struct iphdr *)(buffer + sizeof(struct ethhdr)); printf("Received packet with protocol: %d\n", ip_header->protocol); int ip_header_length = ip_header->ihl * 4; printf("Packet protocol: %u\n", ip_header->protocol); printf("IPPROTO_ICMP: %u\n", IPPROTO_ICMP); if (ip_header->protocol == IPPROTO_ICMP) { printf("ICMP packet accepted.\n"); return 1; } else if (ip_header->protocol == IPPROTO_TCP) { printf("TCP packet accepted.\n"); struct tcphdr *tcp_header = (struct tcphdr *)(buffer + ip_header_length); if (ntohs(tcp_header->source) == 80 || ntohs(tcp_header->dest) == 80) { printf("HTTP packet\n"); return 1; } if (ntohs(tcp_header->source) == 1234 || ntohs(tcp_header->dest) == 1234) { printf("netcat packet\n"); } } else if (ip_header->protocol == IPPROTO_UDP) { printf("UDP packet accepted.\n"); struct udphdr *udp_header = (struct udphdr *)(buffer + ip_header_length); if (ntohs(udp_header->source) == 53 || ntohs(udp_header->dest) == 53) { printf("DNS packet\n"); return 1; } } else { printf("Non-ICMP/TCP/UDP packet. Protocol number: %d\n", ip_header->protocol); return 0; } int accepted = (ip_header->protocol == IPPROTO_ICMP || ip_header->protocol == IPPROTO_TCP || ip_header->protocol == IPPROTO_UDP); printf("Filtering: Protocol %d, %s\n", ip_header->protocol, (accepted ? "Accepted" : "Rejected")); return accepted ? 1 : 0;}int extract_payload(unsigned char* buffer, int size, unsigned char** payload, int* payload_size) { if (buffer == NULL || size <= 0 || payload == NULL || payload_size == NULL) { printf("Invalid parameters for payload extraction.\n"); return -1; } struct iphdr *ip_header = (struct iphdr *)(buffer + sizeof(struct ethhdr)); *payload_size = 0; unsigned int ip_header_len = ip_header->ihl * 4; printf("Extracting payload: Original packet size %d, IP header length %u\n", size, ip_header_len); if (size < sizeof(struct iphdr)) { fprintf(stderr, "Packet too small for IP header.\n"); return -1; } if (ip_header_len < sizeof(struct iphdr)) { fprintf(stderr, "Invalid IP header length: %u\n", ip_header_len); return -1; } unsigned int total_length = ntohs(ip_header->tot_len); printf("IP Header Length: %u bytes\n", ip_header_len); printf("Total Length from IP header: %u bytes\n", total_length); printf("Received buffer size: %d bytes\n", size); if (total_length <= ip_header_len || total_length > size - sizeof(struct ethhdr)) { printf("Invalid total length in IP header: %u bytes, buffer size: %d bytes\n", total_length, size); return -1; } unsigned int transport_header_len = 0; unsigned int total_packet_size = ntohs(ip_header->tot_len); printf("total_packet_size: %u, buffer size: %d, ip_header_len: %u\n", total_packet_size, size, ip_header_len); if (total_packet_size > size || total_packet_size < ip_header_len) { printf("Invalid packet size: %u bytes (total packet size) is larger than buffer size: %d bytes or smaller than IP header size: %u bytes.\n", total_packet_size, size, ip_header_len); return -1; } printf("Valid packet size: %u bytes, Buffer size: %d bytes, IP header size: %u bytes\n", total_packet_size, size, ip_header_len); unsigned int packet_size = ntohs(ip_header->tot_len); debug_print_packet_size(packet_size, size); if (size < sizeof(struct iphdr) || packet_size > size) { printf("Packet size is larger than the buffer size or too small to be valid.\n"); return -1; } if (ip_header->protocol == IPPROTO_TCP) { struct tcphdr *tcp_header = (struct tcphdr *)(buffer + sizeof(struct ethhdr) + ip_header_len); transport_header_len = tcp_header->doff * 4; } else if (ip_header->protocol == IPPROTO_UDP) { transport_header_len = sizeof(struct udphdr); } else if (ip_header->protocol == IPPROTO_ICMP) { transport_header_len = sizeof(struct icmphdr); } if (total_length <= ip_header_len + transport_header_len) { printf("Total length is less than the combined length of IP and transport headers.\n"); return -1; } *payload = buffer + sizeof(struct ethhdr) + ip_header_len + transport_header_len; *payload_size = total_length - ip_header_len - transport_header_len; if (*payload_size <= 0) { printf("Negative payload size calculated. This should not happen.\n"); return -1; } printf("Payload extracted: Size %d\n", *payload_size); return 0; }int encrypt_payload(unsigned char* buffer, int size, unsigned char* encrypted_payload) { if (buffer == NULL || size <= 0 || encrypted_payload == NULL) { return -1; } printf("Encrypting payload: Original size %d\n", size); printf("Original data: "); for (int i = 0; i < size && i < 16; i++) { printf("%02x ", buffer[i]); } printf("\n"); if (size <= 0 || encrypted_payload == NULL) return -1; printf("Encrypting payload: Original size %d\n", size); printf("Original data: "); for (int i = 0; i < size && i < 16; i++) { printf("%02x ", buffer[i]); } printf("\n"); printf("Encrypting payload...\n"); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) { LOG_ERROR("EVP_CIPHER_CTX_new failed\n"); return -1; } if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, aes_key, aes_iv)) { EVP_CIPHER_CTX_free(ctx); return -2; } int len; if (1 != EVP_EncryptUpdate(ctx, encrypted_payload, &len, buffer, size)) { EVP_CIPHER_CTX_free(ctx); return -3; } int final_len; if (1 != EVP_EncryptFinal_ex(ctx, encrypted_payload + len, &final_len)) { EVP_CIPHER_CTX_free(ctx); return -4; } printf("Encrypted data: "); for (int i = 0; i < len && i < 16; i++) { printf("%02x ", (encrypted_payload)[i]); } printf("\n"); printf("Encryption successful, len: %d, final_len: %d\n", len, final_len); EVP_CIPHER_CTX_free(ctx); return len + final_len; } void reconstruct_packet(unsigned char* buffer, int size) { struct iphdr* iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); int ip_header_len = iph->ihl * 4; if (size < ip_header_len) { LOG_ERROR("Packet size is too small to reconstruct\n"); return; } int payload_size = ntohs(iph->tot_len) - ip_header_len; int new_total_length = ip_header_len + payload_size; iph->tot_len = htons(new_total_length); iph->check = 0; iph->check = calculate_checksum((unsigned short*)iph, ip_header_len); if (iph->protocol == IPPROTO_TCP) { struct tcphdr* tcph = (struct tcphdr*)(buffer + sizeof(struct ethhdr) + ip_header_len); tcph->check = 0; calculate_transport_checksum(buffer + sizeof(struct ethhdr), iph, payload_size + ip_header_len); } else if (iph->protocol == IPPROTO_UDP) { struct udphdr* udph = (struct udphdr*)(buffer + sizeof(struct ethhdr) + ip_header_len); udph->check = 0; calculate_transport_checksum(buffer + sizeof(struct ethhdr), iph, payload_size + ip_header_len); } LOG_ERROR("Packet reconstructed: New total length %d\n", ntohs(iph->tot_len));}void calculate_transport_checksum(unsigned char* transport_segment, struct iphdr* iph, int segment_len) { unsigned short *src_addr = (unsigned short *)&iph->saddr; unsigned short *dest_addr = (unsigned short *)&iph->daddr; struct pseudo_header psh = {0}; psh.source_address = iph->saddr; psh.dest_address = iph->daddr; psh.placeholder = 0; psh.protocol = iph->protocol; psh.tcp_length = htons(segment_len); int psize = sizeof(struct pseudo_header) + segment_len; unsigned char* pseudogram = malloc(psize); if (pseudogram == NULL) { fprintf(stderr, "Failed to allocate memory for pseudogram\n"); return; } memcpy(pseudogram, &psh, sizeof(struct pseudo_header)); memcpy(pseudogram + sizeof(struct pseudo_header), transport_segment, segment_len); if (iph->protocol == IPPROTO_TCP) { struct tcphdr* tcph = (struct tcphdr*)transport_segment; tcph->check = 0; tcph->check = calculate_checksum((unsigned short*)pseudogram, psize); } else if (iph->protocol == IPPROTO_UDP) { struct udphdr* udph = (struct udphdr*)transport_segment; udph->check = 0; udph->check = calculate_checksum((unsigned short*)pseudogram, psize); } free(pseudogram);}void forward_packet(unsigned char* buffer, int size) { printf("Forwarding packet: Size %d\n", size); if (sendto(sock_raw, buffer, size, 0, (struct sockaddr*)&sadr_ll, sizeof(sadr_ll)) < 0) { LOG_ERROR("sendto failed: %s\n", strerror(errno)); fflush(logFile); }}
I entered text abc from one terminal and it instantly receive text abc to another terminal. The output of my applicationOUTPUTabc
Encrypting payload: Original size 4Original data: 61 62 63 0aEncrypting payload: Original size 4Original data: 61 62 63 0aEncrypting payload...Encrypted data: 47 5b 0d bfEncryption successful,