[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