Tag Archives: Proxy

Un proxy PHP per il querybot

Dopo aver pubblicato l’articolo sul querybot per la simulazione di ricerche degli utenti, alcune persone mi hanno chiesto se l’emulazione umana avrebbe previsto anche il cambio di IP durante le richieste.

PHP proxyLa risposta è sì. Se non ne ho parlato nell’articolo è perché, senza pensarci, ho dato per scontata tale caratteristica, visto che da tempo uso un proxy PHP che mi permette di cambiare facilmente IP. Ma ugualmente scontato per i lettori non lo è e quindi vi spiego un po’ come funziona il proxy.

Il proxy è una versione riveduta e corrotta di un software che ho programmato qualche anno fa, per la creazione di alcuni tool SEO e di un proxy web in grado di bypassare certe restrizioni imposte da Google.

Si tratta di uno script PHP che fa da wrapper delle funzioni cURL e che necessita dunque di questa libreria per funzionare, così come di una versione o configurazione di PHP che contempli la presenza di tali funzioni.

Dal punto di vista dello sviluppatore l’uso è molto semplice: esiste una copia esatta delle funzioni previste dalla cURL, con l’aggiunta di alcune opzioni di tipo CURLOPT_ per la gestione dei parametri del proxy.

Per esempio, usando la copia della funzione curl_setopt() è possibile specificare l’URL del proxy che dovrà essere usato per le successive richieste.

All’URL specificato è presente uno script PHP che rappresenta il proxy vero e proprio, ecco come funziona il meccanismo:

  • il client effettua una richiesta come si farebbe normalmente con la cURL
  • il wrapper entra in gioco per codificare la richiesta in un particolare formato
  • il wrapper usa la cURL per inviare la richiesta codificata allo script proxy, nel far questo usa il metodo POST
  • lo script proxy riceve la richiesta codificata e la decodifica
  • lo script proxy usa la cURL per effettuare la richiesta originale esattamente nello stesso modo in cui l’avrebbe fatta il client;
  • ovviamente la richiesta viene effettuata con l’IP dell’host sul quale lo script proxy risiede
  • lo script proxy riceve il risultato della richiesta, lo codifica nuovamente e lo spedisce al client
  • il client riceve e decodifica il risultato della richiesta e lo restituisce al codice chiamante

Tutto il processo sopra indicato viene effettuato in modo assolutamente trasparente per il programmatore. In altre parole, qualsiasi script PHP che usa già la cURL può facilmente essere modificato per aggiungere la capacità di sfruttare uno o più proxy esterni.

Il sistema è comodo perché il sottoscritto, come la maggior parte dei webmaster e dei SEO, possiede più di un host provider per i propri siti web. Uploadare su ciascuno di essi lo script proxy permette dunque di ottenere tanti IP diversi quanti sono gli host su cui si pubblica lo script.

Conflitto tra le opzioni

Un dettaglio di progettazione che trovo interessante e che voglio condividere con voi è il modo in cui ho evitato le collisioni tra le nuove opzioni CURLOPT_ introdotte dal wrapper e le opzioni CURLOPT_ già esistenti.

La cURL prevede già di default un lungo elenco di opzioni attraverso le quali è possibile stabilire il comportamento della libreria. Ciascuna di queste opzioni ha un nome (una costante che inizia con “CURLOPT_”) e un corrispondente valore numerico.

Il wrapper è stato progettato in modo da replicare le opzioni CURLOPT_ e aggiungerne di proprie. Ho dovuto quindi fare attenzione a non definire costanti che avessero gli stessi valori già usati per quelle “ufficiali”. Il problema però sta nel fatto che ad ogni aggiornamento della cURL è possibile che la quantità di opzioni (e quindi delle costanti) aumenti.

Il mio wrapper non poteva quindi definire le nuove costanti in modo statico, perché avrebbe rischiato di usare valori potenzialmente allocabili dalle future versioni della cURL. Ogni aggiornamento della libreria avrebbe potuto scatenare dei conflitti e mettere il wrapper nelle condizioni di produrre malfunzionamenti.

La soluzione che ho trovato è stata quella di definire dinamicamente le costanti che mi serviva aggiungere. Il wrapper fa così ad ogni sua inizializzazione (si legga: lancio dello script):

  • usa la funzione di PHP get_defined_constants() per ottenere la lista delle costanti definite dalla cURL
  • estrae il valore più alto usato dalle costanti “ufficiali”
  • inizia a definire dinamicamente con la funzione define() le nuove costanti, partendo da valori superiori a quello massimo usato dalla cURL

Facendo in questo modo non c’è rischio che le costanti vengano create con valori già in uso o potenzialmente usabili in futuro dalla libreria cURL. 🙂