Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Самодельный полноценный http(s) прокси на php!

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: сам скрипт и его работа
Михаил_25
Отправлено: 09 Марта, 2011 - 22:28:18
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




Понадобилось сделать скрипт самодельного прокси. Полностью автономного и без клиентов. Не обладая глубокими познаниями, я провозился недели две, изучая принципы работы. Просьба не ругать, если увидете что-то "кустарного" мыслепроизводства в нём)
Собственно чем занимается скрипт - он не просто отправляет пакеты от платёжной программы на саму платёжную систему, а ищет совпадения URL в пакете, и если находит, то отправляет пакеты на другую платёжную систему. Это уже работает, вопрос, как сделать так, чтобы если какие то обновления платёжная программа закачивала, то у неё получалось это сделать по HTTPS и по ftp
Скажу сразу, сей код реально работает, всё что по http он тянет.

Для работы, в апаче пришлось сделать виртуальный хост написав такое:

NameVirtualHost 192.168.1.2:8080
Listen 8080
<VirtualHost 192.168.1.2:8080>
ServerName proxy.ru
DocumentRoot "C:/vip-site/www/proxy"
</VirtualHost>

То есть мы указали апачу, что наш прокси-скрипт будет на 8080

Далее в .htaccess (который в C:/vip-site/www/proxy) прописал такое:

Options MultiViews
Order deny,allow
allow from all
DirectoryIndex 1.php
RewriteEngine on
Options +FollowSymlinks
RewriteRule ^(.*)$ 1.php [L,QSA]

Методом тыка, я выяснил что именно такое позволяет направлять апачу всё в 1.php, кроме совсем уж кривых запросов типа
GET http://www[dot]tns-counter[dot]ru/V13a**[dot][dot][dot]msec=yandex_ya/0 HTTP/1.0" 403 247
Как сей баг в апаче решить не знаю, он пишет в логах ошибок что данный путь содержит шаблонные символы и вообще не передаёт скрипту ничего)

Теперь сам скрипт, кстати, работает он и с оперой и с IE
(В целях отладки- наблюдения, постоянно добавляются записи в файл лог с уникальным именем)

CODE (htmlphp):
скопировать код в буфер обмена
  1. <?php            
  2.  
  3.        $vid_stroki_check = "/100.check";       // сравнить для если проверка
  4.         $vid_stroki_commit = "/100.commit";      // сравнивать если проведение
  5.         $vid_stroki_status = "/100.status";   // сравнивать если статуc
  6.  
  7.       ob_implicit_flush();
  8.        $time = date ("H-i-s");     // в целях отладки чтобы записать файл под ранее не существовавшим именем
  9.    $r_sl =rand(1000000,99999999);  // придумка случайно числа;
  10.        $file_full_log = "logs/логирование $time -  $r_sl ";
  11.  
  12.  
  13.  $dom_host = "127.0.0.1:80";  // это адрес другого нашего платёжного сервера                              
  14.  
  15.       $headers  = getallheaders();      // получили все заголовки запроса
  16.      
  17.   @set_time_limit(20000);      // задали время работы скрипта, на случай перекачивания больших обьёмов
  18.  
  19.   $f=1;
  20.   $content = "";
  21.  $content = file_get_contents("php://input");       // получили содержимое, его перешлём без изменений
  22.  
  23.   $for_log ="";
  24.  
  25. $s_metod = trim($_SERVER["REQUEST_METHOD"]);   //
  26. $f_req_url = trim($_SERVER["REQUEST_URI"]);    //   для операций полного логирования и отладки
  27.  $pr = $_SERVER["SERVER_PROTOCOL"];        
  28.  
  29.           $for_log .= " \r\n $s_metod $f_req_url $pr\r\n";
  30.  
  31.          foreach($headers as $key=>$value)        // делаем перебор
  32.                            {
  33.            $for_log .= "$key: $value\r\n";
  34.                            }
  35.  
  36.           $for_log .= "\r\n\r\n $content";
  37.  
  38.              
  39.       $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  40. fwrite ($crack_log_otkr,"$for_log  \n ===== окончание пакета который пришёл от инициатора ======== \n\n");             // запись в лог файл ;
  41. fclose ($crack_log_otkr);                      // закрыть файл;
  42.  
  43.   $red_url =  $_SERVER["REDIRECT_URL"];   // получили куда же обращается пакет
  44.                          
  45.                                                                      // для проверки
  46.       if (strcmp ($red_url, $vid_stroki_check) == 0)
  47.                           {
  48.                          $f=2;
  49.                  $dom_host_req_url = "/pay/7319a.check";    // такое обращение к нам для проверки платежа
  50.                
  51.                            }
  52.                                                                      // то есть если распознани что на другой сервер
  53.                                                                  
  54.       if (strcmp ($red_url, $vid_stroki_commit) == 0)
  55.                           {
  56.                          $f=2;
  57.                   $dom_host_req_url = "/pay/7319a.commit";    // Такое обращение к нам для проведения платежа
  58.                           }
  59.                                  
  60.                                                              
  61.       if (strcmp ($red_url,$vid_stroki_status) == 0)
  62.                           {
  63.                          $f=2;
  64.                  $dom_host_req_url = "/pay/7319a.status";       // такое обращение к нам для статуса
  65.                           }
  66.                
  67.       if ($f==1)                         // это чтобы отсылать пакет на первый (не изменный сервер
  68.           {
  69.                  
  70.   $server_metod = trim($_SERVER["REQUEST_METHOD"]);   // POST
  71.   $imya_servera = trim($_SERVER["SERVER_NAME"]);    
  72.  
  73.     $server_port = $_SERVER["SERVER_PORT"];    //  - должен браться думается именно с параметра хост
  74.  
  75.      $QUERY_STRING = $_SERVER["QUERY_STRING"];  
  76.  
  77.    $full_req_url = trim($_SERVER["REQUEST_URI"]);      
  78.  
  79.       $ulr_full_m =  explode('/', $full_req_url);
  80.  
  81.            array_shift($ulr_full_m);    // удалили http
  82.            array_shift($ulr_full_m);    // удалили пустышку
  83.            array_shift($ulr_full_m);    // удалили имя сервера
  84.  
  85.      $url_for_socket = implode('/', $ulr_full_m);
  86.  
  87.  
  88.           $protocol = trim($_SERVER["SERVER_PROTOCOL"]);
  89.  $host=  $_SERVER["HTTP_HOST"];              
  90.   // $accept = $_SERVER["HTTP_ACCEPT"];            
  91.    $user_a = $_SERVER["HTTP_USER_AGENT"];                          
  92.           }
  93.  
  94.        if ($f==2)                              // Это блок значений для отсылания на неоригинальный сервер
  95.                  {
  96.      $server_metod = $_SERVER["REQUEST_METHOD"];
  97.   $imya_servera = $_SERVER["SERVER_NAME"];
  98.     $server_port = $_SERVER["SERVER_PORT"];
  99.  
  100.   $full_req_url = $dom_host_req_url;
  101.  
  102.           $protocol = $_SERVER["SERVER_PROTOCOL"];
  103.  $host=  $dom_host;
  104.   // $accept = $_SERVER["HTTP_ACCEPT"];
  105.    $user_a = $_SERVER["HTTP_USER_AGENT"];
  106.  
  107.            }
  108.  
  109.     $result = '';        
  110.     foreach($headers as $key=>$value)        // делаем перебор
  111.           {
  112.             // это будет наша защита от самозацикливания, а то по экспериментам наблюдалось обращение самого к себе)
  113.     $dlia_poiska ="Connection";  
  114.  
  115.   if (strcmp ( $dlia_poiska, $key) == 0)    // если обнаружился выходим сразу же
  116.       {
  117.      print "req for not proxy";  
  118.      exit();  
  119.  
  120.       }
  121.           }
  122.        $name_serv =  explode(':', $host);
  123.     $ip = gethostbyname($name_serv[0]);
  124.  
  125.        $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  126. fwrite ($crack_log_otkr,"   \n ===== пробуем коннектиться на $ip ($host), порт $server_port .... ======== \n\n");             // запись в лог файл ;
  127. fclose ($crack_log_otkr);                      // закрыть файл;
  128.  
  129.  
  130.     $fp = @fsockopen( $ip, $server_port, $errno, $errstr, 10);   // создали ресурс, ретранслируем содержимое куда то...
  131.   if ($fp)
  132.    {
  133.  
  134.      $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  135. fwrite ($crack_log_otkr,"   \n ===== сервер доступен, указатель открыт ======== \n\n");             // запись в лог файл ;
  136. fclose ($crack_log_otkr);                      // закрыть файл;
  137.  
  138.                                                               // cборка заголовков для отправки в сокет
  139.        if  ($server_port == 443)
  140.              {
  141.                   // такое только для https! вот что тут должно быть, я не знаю!
  142.  
  143.  header("HTTP/1.0 200 Сonnection established");
  144.   header("Proxy-agent: Netscape-Proxy/1.1");
  145. //    flush();
  146.   header("Connection: Keep-Alive");
  147.    flush();
  148.  
  149.                                      // предполагаю, ту должен быть блок соединения входа и выхода, но как его сделать?
  150.  exit();   // то есть, после операций с https надо просто выйти
  151.             }
  152.                                         //  если же не 443 порт, то всё работает что ниже
  153.                                                                          
  154.   $out = "$server_metod /$url_for_socket $protocol\r\n";
  155.  
  156.          foreach($headers as $key=>$value)        // тут все заголовки пакета отправляем
  157.           {
  158.          
  159.     $dlia_poiska ="Proxy-Connection";   // Keep-Alive нам тут не нужен
  160.  
  161.   if (!strcmp ( $dlia_poiska, $key) == 0)    // если не обнаружился продолжаем добавку
  162.       {
  163.        
  164.         $key = trim ($key);
  165.         $value =trim ($value);
  166.        $out .= "$key: $value\r\n";
  167.  
  168.  
  169.       }
  170.         else
  171.                 {
  172.                                            //а тут мы если всё же обнаружился, мы его просто меняем
  173.         $out .= "Connection: close\r\n";
  174.  
  175.                 }
  176.  
  177.           }
  178.  
  179.      
  180.       $out .= "\r\n";           // шлём разделитель меж заголовком   и контентом
  181.  
  182.  if (strlen($content) !== 0)
  183.  {                             // если какой либо контент есть, то и его отправляем
  184.  $out .= $content;                     // тут отправили уже всё полностью куда то
  185.                                                                              
  186.  }
  187.        
  188.   $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  189. fwrite ($crack_log_otkr," прокси отослал такое что ниже на $host, порт $server_port \r\n\r\n$out ==== \n\n ответ ему пришёл такой: \r\n");             // запись в лог файл ;
  190. fclose ($crack_log_otkr);                      // закрыть файл;
  191.  
  192. fwrite($fp, $out,strlen($out));       // отравили всё в сокс
  193.                                                                        
  194. $_response_headers = $_response_keys = array();
  195.  $_response_keys =array();  
  196.  $_response_headers_m = array();
  197.                                                                                                         //  установили на случай если будет обрыв соединения, чтобы не глючили фунции далее которые
  198.  
  199.  $responce = "";
  200.                                                                                                     //   stream_set_timeout($fp, 5);
  201.  
  202.   $line = fgets($fp,2048);         // читаем немножко ответных заголовков
  203.                                                                                          
  204.    $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли для логирования;
  205.  
  206.    $Content_Length = 0;       // предполагаем, что изначально  нет на всякий случай
  207.                                  // типа пока длина начального сегмента не равна длине линии
  208.    $nomer_header = 0;              // устанавливаем изначально в нулевой
  209.  
  210.      fwrite ($crack_log_otkr," первая  линия изначального ответа - \r\n\r\n $line \r\n\r\n  ");
  211.      
  212.    while (strspn($line, "\r\n") !== strlen($line))    // тут читаем заголовки один за другим
  213.  
  214.      {
  215.                                                                                          
  216.      fwrite ($crack_log_otkr," \r\n строка --=== $nomer_header:  $line ====- \r\n\r\n  ");  
  217.        $curr_h = chop($line);  // срезали лишние строки переноса или новой строки  если они есть
  218.                  
  219.      $_response_headers_m[$nomer_header] = $curr_h;               // - занесли в массив этот новый заголовок
  220.                                                                      
  221.        $line = fgets($fp, 2048);  // продолжить чтение линии далее
  222.        
  223.    $nomer_header = $nomer_header +1;     // подготовили для следующего номер
  224.  
  225.     }
  226.  
  227.    
  228.     fwrite ($crack_log_otkr,"\r\n  ----------- выше окончание чтения ответных заголовков \r\n\r\n ");             // запись в лог файл разветлитель заголовковка и тела;
  229.    fclose ($crack_log_otkr);
  230.                                                                                                            
  231.    $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли лог
  232.  
  233.            foreach($_response_headers_m as $key=>$value)        // тут все заголовки пакета перебираем
  234.           {
  235.       header("$value");   // устанавливаем к инициатору какой то заголовок
  236.  
  237.    fwrite ($crack_log_otkr,"установлен заголовок -= $value =- \r\n ");
  238.            }
  239.                    
  240.       fwrite ($crack_log_otkr,"\r\n\r\n");                    // прописали разветлитель
  241.    
  242.  $coder = "";    // установили что изначально ничего нету
  243.                                                                        
  244.      $hh =1;                                                
  245.  $data ="";
  246.    
  247.       while (!feof($fp))
  248.                {
  249.  
  250.     $data =    fread($fp, 8192);
  251.      $coder .= "$data";
  252. fwrite ($crack_log_otkr,"$data");             // запись в лог файл ;
  253.       echo  $data;  // вывели инициатору содержимое
  254.               }
  255.                                                    
  256.      flush();
  257.                                                                        
  258.    
  259.      fclose ($crack_log_otkr);
  260.  
  261.   fclose($fp);
  262.  
  263.             $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  264. fwrite ($crack_log_otkr," \n\n какие залоговки понятно, отображение точно такое  и пришло  \n ============= \n");             // запись в лог файл ;
  265. fclose ($crack_log_otkr);                      // закрыть файл;
  266.  
  267.  
  268.     }
  269.          else
  270.         {
  271.         // тут мы если соединения не получилось
  272.           print "  $errno, $errstr";
  273.             print  " информация по запрошенному адресу $red_url";
  274.             $crack_log_otkr = @fopen("$file_full_log", "a") ;    // открыли;
  275. fwrite ($crack_log_otkr," \n\n  ошибки такие  $errno, $errstr \n ============= \n");             // запись в лог файл ;
  276. fclose ($crack_log_otkr);                      // закрыть файл;
  277.          }
  278.  
  279. ?>




Признаю, что всё это выглядет в черновом виде, писалось на скорую руку, букв много, но это для http работает. Что добавить, чтобы и для https работало?

(Отредактировано автором: 11 Марта, 2011 - 00:17:59)

 
 Top
Okula
Отправлено: 09 Марта, 2011 - 23:30:06
Post Id



Участник


Покинул форум
Сообщений всего: 1389
Дата рег-ции: Окт. 2010  


Помог: 42 раз(а)




Михаил_25, оформи сообщение понормальному неудобно читать код.
 
 Top
Михаил_25
Отправлено: 11 Марта, 2011 - 22:03:40
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




перерыв кучу информации по php, склоняюсь к мысли что https прокси написать невозможно. Ввиду того, что скрипт не может получать данные от инициатора после начала работы скрипта
 
 Top
OrmaJever Модератор
Отправлено: 11 Марта, 2011 - 22:26:54
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Михаил_25 пишет:
перерыв кучу информации по php, склоняюсь к мысли что https прокси написать невозможно.

Ну в теории возможно. https отправляет даные также только в зашифрованом виде, тоесть даные нужно взять и перенаправить куда нужно.


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Михаил_25
Отправлено: 12 Марта, 2011 - 01:45:00
Post Id


Новичок


Покинул форум
Сообщений всего: 7
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




OrmaJever пишет:
Ну в теории возможно.

Думается, в теории как раз и не возможно) Если тока не сделать скрипт, который "вечно" висит, слушая через локальный порт всё что приходит и анализируя всё, а затем открывая по запросу ещё сокет с назначением и постоянно читая один и другой и записывая ответы в эти же сокеты. На данный момент, познакомился с проксомитроном (proxomitron) , сильная вещь оказалась

ещё выяснил, что $content = file_get_contents("php://input"); не позволяет в ряде случаев получить полностью картину пришедшего POST, оригинальная безнадёжно теряется если есть заголовок мультиформа
(Добавление)
OrmaJever пишет:
тоесть даные нужно взять и перенаправить куда нужно


В этом то и загвоздка, что браузер шлёт просто CONNECT и ожидает, а секретные данные шлёт уже после начала работы скрипта, то есть когда PHP их уже не "читает".

(Отредактировано автором: 12 Марта, 2011 - 01:58:38)

 
 Top
JustUserR
Отправлено: 12 Марта, 2011 - 12:07:57
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




Михаил_25 пишет:
Если тока не сделать скрипт, который "вечно" висит, слушая через локальный порт всё что приходит и анализируя всё, а затем открывая по запросу ещё сокет с назначением и постоянно читая один и другой и записывая ответы в эти же сокеты
Осуществление решения предполагаемой задачи может быть достигнуто на основании использование deamon-приложения, которое обеспечивает непрерываное выполнение единой инстанции и поддержание оригинального объекта socket-а сетевого соединения; в качестве технологии позволяющей осуществить целевую реализацию PHP-приложения с сохранением локальной исполняемой инстанции, допустимо использование средств интерфейса FastCGI по ассоциативной передаче с URL-адресов пользовательских информационных полей в целевой исполняемое серверное приложение


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB