[tproxy] tproxy iptables rules

Kevin Stewart tproxy at stewart.gen.nz
Mon Apr 7 14:00:57 CEST 2008


I am trying to transparently proxy traffic to specific hosts each
listening on a different port.

I would like to if at all possible run without having to specifically
create iptables rules per host.

the important parts of the code are below

I listen to an ip:port pair using listento and then once I see an incoming
connection attempt to connect to that host using the clients IP:port using
connectas.

what I am seeing is that I get the client connection then make the
outbound connection but that does not have its source changed and its
intercepted by the tproxyed listen so I get an loop of incoming
connections

I have 2 interfaces on my server and plan to run it as a router
I bind to 2 the client facing IP for listening and the internet facing IP
for connecting out

I am using 2.6.20-wolk5.0 from here
http://ftp.ticklers.org/ftp.kernel.org/linux/kernel/people/mcp/2.6-WOLK/?C=M;O=A
the tproxy version is 2.0.6

any help would be greatly appreciated.
Kevin

int listento(struct sockaddr_in *laddr,
                struct sockaddr_in *raddr){
        int sock;
        int i;
        struct in_tproxy itp;
        struct sockaddr_in sin;

        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1){
                perror("socket");
                return -1;
        }
        i = 1;
        if (setsockopt(sock, SOL_IP, SO_REUSEADDR, &i, sizeof(i)) == -1){
                perror("SO_REUSEADDR");
                return -1;
        }

        /* check tproxy version */
        itp.op = TPROXY_VERSION;
        itp.v.version = 0x02000000;
        if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) {
                perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_VERSION)");
                return -1;
        }

        /* bind to local address */
        if (bind(sock, (struct sockaddr *) laddr, sizeof(sin)) == -1) {
                perror("listento: bind");
                return -1;
        }

        /* assign foreign address */
        itp.op = TPROXY_ASSIGN;
        itp.v.addr.faddr=raddr->sin_addr;
        itp.v.addr.fport = raddr->sin_port;

        if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) {
                perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_ASSIGN)");
                return -1;
        }

        /* set listen flag */
        itp.op = TPROXY_FLAGS;
        itp.v.flags = ITP_LISTEN;
        if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) {
                perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_FLAGS)");
                return -1;
        }

        /* listen */
        if (listen(sock, BACKLOG) == -1) {
                perror("listen");
                return -1;
        }
        return sock;
}

int connectas(  struct sockaddr_in *laddr,
                struct sockaddr_in *faddr,
                struct sockaddr_in *daddr)
{

        int sock;
        struct in_tproxy itp;

        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1){
                perror("socket");
                return(-1);
        }

        /* bind to local address */
        if (bind(sock, (struct sockaddr*) laddr, sizeof(*laddr)) == -1){
                perror("connectas: bind");
                return -1;
        }

        /* assign foreign address */
        itp.op = TPROXY_ASSIGN;
        itp.v.addr.faddr=faddr->sin_addr;
        itp.v.addr.fport=faddr->sin_port;

        if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1){
                close(sock);
                printf("errno=%i\n",errno);
                perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_ASSIGN)");
                return -1;
        }

        /* specify peer endpoint: the same address we will pass to
connect() */
        itp.op = TPROXY_FLAGS;
        itp.v.flags = ITP_CONNECT | ITP_ONCE;
        itp.v.addr.faddr=daddr->sin_addr;
        itp.v.addr.fport=daddr->sin_port;
        if (setsockopt(sock, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1){
                close(sock);
                printf("errno=%i\n",errno);
                perror("setsockopt(SOL_IP, IP_TPROXY, TPROXY_FLAGS)");
                return -1;
        }

        /* connect */
        if (connect(sock, (struct sockaddr*) daddr, sizeof(*daddr)) == -1){
                close(sock);
                perror("connect");
                return -1;
        }
        return sock;
}




More information about the tproxy mailing list