用iptables TPROXYredirect到原始套接字

我打算使用iptables的TPROXY目标redirect一些UDP数据包到一个原始的套接字,但没有数据包会被套接字接收。 它使用UDP套接字。 我错过了东西或原始套接字无法接收水平TPROXY作品中的数据?

 iptables -A PREROUTING -t mangle -p udp -dport 8816 -dst 127.0.0.1 -j
 TPROXY  - 在端口0  - 在-IP 127.0.0.2

消费redirect数据包的代码:

#include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> char _errstr[100]; #define CHECK(X) \ if (! (X)) {\ sprintf(_errstr, "%d: check failed", __LINE__);\ perror(_errstr);\ exit(1);\ } int main() { int r; int fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); CHECK(fd != 0); int val = 1; CHECK(setsockopt(fd, SOL_IP, IP_TRANSPARENT, &val, sizeof(val))== 0); char buff[1500] = {0}; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.2"); r = bind(fd, (struct sockaddr* )&addr, sizeof(addr)); CHECK(r == 0); r = read(fd, buff, 1500); CHECK(r >= 0); int c; for (c=0; r>c; c++) printf("%02X ", 0xFF & *(buff + c)); return 0; } 

我使用netcat(nc -u 127.0.0.1 8816)进行了testing,看到IPTables规则匹配,但没有数据包发送到原始套接字。

问题在这里r = bind(fd, (struct sockaddr* )&addr, sizeof(addr)); 。 你不应该bind到一个原始的套接字,而应该使用SO_BINDTODEVICE调用setsockopt来绑定到接口,在你的情况下,它是接口的地址127.0.0.2

有关如何使用此选项的详细信息,请查看http://linux.die.net/man/7/socket