# Proxy server programmieren



## thedafelix (10. April 2011)

Hi alle,
für die verbindung eines javascript xmpp/jabber chats zum xmpp/jabber server brauche ich einen proxy server. Das ganze wird leider auch "man in the middle attack" genannt, ich weiß. Trotzdem gibts neben Flash keine andere möglichkeit solche chats zu bauen.

Also was muss ein Proxy server alles können. Doch eigentlich nur asynchron auf anfragen warten , die auslesen, zum eigentlichen webserver verbinden, empfangen und des empfangene gleich wieder an den anfrage stream schieben oder? 

evtl ist es ja auch sinnvolller einen java opensource proxy zu benutzen und den dann nur umzubastel, oder ist des zu schwierig?

mfg thedafelix


----------



## Bratkartoffel (11. April 2011)

Hi,

alles was du zu Proxies (Socks-Proxies) wissen musst, kannst du auf Wikipedia (klick) oder in den RFC's nachlesen. (#1928, #1929)

Meiner Meinung nach wäre die Verwendung eines fertigen Proxies besser, bzw. schneller. Wenn du dich aber allgemein mit der Thematik auseinandersetzen willst und deine Programmier-Fähigkeiten verbessern willst, dann setz das ganze selber um 

Gruß
BK


----------



## thedafelix (14. April 2011)

Hi, 
hab jetzt einfach mal angefangen ist aber iwie doch nicht so leicht wie ich mir des dachte.

Ich lese zuerst die Anfrage vom Browser mit


```
Socket sock = ssock.accept();
				InputStream in = sock.getInputStream();
				int read = 1;
				byte[] buff = new byte[56];
				byte[] total = new byte[1024];
				int totalread=0;
				while(read!=0){
					read = 0;
					read = in.read(buff,0,buff.length);
					System.out.println("Read"+read+" bytes");
					System.arraycopy(buff,0,total,totalread,read);
					totalread+=read;
				}
				String request = total.toString();
```

Des funktioniert schonmal nicht. Vorher hatte ich einen BufferedReader und hab mit readLine eingelesen fand des so gefühlt besser.
Der gibt aus er liest 5 mal 56 bytes was mir ziemlich viel vorkommt dann meint er noch einmal 46 bytes was insgesamt viel zu viel ist für ein "GET /war HTTP 1/1" oder?

Ein ähnlicher fehler ist wenn ich versuche den COntent vom apache zu laden da bleibt er wirklich hängen bei in.read

```
System.out.println("	Sending Request to local webserver...");
				Socket request_sock = new Socket("127.0.0.1",80);
				OutputStream out = request_sock.getOutputStream();
				byte[] request_b = (request).getBytes();
				System.out.println("	Now sending");
				out.write(request_b,0,request_b.length);
				System.out.println("	Sended "+request_b.length+" bytes");
				InputStream in = request_sock.getInputStream();
				int read=1;
				int read_total = 0;
				byte[] in_buff = new byte[8*1024];
				while(read!=0){
					System.out.println("	Now reading buff of 8 kb");
					read = in.read(in_buff,0,in_buff.length);
					System.out.println("	Reading "+read+" bytes");
					if(read>0){
						out.write(in_buff,0,read);
					}
					read_total+=read;
				}
				System.out.println("	Read "+read_total+" bytes");
```

Mit was kann des zusammenhängen?

@Bratkartoffel
Ich hab den wiki link den du gepostete hast mal überflogen fand des aber ziemlich kompliziert. Muss mein proxy wirklich mit irgendwelchen bitmuster, über ein extra protokoll kommunizieren?
Kann der nicht nur den doofen durchleiter spielen?

thx thedafelix


----------



## Bratkartoffel (14. April 2011)

Hi,

irgendwie muss der Client dem Proxy ja sagen, was er wie von wem braucht. Socks ist da ja nicht nur auf HTTP beschränkt, den kannst ja auch für ICQ, FTP, SSH, HTTPS oder sonst alles hernehmen.

Deine Rechnung mit 5*56 + 46 Bytes kann sich schon hingehen, der Browser sendet viel mehr Informationen als nur ein einfaches "GET".  Für die Wikipediaseite oben schickt mein Firefox zum Beispiel folgendes weg:


```
Host: secure.wikimedia.org
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.7,de-de;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset :ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
DNT: 1
Connection: keep-alive
Referer: http://www.tutorials.de/java/374706-proxy-server-programmieren.html
If-Modified-Since: Thu, 14 Apr 2011 00:39:16 GMT
Cache-Control: max-age=0
```

Mein Browser geht auch über einen Socks5 Proxy. Das Lesen von anderen Seiten ist etwas tricky. Hier halten nämlich viele Server die Verbindung offen, wenn sie ihre Daten geschickt haben damit der Client über die selbe Verbindung mehrere Anfragen stellen kann. Somit sinkt der Overhead, da eine Verbindung theoretisch für 5-10 Anfragen verwendet werden kann.
Hier kannst du dann entweder ein "GET .... HTTP/1.0" senden (also nicht Version 1.1) oder den Header "Connection: close" bei der Anfrage mitschicken, dann wird die Verbindung getrennt wenn alle Daten gesendet wurden. Besser wäre es aber, den "Content-Length" Header zu parsen und dann exakt so viele Daten zu lesen. Hier musst du aber auch auf die "Content-Encoding: chunked" achten  Das ganze HTTP ist komplizierter als man denkt, aber auch hierfür gibt es RFC's.

Aber wie schon gesagt, Socks arbeitet eine Ebene tiefer und du musst die Verbindung zum Servers eigentlich erst schließen, wenn der Client an dem Proxy die Verbindung schließt. Der Proxy dient dann nur als Vermittler der Daten ohne in diese reinzuschauen. Es ist im quasi egal was die kommunieren. Und genau dafür gibt es die von mir geposteten RFC's, die genau festlegen wie die Kommunikation zwischen Client und Proxy abläuft und wie du am Proxy erkennen kannst, was der Client jetzt eigentlich will.

Gruß
BK


----------



## thedafelix (22. April 2011)

So. Danke für deine ausführliche Antwort. War letzter Zeit noch ziemlich Schulisch und anderweitig Beschäfftigt also ist meine Spaß-Geschichte Chat erst einmal hintern runtergefallen.

Ich denke des SOCKS Protokoll muss ich nicht implementieren da dann doch im Browser den Serve expliziet als proxy eintragen sein muss dass der auch wirklich mit meinem Proxy als Proxy kommuniziert, oder? 

Mein Server soll sich bloß als Webserver ausgeben der noch die nette fähigkeit hat sich zu meinem xmpp server zu verbinden.

Hab des mit dem Verbindung erst Schließen wenn Server verbindung schließt mal so umgesetzt und mit 1 Byte Puffern in 2 Threads Browser und Server kommunzieren lassen.

Des PRoblem ist nur. Ich muss ja irgendwie die erste Zeile jeder Request bekommen um rauszufinden ob der Browser jetzt den Web- oder XMPP Server will. Im Main also AnnahmeThread funktioniert dass auch einwandfrei, ich lese einfach bis zum ersten \n Zeichen undS Splitte dann nach Leerzeichen. Bloß der Browser nutzt die Chance einer stehenden Verbindung gleich aus und baut bei aufwendigeren Seiten. 4 Threads auf durch die dann nacheinander um die 20 Requests die ich dann im VerbindungsThread, ich nenn Ihn Tunnel nicht mehr filtern richtig filtern kann -  bzw können schon waren aber alle mehr oder minder schlecht bzw langsam meine Möglichkeiten.

Fällt da irgendjemanden ne Möglichkeit ein wie ich die Request wie Bratkartoffel seinen Wiki Request gepostete hat auseindander halten kann.

gruß thedafelix


----------

