#!/usr/bin/php /proc/sys/net/ipv4/ip_forward * iptables -F -t nat * iptables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --dport 443 --to-ports 8443 * iptables -t nat -A PREROUTING -i eth0 -j ACCEPT * * Потом * ./proxy_to_api.php -p 8443 * ./proxy_to_api.php -p 8080 --no-ssl * * На windows-клиенте * route add 93.184.216.34 mask 255.255.255.255 192.168.1.14 metric 1 * * Не забудьте включить на Fiddler'е "принимать подключения из вне", а на клиенте — импортнуть рутовый сертификат */ $options = getopt('d:p:', array( 'no-ssl' )); $domain = array_key_exists('d', $options) ? $options['d'] : 'example.com'; $port = array_key_exists('p', $options) ? (int) $options['p'] : 8443; $ssl_enabled = !array_key_exists('no-ssl', $options); $input_server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($input_server === false) { echo "can not spawn socket\n"; return; } if (@socket_bind($input_server, '0.0.0.0', $port) === false) { echo "can not bind socket: ".socket_strerror(socket_last_error($input_server))."\n"; return; } if (@socket_listen($input_server, 5) === false) { echo "can not listen socket: ".socket_strerror(socket_last_error($input_server))."\n"; return; } $our_proxy = gethostbyname('192.168.1.16'); $real_api_ip = gethostbyname($domain); socket_set_nonblock($input_server); /** * @var resource[][] $socket_pairs */ $socket_pairs = array(); $start_session_time = time(); while (true) { // Принимаем подключения $input_socket = @socket_accept($input_server); if ($input_socket !== false) { echo "CONNEСT\n"; $output_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $result = socket_connect($output_socket, $our_proxy, 8888);// Порт поменять, это до Фиддлера if ($result === false) { socket_shutdown($output_socket); socket_close($output_socket); socket_shutdown($input_socket); socket_close($input_socket); continue; } if ($ssl_enabled) { $first_packet_bytes = @socket_recv($input_socket, $first_packet_buf, 2048, 0); if (!preg_match('_([a-z0-9.-]{5,})_i', $first_packet_buf, $a)) { echo "First input ssl packet malformed\n"; continue; } $real_domain = $a[1]; $init_string = "CONNECT {$real_domain}:443 HTTP/1.1\n". "HOST: {$real_domain}\n\n"; socket_write($output_socket, $init_string, strlen($init_string)); $full_buf = ''; while (!preg_match('_\\r\\n\\r\\n_', $full_buf)) { $bytes = @socket_recv($output_socket, $buf, 1000, 0); $full_buf .= $buf; if ($bytes == 0) { echo "Connect-proxy malformed answer\n"; socket_shutdown($output_socket); socket_close($output_socket); socket_shutdown($input_socket); socket_close($input_socket); continue 2; } } $a = explode("\r\n\r\n", $full_buf, 2); if (!preg_match('_^HTTP/1\\.[01] ([0-9]+) _', $a[0], $b)) { echo "Can not establish properly proxy connect\n"; socket_shutdown($output_socket); socket_close($output_socket); socket_shutdown($input_socket); socket_close($input_socket); continue; } elseif ($b[1] != 200) { echo "Can not establish properly proxy connect. HTTP Status {$b[1]}\n"; socket_shutdown($output_socket); socket_close($output_socket); socket_shutdown($input_socket); socket_close($input_socket); continue; } if ($first_packet_bytes > 0) {// Что очевидно, иначе бы сюда код не пришёл socket_write($output_socket, $first_packet_buf, $first_packet_bytes); } if (strlen($a[1]) > 0) { socket_write($input_socket, $a[1], strlen($a[1])); } echo "CONNEСT #".count($socket_pairs)." ESTABLISHED TO {$real_domain}\n"; unset($first_packet_buf, $first_packet_bytes, $a, $full_buf, $bytes); $socket_pairs[] = array($input_socket, $output_socket, $real_domain); } else { $socket_pairs[] = array($input_socket, $output_socket); } unset($input_socket, $output_socket); } // Обрабатываем подключения (кидаем пакеты) foreach ($socket_pairs as $pair_id => &$pair) { if ($pair === null) { continue; } $r = array($pair[0]); $count = socket_select($r, $write = null, $except = null, 0); if ($count === false) { socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, I, count=false\n"; continue; } elseif ($count > 0) { $bytes = @socket_recv($pair[0], $buf, 2048, 0); if ($bytes == 0) { socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, I, bytes=0\n"; continue; } echo "!I{$pair_id}\t{$bytes}\n"; file_put_contents("/root/pta-{$start_session_time}-{$pair_id}-".microtime(true).'-i.dat', $buf); socket_write($pair[1], $buf, $bytes); } $r = array($pair[1]); $count = socket_select($r, $write = null, $except = null, 0); if ($count === false) { socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, O, count=false\n"; continue; } elseif ($count > 0) { $bytes = @socket_recv($pair[1], $buf, 2048, 0); if ($bytes == 0) { socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, O, bytes=0\n"; continue; } echo "!O{$pair_id}\t{$bytes}\n"; file_put_contents("/root/pta-{$start_session_time}-{$pair_id}-".microtime(true).'-o.dat', $buf); socket_write($pair[0], $buf, $bytes); } $except = array($pair[1], $pair[0]); $count = socket_select($read = null, $write = null, $except, 0); if ($count === false) { socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, E, count=false\n"; continue; } elseif ($count > 0) { echo "!E{$pair_id}\n"; socket_shutdown($pair[1], 2); socket_close($pair[1]); socket_shutdown($pair[0], 2); socket_close($pair[0]); $pair = null; echo "!{$pair_id}\tclose, E, count>0\n"; continue; } } }; socket_shutdown($input_server, 2); socket_close($input_server); ?>