[PATCH] tcpserver: transparent tcp proxying support using Linux netfilter + nc

Denis Vlasenko <[email protected]> Tue, 5 Aug 2003 14:52:24 +0300
Newsgroups gmane.org.djb.miscellaneous
Message-ID <[email protected]>
Hi folks,

I'm not really sure where to send this.

Moreover, it seems like ucspi-tcp is so good that
it froze after 0.88, no more development seen
for quite some time...

With this really small patch you can proxy any TCP
service.

Theory of operation: upon accept, tcpserver queries
Linux kernel about 'original' (ie, before -j REDIRECT)
IP and port numbers and places them into
TCPORIGDSTIP and TCPORIGDSTPORT.

You can use these variables to establish proxy connection
with netcat. Live example:

#!/bin/sh
# This service can proxy any simple TCP service
# Use it with netfilter rule(s) like:
# ipt="iptables -t nat -A PREROUTING"
# $ipt -i $intif -p tcp --dport 80 -j REDIRECT --to 9080
# $ipt -i $intif -p tcp --dport 22 -j REDIRECT --to 9080
# NB: needs patched tcpserver! ;)
ip=0.0.0.0
port=9080
user=apache
timeout=100
maxconn=100
exec \
env - \
softlimit \
envuidgid $user \
tcpserver \
    -U \
    -v -R -H -l 0 -c $maxconn \
    $ip $port \
    sh -c 'exec env - nc -w $timeout $TCPORIGDSTIP $TCPORIGDSTPORT'

Patch applies cleanly to today's http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
Run tested.

DJB, please apply or complain. I hate being -j DROPped! ;)
--
vda

diff -urN ucspi-tcp-0.88/Makefile ucspi-tcp-0.88-netfilter/Makefile
--- ucspi-tcp-0.88/Makefile	Sat Mar 18 13:18:42 2000
+++ ucspi-tcp-0.88-netfilter/Makefile	Thu Feb 13 19:24:32 2003
@@ -580,6 +580,10 @@
 compile socket_local.c byte.h socket.h uint16.h
 	./compile socket_local.c
 
+socket_origdst.o: \
+compile socket_origdst.c byte.h socket.h uint16.h
+	./compile socket_origdst.c
+
 socket_opts.o: \
 compile socket_opts.c socket.h uint16.h
 	./compile socket_opts.c
@@ -802,7 +806,7 @@
 open_read.o open_trunc.o open_write.o openreadclose.o pathexec_env.o \
 pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \
 sig_block.o sig_catch.o sig_pause.o socket_accept.o socket_bind.o \
-socket_conn.o socket_delay.o socket_listen.o socket_local.o \
+socket_conn.o socket_delay.o socket_listen.o socket_local.o socket_origdst.o \
 socket_opts.o socket_remote.o socket_tcp.o socket_udp.o \
 stralloc_cat.o stralloc_catb.o stralloc_cats.o stralloc_copy.o \
 stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o \
@@ -815,7 +819,7 @@
 	pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o \
 	sig.o sig_block.o sig_catch.o sig_pause.o socket_accept.o \
 	socket_bind.o socket_conn.o socket_delay.o socket_listen.o \
-	socket_local.o socket_opts.o socket_remote.o socket_tcp.o \
+	socket_local.o socket_origdst.o socket_opts.o socket_remote.o socket_tcp.o \
 	socket_udp.o stralloc_cat.o stralloc_catb.o stralloc_cats.o \
 	stralloc_copy.o stralloc_eady.o stralloc_opyb.o \
 	stralloc_opys.o stralloc_pend.o strerr_die.o strerr_sys.o \
diff -urN ucspi-tcp-0.88/socket.h ucspi-tcp-0.88-netfilter/socket.h
--- ucspi-tcp-0.88/socket.h	Sat Mar 18 13:18:42 2000
+++ ucspi-tcp-0.88-netfilter/socket.h	Thu Feb 13 19:24:27 2003
@@ -16,6 +16,7 @@
 extern int socket_send4(int,char *,int,char *,uint16);
 extern int socket_local4(int,char *,uint16 *);
 extern int socket_remote4(int,char *,uint16 *);
+extern int socket_origdst4(int,char *,uint16 *);
 
 extern void socket_tryreservein(int,int);
 
diff -urN ucspi-tcp-0.88/socket_origdst.c ucspi-tcp-0.88-netfilter/socket_origdst.c
--- ucspi-tcp-0.88/socket_origdst.c	Wed Dec 31 22:00:00 1969
+++ ucspi-tcp-0.88-netfilter/socket_origdst.c	Thu Feb 13 19:24:43 2003
@@ -0,0 +1,18 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/netfilter_ipv4.h>
+#include "byte.h"
+#include "socket.h"
+
+int socket_origdst4(int s,char ip[4],uint16 *port)
+{
+  struct sockaddr_in sa;
+  int dummy = sizeof sa;
+
+  if (getsockopt(s,SOL_IP,SO_ORIGINAL_DST,(struct sockaddr *) &sa,&dummy) == -1) return -1;
+  byte_copy(ip,4,(char *) &sa.sin_addr);
+  uint16_unpack_big((char *) &sa.sin_port,port);
+  return 0;
+}
diff -urN ucspi-tcp-0.88/tcpserver.c ucspi-tcp-0.88-netfilter/tcpserver.c
--- ucspi-tcp-0.88/tcpserver.c	Sat Mar 18 13:18:42 2000
+++ ucspi-tcp-0.88-netfilter/tcpserver.c	Thu Feb 13 19:24:10 2003
@@ -53,6 +53,11 @@
 static stralloc remotehostsa;
 char *remotehost = 0;
 
+uint16 origdstport;
+char origdstportstr[FMT_ULONG];
+char origdstip[4];
+char origdstipstr[IP4_FMT];
+
 char strnum[FMT_ULONG];
 char strnum2[FMT_ULONG];
 
@@ -171,6 +176,13 @@
   env("TCPLOCALIP",localipstr);
   env("TCPLOCALPORT",localportstr);
   env("TCPLOCALHOST",localhost);
+
+  if (socket_origdst4(t,origdstip,&origdstport) != -1) {
+    origdstipstr[ip4_fmt(origdstipstr,origdstip)] = 0;
+    origdstportstr[fmt_ulong(origdstportstr,origdstport)] = 0;
+    env("TCPORIGDSTIP",origdstipstr);
+    env("TCPORIGDSTPORT",origdstportstr);
+  }
 
   if (flagremotehost)
     if (dns_name4(&remotehostsa,remoteip) == 0)