Answer the question
In order to leave comments, you need to log in
Linux kernel module: changing the tcp destination address of a packet does not work, how to fix it?
I form and send a TCP packet via RAW-socket( socket(PF_INET, SOCK_RAW, IPPROTO_TCP) ) to the specified IP (main_server_ip).
The Linux kernel module is running on the machine, which catches TCP packets to this IP address (main_server_ip) and changes the destination address to another one (other_server_ip). Packets do not arrive at their destination. I intercept packets between machines with Wireshark and observe the picture: the IP header of the packet contains the correct IP address (other_server_ip), but the Ethenet headers contain the MAC address corresponding to the original IP address (other_server_ip). That is, it turns out that the IP address has changed, but the MAC has remained from the old IP address.
I can't figure out what this is connected with and how to fix it...
If you send data via regular sockets, then everything works successfully. Kernel version: 3.13.0-65-generic.
Here is the code I use to change the destination IP address in the kernel module:
struct iphdr *ip_header = (struct iphdr *) skb_network_header(skb);
unsigned int dest_ip = (unsigned int) ip_header->daddr;
struct tcphdr *tcp_header;
if (dest_ip == main_server_ip) {
printk(KERN_INFO "Protocol: %d\n", ip_header->protocol);
if (ip_header->protocol == 6) {
tcp_header = (struct tcphdr*) ((char*) ip_header + (ip_header->ihl * 4));
tcp_header->check = 0;
}
unsigned char* pack = ((char*) ip_header + (ip_header->ihl * 4));
tcp_len = ntohs(ip_header->tot_len) - (ip_header->ihl * 4);
ip_header->daddr = other_server_ip;
if (ip_header->protocol == 6) {
tcp_header = (struct tcphdr*) ((char*) ip_header + (ip_header->ihl * 4));
len = skb->len;
tcp_header->check = 0;
tcp_header->check = tcp_v4_check(len - 4 * ip_header->ihl,
ip_header->saddr, ip_header->daddr,
csum_partial((char *) tcp_header, len - 4 * ip_header->ihl,
0));
skb->ip_summed = CHECKSUM_NONE;
ip_header->check = 0;
ip_header->check = ip_fast_csum((u8 *) ip_header, ip_header->ihl);
printk(KERN_INFO "IP addr after change: %u", ip_header->daddr);
return NF_ACCEPT;
}
}
Answer the question
In order to leave comments, you need to log in
but the MAC address is registered in the Ethenet headers - the address corresponding to the original IP address
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question