Sockets: Соединение и Отправка пакетов через прокси сервера, на примере HTTP(S) слоя

Как лучше отправить и принять HTTP запрос в крупном приложении

  • Установив связь через сокет (Используя спец. Обертку)

    Голосов: 1 33,3%
  • Использовать cURL

    Голосов: 2 66,7%

  • Всего проголосовало
    3

Kutuz

Новичок
Здравствуйте, ребят можете подсказать как работать с проксями на прикладных уровнях , посредством только сокетов по tcp или ssl транспорту.
Интересует соединение с прокси, далее предварительная конвертация данных в тип кушаемый проксей, далее отправка и уже чтение.
Естественно можно использовать специальные HTTP прокси, но мы не ищем легких путей
Интересует так-же работа с smtp и так-же через прокси например типа Socks4/5.
Отсюда и строятся принципы туннелирования всех остальных протоколов, например pop imap и другие
Может есть у кого примеры в виде кусочков лапшекода?)

Сопутствующие ссылки:
https://ru.wikipedia.org/wiki/Туннелирование_(компьютерные_сети)
https://ru.wikipedia.org/wiki/SOCKS
https://ru.wikipedia.org/wiki/Tor
 
Что есть "крупное приложение"?
Ты ж понимаешь, что оба варианта приемлемы в зависимости от конкретной ситуации и задачи, да?
 
Под разные ситуации разные варианты, это да) Давайте сложим примеры скриптовки таких запросов в этой теме? и разберем эти возможные ситуации)
 
Зачем? 90% программистов не столкнутся с проблемами при использовании curl.
 
Искренне извеняюсь за свою изначальную неточность и недостаточную конкретность вопроса, просто я планирую архитектуру библиотеки, в которой все должно быть достаточно абстрактно и много-направленно, хотел узнать разные способы и средства достижения данной цели. Важна теоретическая часть)

Ребят ответте пожалуйста, можно ли в соксовом протоколе(имея активное, уже настроенное на некоторый дестинейшн соединение, при этом туннель был использован) не закрывая сокет задать другой дестинейшн и проделывать общение далее уже на него? это прямо касается производительности
 
может просто воспользоваться существующим транспортом вроде guzzle?
 
Да не, даже не спрашивай)
нужен ответ по соксу, я просто так и не пойму, можно ли в одном соединении последовательно менять сервера к которым мы подключаемся через сокс?
 
Ты такие вопросы задаёшь… что хоть стой, хоть падай.
Ты вообще представляешь себе, что есть соединение на уровне TCP протокола?
 
Не совсем, поэтому и спросил, может я не правильно вопрос поставил?)
 
Сложно хотя бы такой код выложить? где есть простое рукопожатие? может это куда проще чем Guzzle? простой императивный код - лапшакод, где все ясно
PHP:
function socks5($ip,$port, $to_host,$to_port){

    $socks = fsockopen($ip,$port);

    //Initiate the SOCKS handshake sequence.

    //Write our version an method to the server.
    //Version 5, 1 authentication method, no authentication. (For now)
    fwrite($socks, pack("C3", 0x05, 0x01, 0x00) );

    //Wait for a reply from the SOCKS server.
    $status = fread($socks,8192);

    //Check if server status is okay.
    if ( $status != pack("C2", 0x05, 0x00) ) {
        //Throw error if required.
        throw new \Exception(
            "SOCKS Server does not support this version and/or authentication method of SOCKS."
        );
    }

    //At this stage, our SOCKS socket should be open and ready to make its remote connection.
    //Send the connection request.
    fwrite( $socks, pack("C5", 0x05 , 0x01 , 0x00 , 0x03, strlen($to_host) ) . $to_host . pack("n", $to_port) );

    //Wait for a reply from the SOCKS server.
    $buffer = fread($socks,8192);

    $state = substr($buffer,0,4);

    if($state == pack("C4", 0x05, 0x00, 0x00, 0x01)){
        return $socks;
    }else {
        //Connection failed.
        throw new \Exception(
            "The SOCKS server failed to connect to the specificed host and port. ( ".$to_host.":".$to_port." )"
        );
    }
}
Открывается соединение с ($ip,$port) , жмем руки и задаем коннект c ($to_host,$to_port), далее в этот поток шли что хочешь по любому протоколу https, smtp, etc(смотря к какому $to_ip подключились).
А уже позже я узнал что нельзя изменить уже заданный хост порт у сокса, т.к любая комманда пущенная в сокет (fwrite) после рукопожатий, соксовая или даже 0x00 байт уйдет в конец(адресату), что оказалось логично.
 
Последнее редактирование:
Ну вот видишь. Оказалось, всё не так сложно, как казалось.
 
Да не сложно, я же написал в топике что нужны просто кусочки кода, ты же и сам мне ответил
Складывайте, разбирайте…
Сам то я знаю как работает клиентская часть сокетов, просто не знаю протоколов, что мне в сокеты писать, я не знаю)
В общем пишу либу Communication с поддержкой Туннелирования, туннелирование будет определятся в потоках т.к это наилучший вариант который годится для любых покрывающих протоколов что http что smtp

Потоки в таком случае намного проще чем курлы с точки зрения того функционала что я хочу получить

Могу привести пример некоторой части либы

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

Определение спецификации(здесь в виде наследования базового класса):
PHP:
class Smtp extends Specification{


        /**
         * Smtp constructor.
         */
        public function __construct(){
            $this->command('start',[
                'rules' => [
                    [ 'check' => [220], 'message' => 'Error connect to SMTP server', 'negate' => true ]
                ]
            ]);
            $this->command('hello',[
                'definition' => 'EHLO {{host}}',
                'rules' => [
                    [ 'check' => 250, 'message' => 'SMTP Hello error', 'negate' => true ]
                ]
            ]);
            $this->bundle('auth',[[
                'definition' => 'AUTH LOGIN',
                'rules' => [
                    ['check' => 334, 'message' => 'Authentication error(START)', 'negate' => true]
                ]
            ],[
                'definition' => '{{login}}',
                'rules' => [
                    ['check' => 334, 'message' => 'Authentication error(login)', 'negate' => true]
                ]
            ],[
                'definition' => '{{password}}',
                'rules' => [
                    ['check'=> 235, 'message' => 'AuthenticationMissed', 'negate' => true]
                ]
            ]]);
            $this->command('mail_from',[
                'definition' => 'MAIL FROM:<{{mail_from}}> SIZE={{size}}',
                'rules' => [
                    ['check' => 250, 'message' => 'Sender invalid','negate' => true]
                ]
            ]);
            $this->command('recipient',[
                'definition' => 'RCPT TO:<{{recipient}}>',
                'aggregator' => function(array $params){
                    $a = [];
                    if(isset($params['recipient'])){
                        if(is_scalar($params['recipient'])){
                            $a[] = $params['recipient'];
                        }
                        if(is_callable($params['recipient'])){
                            $params['recipient'] = call_user_func($params['recipient']);
                        }
                        foreach($params['recipient'] as $recipient){
                            $a[] = [
                                'recipient' => $recipient
                            ];
                        }
                    }
                    return $a;
                },
                'rules' => [[
                    'check'    => [250,220,251],
                    'message' => "Ошибка, адрес не может быть доступен",
                    'negate'  => true
                ]]
            ]);
            $this->bundle('data',[[
                'definition' => 'DATA',
                'rules' => [
                    ['check' => 354, 'message' => 'DATA pre send error','negate' => true]
                ]
            ],[
                'definition' => "{{data}}\r\n.",
                'rules' => [
                    ['check' => [220,250], 'message' => 'SMTP server not accepted send data','negate' => true]
                ]
            ]]);
            $this->command('reset', [ 'definition' => 'RESET' ]);
            $this->command('quit', [ 'definition' => 'QUIT' ]);
        }


        /**
         * @return mixed
         */
        public function getMaxLength(){
            return 515;
        }

        /**
         * @param $response
         * @return int
         */
        public function recognizeCode($response){
            return intval(substr($response,0,3));
        }

        /**
         * @param $command
         * @return string
         */
        public function convertBeforeSend($command){
            return $command . "\r\n";
        }


        /**
         * @param StreamInteractionInterface $connection
         * @return string
         */
        public function read(StreamInteractionInterface $connection){
            $data = "";$length = $this->getMaxLength();
            while($str = $connection->readLine($length)){
                $data .= $str;
                if(substr($str,3,1) == " ") { break; }
            }
            return $data;
        }

        /**
         * @return ConnectionInterface
         */
        public function createConnection(){
            return new Socket([]);
        }

        /**
         * @param ProcessSequenceInterface $processSequence
         * @return mixed
         */
        public function beforeSequence(ProcessSequenceInterface $processSequence){
            $this->getCommand('start')->run($processSequence,[]);
        }

        /**
         * @param $processSequence
         * @return mixed
         */
        public function afterSequence(ProcessSequenceInterface $processSequence){}

        /**
         * @param ProcessSequenceInterface $processSequence
         * @return mixed
         */
        public function continueSequence(ProcessSequenceInterface $processSequence){

        }
    }
Использование этой спецификации

PHP:
/**
 * 'params_merge' - если Тру, то весь конфиг будет закидываться как аргументы в каждую последующую команду
 *
 */
$specification = new Specification\Smtp();
$sequence = $specification->createSequence();
$sequence->setSpecification($specification);
$sequence->setConfig([
    'params_merge' => true,

    'scheme'       => 'ssl',
    'host'         => 'smtp.mail.ru',
    'port'         => 465,

    'login'        => null,
    'password'     => null,

    'mail_from'    => null,
    'recipient'    => null,

    'data'         => null,
    'size'         => null,
]);
$sequence->setSequence([
    'hello',
    'auth',
    'mail_from',
    'recipient',
    'data'
]);
$sequence->run();

Предназначение у этого компонента более расположено к интеграции функциональности в пользовательский интерфейс, т.к легко с помощью массивов декларировать как Спецификации так и Последовательности

К сожалению, у этой компоненты либы есть минусы в виде отсутствия туннелирования и отсутствия возможности указывать или требовать выполнение определенной команды в зависимости от того или иного ответа полученного от сервера прямо во время выполнения (то есть считать ответ где описано что требуется авторизация и автоматически подставить в нужное место вызов этой команды, а в случае отсутствия нужных агрументов выбросить исключение) или наоборот если авторизация не описана убрать команду из очереди на выполнение

Хотя случай с динамикой очереди команд на выполнение не так уж и нужен в smtp)
 
Последнее редактирование:
"Я не знаю протоколов но пишу библиотеку…"
Внушает доверие, да.
 
Сверху