[英]Sending a raw tcp packet with syn flag set just goes through the lo interface, not eth0 as I want
I would like to send a syn packet to my httpd server and get a responding syn-ack packet. 我想发送一个syn数据包到我的httpd服务器并获得响应的syn-ack数据包。 But when I monitor with Wireshark, the packet is beeing sent by my local interface,
lo
and not eth0
. 但是,当我使用Wireshark监控,数据包与否有关我的本地接口,发送
lo
,而不是eth0
。
I have tried to set some different values in setsockopt
as you can see in the code below, but none seems to work, it is always using the lo
interface and not eth0
. 我已经尝试在
setsockopt
设置一些不同的值,如下面的代码所示,但似乎没有一个工作,它总是使用lo
接口而不是eth0
。 I don't know if it something wrong in the tcp packet that makes it go through local interface, or if it is something else. 我不知道tcp数据包是否有什么问题导致它通过本地接口,或者是否是其他东西。
#include <cstdlib>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#define PCKT_LEN 8192
unsigned short csum(unsigned short *buf, int len) {
unsigned long sum;
for(sum=0; len>0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
int main(int argc, char** argv) {
char *buffer = new char[PCKT_LEN]();
class iphdr *ip = (struct iphdr *) buffer;
class tcphdr *tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr));
class sockaddr_in sin;
int sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sd < 0) {
perror("socket() error");
exit(-1);
} else {
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
}
sin.sin_family = AF_INET; // Address family
sin.sin_port = htons(atoi("2345")); // Source port
inet_pton(AF_INET, "192.168.1.11", &(sin.sin_addr.s_addr)); // Dest IP - ERROR WAS WRONG IP
ip->ihl = 5;
ip->version = 4;
ip->tos = 16;
ip->tot_len = sizeof(class iphdr) + sizeof(class tcphdr);
ip->id = htons(54321);
ip->frag_off = 0;
ip->ttl = 32;
ip->protocol = 6; // TCP
ip->check = 0; // Done by kernel
inet_pton(AF_INET, "192.168.1.10", &(ip->saddr)); // Source IP
inet_pton(AF_INET, "192.168.1.11", &(ip->daddr)); // Destination IP
// The TCP structure
tcp->source = htons(atoi("2345"));
tcp->dest = htons(atoi("80")); // Destination port
tcp->seq = htonl(1);
tcp->ack_seq = random();
tcp->doff = 5;
tcp->syn = 1;
tcp->ack = 0;
tcp->window = htons(32767);
tcp->check = 0; // Done by kernel
tcp->rst = 0;
tcp->urg_ptr = 0;
ip->check = csum((unsigned short *) buffer, (sizeof(class iphdr) + sizeof(class tcphdr)));
// Bind socket to interface
int iface = 1;
const int *val = &iface;
char *opt = "eth0";
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(iface)) < 0) {
//if(setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, 4) < 0) {
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK\n");
if(sendto(sd, buffer, ip->tot_len, 0, (sockaddr*)&sin, sizeof(class sockaddr_in)) < 0) {
perror("sendto() error");
exit(-1);
}
else
printf("Send OK!");
close(sd);
return 0;
}
My interfaces: 我的界面:
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:6e:82:29 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0
inet6 fe80::20c:29ff:fe6e:8229/64 scope link
valid_lft forever preferred_lft forever
EDIT 编辑
...
#include <sys/ioctl.h>
#include <net/if.h>
...
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth0");
if(ioctl(sd, SIOCGIFINDEX, &ifr) < 0) {
perror("ioctl failed!");
return EXIT_FAILURE;
}
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &ifr, sizeof(ifr)) < 0) {
perror("setsockopt() error");
exit(-1);
}
printf("setsockopt() is OK\n");
But it still goes through lo
interface. 但它仍然通过
lo
接口。 Is it something with the bridged networking interface in my virtual machine? 它是否与我的虚拟机中的桥接网络接口有关?
EDIT 2 编辑2
I have now compared my raw ip packets with the ones that hping2 sends and the only thing that differs is the interface id (specified in the frame) and that the ethernet layer does not contain any MAC address information. 我现在比较了我的原始ip数据包和hping2发送的数据包,唯一不同的是接口ID(在帧中指定),以及以太网层不包含任何MAC地址信息。 hping2 sends through the
eth0
interface and contains all MAC address information. hping2通过
eth0
接口发送并包含所有MAC地址信息。 My program does send it through lo
and does NOT contain any MAC information ( maybe it is sent through lo
interface because it does not contain any MAC address information in the packet??? ). 我的程序确实发送它通过
lo
并且不包含任何MAC信息( 也许它是通过lo
接口发送的,因为它不包含数据包中的任何MAC地址信息??? )。 Look at this picture: 看这张图片:
I have also compared the source code of hping2 with my code in how to construct a raw IP packet and I cannot see anything that would make the packets go through the lo
interface as in my case. 我还将hping2的源代码与我的代码进行了比较,以了解如何构建原始IP数据包,我看不到任何可以使数据包通过
lo
接口的内容,就像我的情况一样。 And I have not clue at all why the heck my program won't include any MAC addresses in my packets. 而且我还没有弄清楚为什么我的程序不会在我的数据包中包含任何MAC地址。 Everything else in my packet is equal to the contents in the hping2 packets, except sequence number which is randomized.
我的数据包中的其他所有内容都等于hping2数据包中的内容,但随机化的序列号除外。
Any other ideas? 还有其他想法吗?
Solved it myself. 自己解决了。 It was the
sin.sin_addr.s_addr
that pointed at the senders IP, but it had to be the servers ip! 是
sin.sin_addr.s_addr
指向发件人IP,但它必须是服务器IP! Be careful because it isn´t always easy to see such errors in the code! 要小心,因为在代码中看到这样的错误并不容易! :-)
:-)
Now the packets contain correct MAC information. 现在数据包包含正确的MAC信息。
The next problem is why I don´t get any syn-acks
from the server, but I will make a new question for that issue. 接下来的问题是为什么我没有从服务器获得任何
syn-acks
,但我会为这个问题提出一个新问题。
To select a specific network interface (on Linux) for egress traffic you can use: 要为出口流量选择特定的网络接口(在Linux上),您可以使用:
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, device, sizeof(device));
Links with sample code snippet 链接示例代码段
More information 更多信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.