2
votes

I intend using iptables' TPROXY target to redirect some UDP packets to a raw socket, but no packet would received by socket. It work with UDP sockets. Am I missing something or raw socket cannot receive data in level TPROXY works?

iptables -A PREROUTING -t mangle -p udp --dport 8816 --dst 127.0.0.1 -j
TPROXY --on-port 0 --on-ip 127.0.0.2

Code for consuming redirected packets:

#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;
}

I tested with netcat (nc -u 127.0.0.1 8816) and saw IPTables rule matches but no packet sent to raw socket.

1

1 Answers

1
votes

The problem is here r = bind(fd, (struct sockaddr* )&addr, sizeof(addr));. You should not bind to a raw socket, instead you should call setsockopt with SO_BINDTODEVICE to bind to the interface, in your case, it's the interface that has the address 127.0.0.2.

For the details of how to use this option, check out http://linux.die.net/man/7/socket