#!/usr/local/bin/bash # # tvhpt - tcp via https proxy tunnel # # Autor: Raphael Becker # Lizenz: BSD # # Version 0.3 / Sat May 5 01:25:59 MEST 2001 # Debug-Mode (VERBOSE) und Erreichbarkeits-Test fuer Proxy # # Version 0.2 / Thu May 3 10:07:57 MEST 2001 # Optimierung: beliebige http-Responses werden jetzt # verworfen, nicht nur konstant 2-zeilige. # # Version 0.1 # Lauffaehiges Script, Trennung zwischen ini und Programmteil # # Version 0.0 # Lauffaehige Kommandozeile # # Dieses Script erzeugt mit Hilfe von netcat eine # TCP-Verbindung via http-Proxy. Hierbei wird das # CONNECT-Feature ausgenutzt, welches fuer https # benoetigt wird. # # Wichtig: Manche Proxies oder Firewalls erlauben dem Proxy # ausschliesslich Zielports 80 und 443. Hier ist es # nicht moeglich auf beliebige Ports zu connecten. # # Falls beliebige Ports nicht moeglich sind, muss auf dem # Zielrechner ein "Tunnelende" installiert werden, welches # dann das Forwarding uebernimmt. Sinnvollerweise sollte dieses # Tunnelende auf Port 443 (https) laufen und zB durch den inetd # gestartet werden. Das aktuelle Script unterstuetzt dies jedoch # derzeit noch nicht. # # Dieses Script unterstuetzt derzeit noch keine # Authentifizierung am Proxy. Dieses ist aber sicher # nicht zu schwierig zu implementieren. # Wir benoetigen netcat, welches uns die # Moeglichkeit gibt stdin/stdout auf eine TCP- # Verbindung zu geben. Wir verenden es hier einmal # zur Verbindung zwischen unserem Rechner und dem # http-Proxy und zum anderen im "listen"-Mode um # die Verbindung zu unserem Client (zB irc-Client) # aufzubauen. # Netcat gibts unter http://www.l0pht.com/~weld/netcat/ # # TO-DO # * Proxy-Authentifizierung # * Remote-Tunnelende, falls Proxy nur feste Ports forwardet # * trap einbauen, damit bei exit _immer_ aufgeraeumt wird. # * Fehlermeldungen vom Proxy auswerten. # # Idee: PPP tunneln, damit IP-Verbindung herstellen. # # Ende der Doku ######################################################### # NETCAT=$(type -p netcat || type -p nc) # Info-Ausgaben? "true" fuer ja oder anderer Wert fuer nein VERBOSE=true # Daten des Proxy-Servers PROXY_HOST=localhost PROXY_PORT=3128 # Daten des Remote-Rechners # Beispiel: IRC-Server der UUGRN http://www.uugrn.org/ REMOTE_HOST=blowfish.scram.de REMOTE_PORT=6667 LOCAL_PORT=16667 # Mit einem beliebigen IRC-Client kann man nun # auf den server localhost port 16667 connecten. # # Beispiel mit ircII: # $ ircII -c "#uugrn" -p 16667 nickname localhost # # ... wobei hier das "localhost" sich auf den Rechner bezieht, auf dem # dieses script hier gestartet ist. # # Ende der User-Definierten Variablen ################################################### # # dafuer sorgen, dass es nur "true" oder "false" gibt. [ "${VERBOSE}" = "true" ] || VERBOSE=false # Falls netcat nicht installiert ... if [ -z ${NETCAT} ]; then echo 'Fehler: "netcat" oder "nc" nicht gefunden!' echo ' http://www.l0pht.com/~weld/netcat/' exit 1 fi # Brauchen ne Variable, die nur "\r" enthaelt: RET=$(echo -e '\r') # Testen, ob Proxy-Server ueberhaupt erreichbar. ${VERBOSE} && echo -n "Teste ${PROXY_HOST}:${PROXY_PORT} ... " if ${NETCAT} -z ${PROXY_HOST} ${PROXY_PORT}; then ${VERBOSE} && echo "ok" else ${VERBOSE} && echo 'nicht erreichbar.' echo "Fehler: Proxy Server unter ${PROXY_HOST}:${PROXY_PORT} nicht erreichbar!" exit 1 fi # # Ende der Initialisierung ####################################################### # # Wir brauchen ein FIFO, damit sich die beiden netcat-Prozesse # unterhalten koennen, da wir eine bidirektionale Verbindung # brauchen, es aber keine bidirektionalen pipes gibt; # etwas, wo sich p1 und p2 unterhalten koennten: p1 | p2 ... # liefert kann nur stdin von p1 aufnehmen und das stdout von p2 # ausgeben. stdout von p2 muss aber wieder nach stadin von p1 und # hierfuer wird die FIFO gebaurcht. # Das FIFO wird mit den aktuellen User-rechten in /tmp angelegt, # nur der User selbst hat lese/schreibrechte. # FIFO=/tmp/tvhpt.$$ ${VERBOSE} && echo -n "Lege FIFO ${FIFO} an ... " mkfifo -m 600 ${FIFO} ${VERBOSE} && echo "ok" # # Verbindung zu Proxy aufnehmen und diesen # zum Aufbau der gewuenschten Verbindung auffordern. # # Folgender Ausdruck (lange pipe) liest sich etwa so: # sende mit echo -e einen string mit Returns, kopiere danach # alles weitere von stdin nach stdout (mit cat), beziehe stdin # aus der FIFO und schicke stdout an netcat1, welches den output # des {...}-Konstrukts via stdin entgegennimmt und sein stdout # zum 2. {...}-Ausdruck schiebt, welcher nichts weiter # tut, als den http-Response-Header von stdin wegzuwerfen. # Danach gehts mittels cat stdin nach stdout kopiert. Dieses # stdout geht via pipe zum netcat2, welches im "listen"-Modus auf # dem oben definierten Port lauscht, Eingaben via stdin entgegennimmt # und seine Ausgabe in das FIFO umleitet und somit ueber den ersten # netcat-Prozess die Daten wieder an den Remote Host zu schicken. # Damit ist der "Ring" vollstaendig: # # [Remote] # | # [Proxy] # | # [fifo] -> {...} -> [netcat] -> {...} -> [netcat -l] -> [fifo] # | # [client] # # Horizontal: Lokale pipe # Vertikal: TCP-Verbindungen # # Unklar ist, ob man die FIFO nicht an anderer Stelle # dazwischenhaengen kann. Das duerfte wohl davon abhaengen, welcher # der beiden netcat-Prozesse zuerst gestartet wird. Wichtig ist, # dass zuerst lesend auf die FIFO zugegriffen wird, da sonst # offenbar Daten, die vorher reingeschrieben wurden "verschwinden". # Das ist soweit ungeklaert. Unter Linux und bash funktioniert das # ganze wie hier gezeigt. ${VERBOSE} && echo "Tunnel zu ${REMOTE_HOST}:${REMOTE_PORT} via ${PROXY_HOST}:${PROXY_PORT}, lokaler Port ${LOCAL_PORT} ... " { echo -e "CONNECT ${REMOTE_HOST}:${REMOTE_PORT} HTTP/1.0\r User-Agent: tvhpt 0.2\r \r" cat } < ${FIFO} |\ ${NETCAT} ${PROXY_HOST} ${PROXY_PORT} |\ { while read L; do [ "${L}" == "${RET}" ] && break; done; cat; }|\ ${NETCAT} -l -p ${LOCAL_PORT} >${FIFO} ${VERBOSE} && echo "Der Tunnel wurde abgebaut" ${VERBOSE} && echo "Raeume auf." # Aufraeumen rm ${FIFO} ${VERBOSE} && echo "Ende"