Hola, pues es muy facil hacer un proxy socks, yo ayer termine 1 xD, basandome en las especificaciones:
http://www.socks.permeo.com/AboutSOCKS/SOCKSvE.asp
tambien puedes hacer la version 5 q es la mas reciente, de todas formas te pasteo el codigo. Esto esta creado en C++ Builder usando Indy 9, pero es muy facil traducirlo a delphi.
Necesitas un formulario con
TEdit llamado Edit1 y Text = 1080
TButton llamado Button1 y Caption = "Start"
TLabel llamado Label2 y Caption = 0 (este sera solo un contador de conexiones, muy simple)
TIdTCPServer llamado IdTCPServer1 con sus valores por defecto.
El codigo es el siguiente:
Unit1.cpp
Código PHP:
//
// EJEMPLO PROXY SOCKS 4A
// Creado por Gemu - www.netsock.net
//
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (Button1->Caption == "Start")
{
Button1->Caption = "Stop";
IdTCPServer1->DefaultPort = Edit1->Text.ToInt();
IdTCPServer1->Active = true;
}
else
{
IdTCPServer1->Active = false;
Button1->Caption = "Start";
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
TIdTCPClient *dstSock;
TSocksRequestPacket srp;
try
{
// define el timeout
AThread->Connection->ReadTimeout = 10000;
// obtiene el paquete de solicitud Proxs
srp = SocksRequestPacket(AThread->Connection);
// comprueba los datos Socks4
if (srp.VN != 4) throw ESocksRequestError(); // solo Socks4
if (srp.CD != 1) throw ESocksRequestError(); // solo CONNECT (no BIND)
// intenta conectar el cliente
dstSock = new TIdTCPClient(NULL);
dstSock->Host = srp.DSTIP;
dstSock->Port = srp.DSTPORT;
dstSock->Connect(5000); // 5seg
// establecida la conexion, retorna respuesta
SocksResponsePacket(AThread->Connection, REQUEST_GRANTED, srp.DSTPORT, srp.DSTIP);
// inicia el flujo de datos
char flowBuffer[8192];
int flowCount;
AThread->Connection->ReadTimeout = IdTimeoutInfinite;
while (true)
{
// lee del servidor
if(dstSock->Socket->Readable(20))
{
flowCount = dstSock->Socket->Recv(flowBuffer, sizeof(flowBuffer));
if (flowCount < 1) throw EIdConnClosedGracefully(NULL);
AThread->Connection->Socket->Send(flowBuffer, flowCount);
}
// lee del cliente
if(AThread->Connection->Socket->Readable(20))
{
flowCount = AThread->Connection->Socket->Recv(flowBuffer, sizeof(flowBuffer));
if (flowCount < 1) throw EIdConnClosedGracefully(NULL);
dstSock->Socket->Send(flowBuffer, flowCount);
}
}
}
catch(ESocksRequestError)
{
SocksResponsePacket(AThread->Connection, REQUEST_REJECTED_OR_FAILED);
}
catch(...)
{
// no hace nada
}
// desconecta
try
{
dstSock->Disconnect();
delete dstSock;
}
catch(...)
{
// no hace nada
}
AThread->Connection->Disconnect();
}
//---------------------------------------------------------------------------
TSocksRequestPacket __fastcall TForm1::SocksRequestPacket(TIdTCPServerConnection *Connection)
{
TSocksRequestPacket srp;
byte prt[2];
char c;
/* Implementacion Socks4 */
// VN | CD
Connection->ReadBuffer(&srp, 2);
// DSTPORT
Connection->ReadBuffer(&prt, 2);
srp.DSTPORT = (((unsigned int)prt[0]<<8) | prt[1]);
// DSTIP
for(int i=0; i<4; i++)
{
Connection->ReadBuffer(&c, 1);
srp.DSTIP += (byte)c;
if(i<3) srp.DSTIP += '.';
}
// USERID
// lee un maximo de 256 caracteres, evita el bucle infinito
for(int i=0; i<256; i++)
{
Connection->ReadBuffer(&c, 1);
if(c == 0) break;
srp.USERID += c;
}
/* implementacion Socks4A */
if(srp.DSTIP.SubString(0,6) == "0.0.0.")
{
srp.DSTIP = ""; // limpia la IP destino
// DSTIP (como DNS)
// lee un maximo de 256 caracteres, evita el bucle infinito
for(int i=0; i<256; i++)
{
Connection->ReadBuffer(&c, 1);
if(c == 0) break;
srp.DSTIP += c;
}
// obtiene la IP del HOST
srp.DSTIP = GStack->ResolveHost(srp.DSTIP);
}
return srp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SocksResponsePacket(TIdTCPServerConnection *Connection, TSocksReplyCode code, AnsiString dstport, AnsiString dstip)
{
TSocksRequestPacket srp;
byte b_dstport[2];
byte b_dstip[4];
// VN | CD
srp.VN = 0;
srp.CD = (char)code;
Connection->WriteBuffer(&srp, 2);
// DSTPORT
b_dstport[0] = dstport >> 8;
b_dstport[1] = dstport & 0xFF;
Connection->WriteBuffer(b_dstport, 2);
// DSTIP
TStringList *sl = new TStringList();
sl->Delimiter = '.'; sl->DelimitedText = dstip;
for(int i=0; i<sl->Count; i++)
b_dstip[i] = sl->Strings[i].ToIntDef(0);
delete sl;
Connection->WriteBuffer(b_dstip, 4);
}
void __fastcall TForm1::IdTCPServer1Connect(TIdPeerThread *AThread)
{
Label2->Caption = Label2->Caption.ToInt() + 1;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdTCPServer1Disconnect(TIdPeerThread *AThread)
{
Label2->Caption = Label2->Caption.ToInt() - 1;
}
//---------------------------------------------------------------------------
Unit1.h
Código PHP:
//
// EJEMPLO PROXY SOCKS 4A
// Creado por Gemu - www.netsock.net
//
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdTCPServer.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <IdDNSResolver.hpp>
#include <IdUDPBase.hpp>
#include <IdUDPClient.hpp>
//---------------------------------------------------------------------------
typedef struct
{
char VN;
char CD;
unsigned int DSTPORT;
AnsiString DSTIP;
AnsiString USERID;
} TSocksRequestPacket;
enum TSocksReplyCode {
REQUEST_GRANTED = 90,
REQUEST_REJECTED_OR_FAILED = 91,
REQUEST_IDENTD_REJECTED = 92,
REQUEST_IDENTD_INVALID_USERID = 93
};
class ESocksRequestError
{
};
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TIdTCPServer *IdTCPServer1;
TEdit *Edit1;
TButton *Button1;
TIdTCPClient *no_se_usa;
TLabel *Label1;
TLabel *Label2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall IdTCPServer1Execute(TIdPeerThread *AThread);
void __fastcall IdTCPServer1Connect(TIdPeerThread *AThread);
void __fastcall IdTCPServer1Disconnect(TIdPeerThread *AThread);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
/* Socks */
TSocksRequestPacket __fastcall SocksRequestPacket(TIdTCPServerConnection *Connection);
void __fastcall SocksResponsePacket(TIdTCPServerConnection *Connection, TSocksReplyCode code, AnsiString dstport=0, AnsiString dstip=0);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Lo unico que necesito es implemetar el soporte para SSL :S, alguien sabra como se hace eso? pense q deberia funcionar por ser TCP pero no lo hace.
PD: Firefox creo que no implementa bien las especificaciones Socks4 porque pierde los datos de respuesta del protocolo e intenta interpretarlo como HTML, y como resultado te muestra el dialogo de descargar archivo :P.
espero q les sirva, saludos (y)
GEMU