I created a interface using wintun and imported all traffic into this interface through the default route (0.0.0.0/0->wintun IP). The problem now is that packets received by the tun interface are sent, but due to the default route, the packets return, causing a loopback. In Linux, I bound the socket to a real interface using SO_BINDTOVICE, and the packet will be sent directly. How can I avoid loopback in Windows?
I tried to use the bind() function to bind this SOCKET to the IP address of a real interface, but there was still a loopback.The annotated code was adapted by me based on a Rust program, but it didn’t work either.WSAIoctl(s,SIO_ROUTING_INTERFACE_CHANGE) also doesn’t work,My real goal is to bypass the kernel protocol stack and avoid being captured by the routing table.
bool bind_socket(SOCKET s) {
// multicast bind. multicast binding only supports udp socket
// if_index:real if index
if (tun_pf.if_index <= 0) {
return true;
}
/*int optval;
int optlen = sizeof(optval);
if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&optval, &optlen) !=
0) {
log_error("getsockopt failed: %d", WSAGetLastError());
return false;
}
int val1 = IP_MULTICAST_IF;
if (optval == SOCK_DGRAM && setsockopt(s, IPPROTO_IP, &val1,
(char*)&tun_pf.if_index, sizeof(tun_pf.if_index)) != 0) {
log_error("setsockopt IP_MULTICAST_IF failed: %d",
WSAGetLastError());
return false;
}
int val2 = IP_UNICAST_IF;
if (setsockopt(s, IPPROTO_IP, &val2, (char*)&tun_pf.if_index,
sizeof(tun_pf.if_index))) {
log_error("setsockopt IP_UNICAST_IF failed: %d",
WSAGetLastError());
return false;
}*/
struct sockaddr_in addr;
const char* interfaceIP = "192.168.10.212"; // real interface addr
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = inet_addr(interfaceIP);
if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
log_error("Bind failed.");
return false;
}
return true;
}
2
Ended.setsockopt(s, IPPROTO_IP, IP_UNICAST_IF, (char*)&tun_pf.if_index, sizeof(tun_pf.if_index)) is useful, if_index should be big-endian.