Advertisement
NokitaKaze

Проксик для для заворачивания пакетов в HTTP-connect запросы

Apr 30th, 2016
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 8.89 KB | None | 0 0
  1. #!/usr/bin/php
  2. <?php
  3.     /**
  4.      * Штука для перехвата HTTP/HTTPS-пакетов на линух-сервере и отправки их
  5.      * на какой-нибудь MITM-прокси типа mitmproxy или Fiddler
  6.      *
  7.      * Запускать так
  8.      *
  9.      * На хост-машине
  10.      * echo 1 > /proc/sys/net/ipv4/ip_forward
  11.      * iptables -F -t nat
  12.      * iptables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --dport 443 --to-ports 8443
  13.      * iptables -t nat -A PREROUTING -i eth0 -j ACCEPT
  14.      *
  15.      * Потом
  16.      * ./proxy_to_api.php -p 8443
  17.      * ./proxy_to_api.php -p 8080 --no-ssl
  18.      *
  19.      * На windows-клиенте
  20.      * route add 93.184.216.34 mask 255.255.255.255 192.168.1.14 metric 1
  21.      *
  22.      * Не забудьте включить на Fiddler'е "принимать подключения из вне", а на клиенте — импортнуть рутовый сертификат
  23.      */
  24.     $options = getopt('d:p:', array(
  25.         'no-ssl'
  26.     ));
  27.     $domain = array_key_exists('d', $options) ? $options['d'] : 'example.com';
  28.     $port = array_key_exists('p', $options) ? (int) $options['p'] : 8443;
  29.     $ssl_enabled = !array_key_exists('no-ssl', $options);
  30.  
  31.     $input_server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  32.     if ($input_server === false) {
  33.         echo "can not spawn socket\n";
  34.  
  35.         return;
  36.     }
  37.  
  38.     if (@socket_bind($input_server, '0.0.0.0', $port) === false) {
  39.         echo "can not bind socket: ".socket_strerror(socket_last_error($input_server))."\n";
  40.  
  41.         return;
  42.     }
  43.  
  44.     if (@socket_listen($input_server, 5) === false) {
  45.         echo "can not listen socket: ".socket_strerror(socket_last_error($input_server))."\n";
  46.  
  47.         return;
  48.     }
  49.  
  50.     $our_proxy = gethostbyname('192.168.1.16');
  51.     $real_api_ip = gethostbyname($domain);
  52.     socket_set_nonblock($input_server);
  53.     /**
  54.      * @var resource[][] $socket_pairs
  55.      */
  56.     $socket_pairs = array();
  57.     $start_session_time = time();
  58.  
  59.     while (true) {
  60.         // Принимаем подключения
  61.         $input_socket = @socket_accept($input_server);
  62.         if ($input_socket !== false) {
  63.             echo "CONNEСT\n";
  64.             $output_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  65.             $result = socket_connect($output_socket, $our_proxy, 8888);// Порт поменять, это до Фиддлера
  66.             if ($result === false) {
  67.                 socket_shutdown($output_socket);
  68.                 socket_close($output_socket);
  69.                 socket_shutdown($input_socket);
  70.                 socket_close($input_socket);
  71.                 continue;
  72.             }
  73.             if ($ssl_enabled) {
  74.                 $first_packet_bytes = @socket_recv($input_socket, $first_packet_buf, 2048, 0);
  75.                 if (!preg_match('_([a-z0-9.-]{5,})_i', $first_packet_buf, $a)) {
  76.                     echo "First input ssl packet malformed\n";
  77.                     continue;
  78.                 }
  79.                 $real_domain = $a[1];
  80.  
  81.                 $init_string = "CONNECT {$real_domain}:443 HTTP/1.1\n".
  82.                                "HOST: {$real_domain}\n\n";
  83.                 socket_write($output_socket, $init_string, strlen($init_string));
  84.                 $full_buf = '';
  85.                 while (!preg_match('_\\r\\n\\r\\n_', $full_buf)) {
  86.                     $bytes = @socket_recv($output_socket, $buf, 1000, 0);
  87.                     $full_buf .= $buf;
  88.                     if ($bytes == 0) {
  89.                         echo "Connect-proxy malformed answer\n";
  90.                         socket_shutdown($output_socket);
  91.                         socket_close($output_socket);
  92.                         socket_shutdown($input_socket);
  93.                         socket_close($input_socket);
  94.                         continue 2;
  95.                     }
  96.                 }
  97.                 $a = explode("\r\n\r\n", $full_buf, 2);
  98.                 if (!preg_match('_^HTTP/1\\.[01] ([0-9]+) _', $a[0], $b)) {
  99.                     echo "Can not establish properly proxy connect\n";
  100.                     socket_shutdown($output_socket);
  101.                     socket_close($output_socket);
  102.                     socket_shutdown($input_socket);
  103.                     socket_close($input_socket);
  104.                     continue;
  105.                 } elseif ($b[1] != 200) {
  106.                     echo "Can not establish properly proxy connect. HTTP Status {$b[1]}\n";
  107.                     socket_shutdown($output_socket);
  108.                     socket_close($output_socket);
  109.                     socket_shutdown($input_socket);
  110.                     socket_close($input_socket);
  111.                     continue;
  112.                 }
  113.  
  114.                 if ($first_packet_bytes > 0) {// Что очевидно, иначе бы сюда код не пришёл
  115.                     socket_write($output_socket, $first_packet_buf, $first_packet_bytes);
  116.                 }
  117.                 if (strlen($a[1]) > 0) {
  118.                     socket_write($input_socket, $a[1], strlen($a[1]));
  119.                 }
  120.  
  121.                 echo "CONNEСT #".count($socket_pairs)." ESTABLISHED TO {$real_domain}\n";
  122.                 unset($first_packet_buf, $first_packet_bytes, $a, $full_buf, $bytes);
  123.                 $socket_pairs[] = array($input_socket, $output_socket, $real_domain);
  124.             } else {
  125.                 $socket_pairs[] = array($input_socket, $output_socket);
  126.             }
  127.             unset($input_socket, $output_socket);
  128.         }
  129.  
  130.         // Обрабатываем подключения (кидаем пакеты)
  131.         foreach ($socket_pairs as $pair_id => &$pair) {
  132.             if ($pair === null) {
  133.                 continue;
  134.             }
  135.  
  136.             $r = array($pair[0]);
  137.             $count = socket_select($r, $write = null, $except = null, 0);
  138.             if ($count === false) {
  139.                 socket_shutdown($pair[1], 2);
  140.                 socket_close($pair[1]);
  141.                 socket_shutdown($pair[0], 2);
  142.                 socket_close($pair[0]);
  143.                 $pair = null;
  144.                 echo "!{$pair_id}\tclose, I, count=false\n";
  145.                 continue;
  146.             } elseif ($count > 0) {
  147.                 $bytes = @socket_recv($pair[0], $buf, 2048, 0);
  148.                 if ($bytes == 0) {
  149.                     socket_shutdown($pair[1], 2);
  150.                     socket_close($pair[1]);
  151.                     socket_shutdown($pair[0], 2);
  152.                     socket_close($pair[0]);
  153.                     $pair = null;
  154.                     echo "!{$pair_id}\tclose, I, bytes=0\n";
  155.                     continue;
  156.                 }
  157.                 echo "!I{$pair_id}\t{$bytes}\n";
  158.                 file_put_contents("/root/pta-{$start_session_time}-{$pair_id}-".microtime(true).'-i.dat', $buf);
  159.                 socket_write($pair[1], $buf, $bytes);
  160.             }
  161.  
  162.             $r = array($pair[1]);
  163.             $count = socket_select($r, $write = null, $except = null, 0);
  164.             if ($count === false) {
  165.                 socket_shutdown($pair[1], 2);
  166.                 socket_close($pair[1]);
  167.                 socket_shutdown($pair[0], 2);
  168.                 socket_close($pair[0]);
  169.                 $pair = null;
  170.                 echo "!{$pair_id}\tclose, O, count=false\n";
  171.                 continue;
  172.             } elseif ($count > 0) {
  173.                 $bytes = @socket_recv($pair[1], $buf, 2048, 0);
  174.                 if ($bytes == 0) {
  175.                     socket_shutdown($pair[1], 2);
  176.                     socket_close($pair[1]);
  177.                     socket_shutdown($pair[0], 2);
  178.                     socket_close($pair[0]);
  179.                     $pair = null;
  180.                     echo "!{$pair_id}\tclose, O, bytes=0\n";
  181.                     continue;
  182.                 }
  183.                 echo "!O{$pair_id}\t{$bytes}\n";
  184.                 file_put_contents("/root/pta-{$start_session_time}-{$pair_id}-".microtime(true).'-o.dat', $buf);
  185.                 socket_write($pair[0], $buf, $bytes);
  186.             }
  187.  
  188.             $except = array($pair[1], $pair[0]);
  189.             $count = socket_select($read = null, $write = null, $except, 0);
  190.             if ($count === false) {
  191.                 socket_shutdown($pair[1], 2);
  192.                 socket_close($pair[1]);
  193.                 socket_shutdown($pair[0], 2);
  194.                 socket_close($pair[0]);
  195.                 $pair = null;
  196.                 echo "!{$pair_id}\tclose, E, count=false\n";
  197.                 continue;
  198.             } elseif ($count > 0) {
  199.                 echo "!E{$pair_id}\n";
  200.                 socket_shutdown($pair[1], 2);
  201.                 socket_close($pair[1]);
  202.                 socket_shutdown($pair[0], 2);
  203.                 socket_close($pair[0]);
  204.                 $pair = null;
  205.                 echo "!{$pair_id}\tclose, E, count>0\n";
  206.                 continue;
  207.             }
  208.         }
  209.     };
  210.  
  211.     socket_shutdown($input_server, 2);
  212.     socket_close($input_server);
  213.  
  214. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement