在 linux 中通过 RAW 套接字重新发送数据包
resend packets via RAW sockets in linux
需要从一个接口读取原始数据并通过另一个接口发送。
open&&config(sock_raw_outer同理):
sock_raw_inner = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
setsockopt(sock_raw_inner, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 4);
struct ifreq if_idx1;
memset(&if_idx1, 0, sizeof(struct ifreq));
strncpy(if_idx1.ifr_name, opt, strlen(opt));
ioctl(sock_raw_inner, SIOCGIFINDEX, &if_idx1);
然后循环:
data_size = recvfrom(sock_raw_inner, buffer, 65536, MSG_DONTWAIT, NULL, NULL);
if (data_size > 0) {
struct sockaddr_ll socket_address;
socket_address.sll_ifindex = if_idx2.ifr_ifindex;
socket_address.sll_halen = ETH_ALEN;
//copy dest
socket_address.sll_addr[0] = buffer[0];
socket_address.sll_addr[1] = buffer[1];
socket_address.sll_addr[2] = buffer[2];
socket_address.sll_addr[3] = buffer[3];
socket_address.sll_addr[4] = buffer[4];
socket_address.sll_addr[5] = buffer[5];
sendto(sock_raw_outer, buffer, size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll))
}
然后,如果我捕获到 sock_raw_inner 任何数据包(例如 arp 请求),它会通过 sendto 一次又一次地在 sock_raw_inner 上发送。怎么了?谢谢
您的 sock_raw_inner 仍在监听每个接口,因为不支持您尝试在 eth0 上执行的绑定。所以发送到另一个接口的数据包确实被你的 sock_raw_inner
接收了
从 man (7) 套接字中提取(见粗体文本)
SO_BINDTODEVICE
Bind this socket to a particular device like "eth0", as speci-
fied in the passed interface name. If the name is an empty
string or the option length is zero, the socket device binding
is removed. The passed option is a variable-length null termi-
nated interface name string with the maximum size of IFNAMSIZ.
If a socket is bound to an interface, only packets received from
that particular interface are processed by the socket. Note that
this only works for some socket types, particularly AF_INET
sockets. It is not supported for packet sockets (use normal
bind(8) there).
需要从一个接口读取原始数据并通过另一个接口发送。
open&&config(sock_raw_outer同理):
sock_raw_inner = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
setsockopt(sock_raw_inner, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 4);
struct ifreq if_idx1;
memset(&if_idx1, 0, sizeof(struct ifreq));
strncpy(if_idx1.ifr_name, opt, strlen(opt));
ioctl(sock_raw_inner, SIOCGIFINDEX, &if_idx1);
然后循环:
data_size = recvfrom(sock_raw_inner, buffer, 65536, MSG_DONTWAIT, NULL, NULL);
if (data_size > 0) {
struct sockaddr_ll socket_address;
socket_address.sll_ifindex = if_idx2.ifr_ifindex;
socket_address.sll_halen = ETH_ALEN;
//copy dest
socket_address.sll_addr[0] = buffer[0];
socket_address.sll_addr[1] = buffer[1];
socket_address.sll_addr[2] = buffer[2];
socket_address.sll_addr[3] = buffer[3];
socket_address.sll_addr[4] = buffer[4];
socket_address.sll_addr[5] = buffer[5];
sendto(sock_raw_outer, buffer, size, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll))
}
然后,如果我捕获到 sock_raw_inner 任何数据包(例如 arp 请求),它会通过 sendto 一次又一次地在 sock_raw_inner 上发送。怎么了?谢谢
您的 sock_raw_inner 仍在监听每个接口,因为不支持您尝试在 eth0 上执行的绑定。所以发送到另一个接口的数据包确实被你的 sock_raw_inner
接收了从 man (7) 套接字中提取(见粗体文本)
SO_BINDTODEVICE Bind this socket to a particular device like "eth0", as speci- fied in the passed interface name. If the name is an empty string or the option length is zero, the socket device binding is removed. The passed option is a variable-length null termi- nated interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this only works for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(8) there).