Jump to content
RA.BY

Какие бывают прокси и чем они различаются, определение типа прокси средствами php(curl)


makag

Recommended Posts

Данная статья-обзор не претендует на 100% достоверность

и является лишь попыткой систематизировать и изложить 

в понятном виде то, что стало известно мне самому.

Критика и дополнения - приветствуются

© 2019 ra.by (makag)

 

 

Прокси-сервер (от англ. proxy — «представитель», «уполномоченный») — промежуточный сервер (комплекс программ), выполняющий роль посредника между пользователем и целевым сервером. 

 

Сначала клиент подключается к прокси-серверу, тот в свою очередь отправляет запрос дальше, на целевой ресурс и возвращает клиенту ответ (в неизменном либо модифицированном виде). © википедия

 

Наглядно это можно представить в таком виде:

 

image.png.c215f14832c57fe440620b69a2994eb7.png

 


 

Прокси-сервера могут использоваться в следующих целях:

- кеширование внешних ресурсов прокси-сервером, с целью минимизации внешнего трафика;

- контроль(ограничение) доступа к внешним ресурсам в сети интернет, учёт трафика;

- обход ограничений (блокировок);

- анонимизация доступа к различным ресурсам.

 

Используя прокси для анонимизации доступа (например при использовании социальных сетей) следует знать, что не все прокси анонимны. Это означает, что даже используя прокси - нельзя быть уверенным в том, что прокси не передаёт ваш ip адрес в служебных заголовках на конечный сервер.


 

По степени анонимности соответственно принято разделять прокси на:

 

- прозрачные (transparent) - такой прокси передаёт ваш ip адрес дальше, т.е. об анонимности речь вообще не идёт. Такие прокси используются в тех случаях, когда нужна не анонимность, а просто обход блокировки вебсайта в локальной сети или в стране;

- анонимные (anonymous) - такой прокси скрывает ваш ip адрес, но при этом не скрывает самого факта, что используется прокси сервер;

- искажающие (distorting) - прокси также не скрывает факт использования прокси-сервера, но вместо вашего ip  в служебных заголовках передаёт совершенно другой ip адрес;

- элитные (elite) - прокси скрывают сам факт использования прокси сервера. 

 


 

По способу авторизации прокси можно разделить на:

 

а) Прокси без авторизации.  Такими прокси может воспользоваться любой, кому стали известны ip адрес и порт доступа к прокси

б) Прокси с авторизацией по IP. Такие прокси строго привязаны к ip адресу пользователя, посторонний не сможет использовать такой прокси.

в) Прокси с авторизацией по логину и паролю. Прокси запрашивает у пользователя логин и пароль и только после авторизации передаёт/принимает данные

г) Возможны и иные варианты. В частности доступ по user agent (используемому браузеру), в том числе с комбинацией вариантов "б" и "в".

 


 

По задачам, которые призваны решать прокси, их можно разделить их на:

 

CGI прокси (так называемые анонимайзеры)  - как правило выполнены в виде веб-сайта, который открывается в любом браузере. Далее - строка ввода адреса  и окно, отображающее содержимое запрашиваемого вебсайта.  Используется в офисах, где злой админ закрыл доступ на порнохаб и в странах, где запрещён фейсбук, вконтакте или твитер. Пример  такого анонимайзера: noblockme.ru

 

FTP прокси предназначен для загрузки данных на FTP сервер.

 

SMTP, POP3 и IMAP прокси - используются для отправки, приёма и фильтрации электронной почты

 

HTTP прокси -  самый распространенный тип прокси, используется браузерами (и не только) для передачи информации по TCP протоколу. Информация при этом передаётся в открытом (не зашифрованном виде). Позволяет кешировать страницы/изображения и таким образом экономить внешний трафик.

 

HTTPS прокси - фактически это HTTP-прокси, а загадочная буква "S"  означает "secure" (защищенный) -  с поддержкой защищенного соединения. Прокси-сервер соединяется с веб-сайтом  и ваш трафик шифруется, в процессе шифрации и дешифрации сам прокси участия не принимает, то есть отследить какие именно данные передаются - сложнее.

 

SOCKS4/SOCKS5  прокси -   передача информации без каких-либо дополнительных модификаций (socks4 только по протоколу TCP, socks5 в том числе и по UDP). Все socks4/socks5 прокси  как минимум анонимны. В socks4 не поддерживается авторизация клиента через "логин:пароль", в то время, как в  socks5 такая возможность есть. 

 


Технические аспекты

(переменные окружения)

 

При соединении с веб-сервером ему в заголовках (служебная информация) передаются такие переменные:

- название и версия операционной системы;

- название и версия браузера;

- индивидуальные настройки браузера и операционной системы (разрешение экрана, глубина цвета, поддержка javascript и т.п.);

- используется ли proxy сервер;

- если используется proxy, то может быть передан  IP адрес конечного пользователя;

- множество других данных.

 

Примерно понять, что именно знает о вас сторонний сайт, можно заглянув по адресу: whoer.net/ru

 

Как выглядят переменные, сообщающие веб-серверу об использовании прокси сервера.

 

1) Если прокси не используется то заголовки будут выглядеть так:

REMOTE_ADDR = Ваш IP
HTTP_VIA = не определён
HTTP_X_FORWARDED_FOR = не определён

 

2) При использовании прозрачного (transparent) прокси эти заголовки будут выглядеть так:

REMOTE_ADDR = IP proxy
HTTP_VIA = IP или имя прокси сервера
HTTP_X_FORWARDED_FOR = Ваш IP

 

3) При использовании анонимного (anonymous) прокси эти заголовки будут выглядеть так:

REMOTE_ADDR = IP proxy
HTTP_VIA = IP или имя прокси сервера
HTTP_X_FORWARDED_FOR =  IP адрес прокси

 

4) При использовании искажающего (distorting) прокси эти заголовки будут выглядеть так:

REMOTE_ADDR = IP proxy

HTTP_VIA = не определён 

HTTP_X_FORWARDED_FOR = случайный IP

 

5) При использовании анонимного (anonymous) прокси эти заголовки будут выглядеть так:

REMOTE_ADDR = IP proxy

HTTP_VIA = не определён
HTTP_X_FORWARDED_FOR = не определён

 

Определение типа прокси средствами php и curl

 

Определить тип прокси - прозрачный, анонимный, искажающий или элитный - можно совершив запрос на заранее подготовленную страницу и проанализировав полученный ответ (в соответствии с пятью вариантами заголовков из раздела выше).  Хороший вариант - использование веб-сайта proxyjudge.info

Несмотря на то, что у http/https прокси порты для соединения обычно 80/8080, а у socks4/socks5 обычно порт 3128, на самом деле прокси может находится на любом порту и определить визуально (по номеру порта) конкретный тип прокси  - невозможно.

 

Определение  типа прокси  - http/https либо socks4/socks5/socks5 с авторизацией -  возможно только лишь поочерёдно осуществляя запросы с различными параметрами.

 

1) Запрос curl без использования прокси

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
$data = curl_exec($ch);

2) Запрос curl по протоколу HTTP

 

Цитата

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); 
curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);

$data = curl_exec($ch);

 

3) Запрос curl по протоколу HTTPS

Цитата

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); 
curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);

$data = curl_exec($ch);

 

4) Запрос curl по протоколу SOCKS4

Цитата

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);

curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);

 

5) Запрос curl по протоколу SOCKS5

Цитата

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);

curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);

 

6) Запрос curl по протоколу SOCKS5 с авторизацией клиента по логину и паролю:
 

Цитата

curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);

curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);

curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_pass);
$data = curl_exec($ch);

 

На данный момент при проверке прокси я отправляю подряд запросы от №6 до №2 с таймаутом 7 секунд, то есть, чтобы достоверно сказать, что прокси - "не рабочий" у меня уходит на это целых 35 секунд, следующим образом:

1) изначально при добавлении прокси в базу mysql  - тип прокси неясен, поле "proxy_type" оставляю пустым

2) php файл detect.php, при обращении к которому выводят служебные заголовки, следующего содержания:
 

<?php
$remote = $_SERVER['REMOTE_ADDR'];
if (isset($remote)) { echo "external ip $remote"; }
$via = $_SERVER['HTTP_VIA'];
if (isset($via)) { echo "via $via"; }
$fwd = $_SERVER['HTTP_X_FORWARDED_FOR'];
if (isset($fwd)) { echo "fwd $fwd"; }
?>

3) функции для запросов к файлу посредством curl как http/https/socks4/socks5/socks5 с авторизацией, соответственно check_proxy1/check_proxy2/check_proxy4/check_proxy5/check_proxy55

function check_proxy1($page, $user_agent, $proxy_ip) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); 
curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && strpos($data, "via") === false)	{ return "1 ELIT"; }
if  ($http_code == 200 && strpos($data, $_SERVER['SERVER_ADDR']) === false) { return "1 ANON"; }
if ($http_code <> 200) { return "http_code $http_code"; }
curl_close($ch); }

function check_proxy2($page, $user_agent, $proxy_ip) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS); 
curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && strpos($data, "via") === false)	{ return "2 ELIT"; }
if  ($http_code == 200 && strpos($data, $_SERVER['SERVER_ADDR']) === false) { return "2 ANON"; }
if ($http_code <> 200) { return "http_code $http_code"; }
curl_close($ch); }

function check_proxy4($page, $user_agent, $proxy_ip) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && strpos($data, "via") === false) {	return "4 ELIT"; }
if  ($http_code == 200 && strpos($data, $_SERVER['SERVER_ADDR']) === false)	{ return "4 ANON"; }
if ($http_code <> 200) { return "http_code $http_code"; }
curl_close($ch); }

function check_proxy5($page, $user_agent, $proxy_ip) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); curl_setopt($ch, CURLOPT_PROXY, $proxy_ip);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && strpos($data, "via") === false)	{ return "5 ELIT"; }
if  ($http_code == 200 && strpos($data, $_SERVER['SERVER_ADDR']) === false)	{ return "5 ANON"; }
if ($http_code <> 200) { return "http_code $http_code"; }
curl_close($ch); }

function check_proxy55($page, $user_agent, $proxy_ip, $proxy_pass) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $page);
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 7);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); curl_setopt($ch, CURLOPT_PROXY, $proxy_ip); curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_pass);
$data = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200 && strpos($data, "via") === false)	{ return "55 ELIT"; }
if  ($http_code == 200 && strpos($data, $_SERVER['SERVER_ADDR']) === false) { return "55 ANON"; }
if ($http_code <> 200) { return "http_code $http_code"; }
curl_close($ch); }

4)  И собственно попытки определить тип  прокси:

 

Цитата

if ((strlen($proxy_ip) > 4) and (strlen($proxy_pass) > 4)) { $proxy_type = 55;  $time_1 = microtime(1); $checker = check_proxy55($page, $user_agent, $proxy_ip, $proxy_pass); $time_2 = microtime(1); $time_3 = round($time_2 - $time_1, 2);
        $is55 = preg_match("/(55)( )([A-Z]{1,4})/", "$checker");
        if ($is55 == 1) { $proxy_rank = 1; $query = "UPDATE vkproxy SET proxy_type = '$proxy_type', proxy_qual = '$time_3', proxy_rank = '$proxy_rank' WHERE num = '$key'";  $fill_db = mysqli_query($link, $query); }
        if ($is55 == 0) {$query = "DELETE FROM vkproxy WHERE (`num`='$key')"; $delete_proxy = mysqli_query($link, $query); } }
                        
            if ((strlen($proxy_ip) > 4) and (strlen($proxy_pass) < 4)) { 
                $time_1 = microtime(1); $checker = check_proxy5($page, $user_agent, $proxy_ip); $time_2 = microtime(1); $time_3 = round($time_2 - $time_1, 2);
                $is5 = preg_match("/(5)( )([A-Z]{1,4})/", "$checker");
                if ($is5 == 1) { $proxy_type = 5; $proxy_rank = 1; $query = "UPDATE vkproxy SET proxy_type = '$proxy_type', proxy_qual = '$time_3', proxy_rank = '$proxy_rank' WHERE num = '$key'";  $fill_db = mysqli_query($link, $query); }
                    if ($is5 == 0) {     $time_1 = microtime(1); $checker = check_proxy4($page, $user_agent, $proxy_ip); $time_2 = microtime(1); $time_3 = round($time_2 - $time_1, 2);
                    $is4 = preg_match("/(4)( )([A-Z]{1,4})/", "$checker"); 
                    if ($is4 == 1) { $proxy_type = 4; $proxy_rank = 1; $query = "UPDATE vkproxy SET proxy_type = '$proxy_type', proxy_qual = '$time_3', proxy_rank = '$proxy_rank' WHERE num = '$key'";  $fill_db = mysqli_query($link, $query); }
                        if ($is4 == 0) {     $time_1 = microtime(1); $checker = check_proxy2($page, $user_agent, $proxy_ip); $time_2 = microtime(1); $time_3 = round($time_2 - $time_1, 2);
                        $is2 = preg_match("/(1)( )([A-Z]{1,4})/", "$checker");
                        if ($is2 == 1) { $proxy_type = 2; $proxy_rank = 1; $query = "UPDATE vkproxy SET proxy_type = '$proxy_type', proxy_qual = '$time_3', proxy_rank = '$proxy_rank' WHERE num = '$key'";  $fill_db = mysqli_query($link, $query); }
                            if ($is2 == 0) {      $time_1 = microtime(1); $checker = check_proxy1($page, $user_agent, $proxy_ip); $time_2 = microtime(1); $time_3 = round($time_2 - $time_1, 2);
                            $is1 = preg_match("/(1)( )([A-Z]{1,4})/", "$checker");
                            if ($is1 == 1) {     $proxy_type = 1; $proxy_rank = 1; $query = "UPDATE vkproxy SET proxy_type = '$proxy_type', proxy_qual = '$time_3', proxy_rank = '$proxy_rank' WHERE num = '$key'";  $fill_db = mysqli_query($link, $query); }
                                    if ($is1 == 0) { $query = "DELETE FROM vkproxy WHERE (`num`='$key')"; $delete_proxy = mysqli_query($link, $query); } } 
 } } }

 

Предполагаю, что  используя curl_multi_init можно сократить время проверки. Но поскольку данная область мною ещё не освоена - лучше помолчу и дополню пост, когда будет что сказать. 

 

Всем спасибо за внимание.

Edited by makag
  • + 2
Link to comment
Share on other sites

  • 1 year later...

Подскажите столкнулся с след. проблемой. Используя прокси паблик в скриптах php (в частности socks4),  не работают post запросы - получаю пустой ответ (например если нужно где авторизоваться), get запросы проходят на ура... Это связано с самими проксями?

пробывал юзать скрипты без прокси через proxyfair(сокс4) тоже самое....

Link to comment
Share on other sites

39 минут назад, akterak сказал:

 не работают post запросы - получаю пустой ответ (например если нужно где авторизоваться), get запросы проходят на ура..

 

 

40 минут назад, akterak сказал:

пробывал юзать скрипты без прокси через proxyfair(сокс4) тоже самое....

 

по всей видимости  да, дело в проксях.. 
 

Link to comment
Share on other sites

23 минуты назад, makag сказал:

по всей видимости  да, дело в проксях.. 

еще читал, что дело может быть в порте,  якобы через стандартные работает (1080, 8080), а через другие (например 4145) уже нет...в чем тут может быть связь? может нужно что-то менять в файлах настройки/curl'a или открыть порты специально на винде ?

Link to comment
Share on other sites

14 минут назад, akterak сказал:

еще читал, что дело может быть в порте,  якобы через стандартные работает (1080, 8080), а через другие (например 4145) уже нет...в чем тут может быть связь? 

не, это бред, имхо
через какой порт работает конкретный прокси - определяет администратор прокси сервера при его создании / конфигурации.
по умолчанию традиционно http/https работают  на 80, 8080 например, сокс на 1080
по факту можно установить любой порт.

если гет запросы проходят, а пост запросы не проходят - дело не винде

на мой взгляд варианта всего два:
- конкретные прокси не работают с пост запросами (на публичных прокси такое в принципе возможно)
- ошибка в коде и пост запросы не работают вообще.

Второй вариант, с ошибкой в коде, маловероятен -т.к. через другие прокси (http, socks5 и без прокси)   пост запросы работают точно также, независимо от вида прокси.

Следовательно дело именно в конкретных прокси и их настройках.

Для паблик прокси это возможно даже норма - чтобы не злоупотребляли, не нагружали проксю - разрешают только гет запросы. 

Edited by makag
Link to comment
Share on other sites

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...