hxv blog
5mar/100

Prosty tracker BitTorrent

Od paru dni (znów) mam konto shellowe, tym razem na innocence.pl. Nie jest może jakieś super-wypasione, ale jak na swoją cenę (35zł/miesiąc) nie jest też takie złe.
Shella fajnie mieć, można nabić sobie naprawdę dużo uploadu na popularnych wstawkach a potem spokojnie ściągać co się chce. Jedyne czego nie lubię to korzystania z FTP, niby jest dużo różnych programów ale jakoś nie lubię tak ściągać dużych plików. Fajnie byłoby korzystać po prostu z uTorrenta (lub innego dowolnego klienta torrent). Można dodać plik .torrent który pobraliśmy z trackera do lokalnego klienta ale to trochę bez sensu - download naliczony będzie podwójnie. Głupim pomysłem jest też wrzucanie go na jakiś publiczny serwer - jeśli podmienimy adres trackera to i tak mnóstwo osób będzie korzystać z naszego shella, jeśli go nie podmienimy to prawdopodobnie dostaniemy bana.

Na szczęście jest jeszcze jedna opcja - można uruchomić własny tracker i używać go do wymiany plików jedynie między shellem a naszym PC. Napisanie takiego skryptu jest w miarę łatwe, kod jest prosty i będzie wykonywany tylko kilka razy w ciągu godziny więc w żaden sposób nie obciąży serwera. Przykładowy kod jest poniżej, na tej stronie można poczytać specyfikację protokołu BitTorrent i samemu coś stworzyć.

Pozostaje jeszcze tylko jedna kwestia - tworzenie pliku torrent. Nie ma sensu na nowo hashować plików, wystarczy podmienić adres trackera i nazwę jednego z plików/katalogu. Do obu czynności przyda się hexedytor (chociaż pewnie istnieją jakieś programy które umożliwiają łatwą podmianę tych danych).
Na początku musimy znaleźć oryginalny adres trackera, powinien być gdzieś na początku pliku i wyglądać jakoś tak: "79:http://tracker.page.org/announce.php?passkey=1234567890123456789012345678901234". Liczba na początku to długość ciągu z adresem, podmieniając URL należy pamiętać też o zmianie długości na odpowiednią. Podmieniamy znaleziony adres na np. coś takiego: "27:http://moja.strona.pl/a.php", a.php to oczywiście skrypt z trackerem.
Podmiana nazwy jednego z plików przyda się, żeby zmienić info_hash torrenta - to m.in. nazw plików. Dzięki zmianie klient będzie "wiedział", żeby wysyłając plik do nas nie naliczać uploadu na trackerze. Lista plików powinna być na początku pliku, najlepiej zmienić po prostu jeden znak w nazwie sampla/pliku nfo/pliku z sumami kontrolnymi.
Po zmianie wystarczy zapisać plik, przesłać na shella (niestety, w ten sposób 'zje' nam jeden proces) i odpalić go w lokalnym kliencie.

Oto kod, pisany na szybko i testowany tylko raz ale powinien działać ;) :

<?php
/*********************************************************\
*                                                         *
*  Najprostszy z mozliwych tracker BitTorrenta, posiada   *
*  jedynie minimalna funkcjonalnosc - zapisywanie         *
*  i wysylanie listy peerow. Zero obslugi bledow, zero    *
*  sprawdzania poprawnosci danych - nadaje sie tylko do   *
*  uzywania w przypadku, gdy np. chcemy przeslac cos      *
*  bardzo waskiej grupie osob lub przeslac sobie pliki    *
*  z shella za pomoca klienta torrent.                    *
*  Zapisuje tylko ip, port, czas announce i info_hash,    *
*  brak jakiejkolwiek kontroli ratio, brak listy          *
*  dozwolonych klientow itd.                              *
*                                                         *
\*********************************************************/

header( "Content-type: text/plain" );

$port = (int) $_GET["port"]; //port klienta - musi byc wyslany w liscie peerow

//pobieramy i filtrujemy info_hash torrenta, potrzebny jest do rozrozniania torrentow
$infoHash = $_GET["info_hash"];
if( get_magic_quotes_gpc() ) {
	$infoHash = stripslashes( $infoHash );
}
$infoHash = urlencode( $infoHash ); //na wszelki wypadek lepiej nie zapisywac w postaci binarnej

$peerList = @file_get_contents( "peers" ); //lista peerow, kazda linia w formacie ip:port|timestamp ostatniego announce|info_hash(url_encoded)
$peerList = explode( "\n", $peerList );

echo "d"; //otwieramy "dictionary" zawierajacy odpowiedz
	echo "8:interval"; //czas co jaki klient bedzie odnawial liste peerow
	echo "i3600e"; //3600 sekund = 1 godzina

	echo "5:peers"; //bedziemy wysylac liste peerow

	$peersLen = 0; //dlugosc stringu z lista peerow
	$peers = ""; //lista peerow
	$selfPeer = false; //klient jest juz na liscie peerow?

	foreach( $peerList as $i => $peer ) //dla kazdego peera z pliku
	{
		$peer = explode( "|", $peer ); //[0] => ip:port, [1] => timestamp of last action, [2] => info_hash
		if( count( $peer ) != 3 ) { //na wszelki wypadek sprawdzamy, czy po podzieleniu jest wlasciwa ilosc elementow
			unset( $peerList[$i] );
			continue;
		}

		if( $peer[1] < time() - 60*60*3 ) { //jesli peer byl nieaktywny przez ponad 3h
 			unset( $peerList[$i] ); //usuwamy go z listy
 			continue;
 		}
 		if( $peer[2] != $infoHash ) { //upewniamy sie, ze peer udostepnia/pobiera zadanego torrenta
 			continue;
 		}
 		$peer = explode( ":", $peer[0] ); //[0] => ip, [1] => port
		if( $peer[0] == $_SERVER["REMOTE_ADDR"] && $peer[1] == $port ) { //jesli ip i port peera z listy == ip+port klienta
			$selfPeer = true; //klient jest na liscie
			continue; //nie wysylamy klientowi jego IP
		}
		$peers .= pack( "Nn", ip2long( $peer[0] ), $peer[1] ); //dopisujemy peera do listy
		$peersLen += 6; //zwiekszamy dlugosc listy peerow (N (4 bajty) + n (2 bajty) = 6 bajtow)
	}
	if( !$selfPeer ) { //jesli klienta nie ma na liscie peerow
		$peerList[] = "{$_SERVER["REMOTE_ADDR"]}:{$port}|" . time() . "|{$infoHash}";
	}
	echo "{$peersLen}:{$peers}"; //wysylamy liste peerow
echo "e"; //zamykamy "dictionary"

file_put_contents( "peers", join( "\n", $peerList ) ); //zapisujemy liste peerow do pliku

?>
Komentarze (0) Trackbacks (0)

Brak komentarzy.


Dodaj komentarz


Brak trackbacków.