100 lines of PHP code to implement SOCKS5 proxy server _php skills

Source: Internet
Author: User
Tags curl php multithreading unpack thread class

Two days ago in B station to see a small group of paper 100 to assemble a computer hit LOL quality fluent, whim 100 lines of code can (simple) realize what fun. I mainly do PHP development, so there is the article.

Of course, because PHP (not swoole expansion) itself is not good at doing network server programming, so this agent, just a toy, away from the day-to-day use of a little distance. If you want to use a stable and reliable encryption (so you can learn the Web) agent, you can use this: Https://github.com/momaer/asocks-go is also 100来 line code using GO implementation.

Writing in the process of discovering PHP multithreading is still difficult. For example, I started thinking about creating a new thread for each connection. But this thread has to be saved (for example, to an array), as in the official example: https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php to put it in the $clients array, otherwise, you try (curl-l a 301 address) to know what happened.

This example says in the "real world", do something-ensure clients not running are destroyed but how to destroy a connection that no longer runs does not speak. Well. I tried to put the $clients into a class, pass the class to the thread class, and then $clients the corresponding connection to the unset at the end of the thread class, without fruit.

That, the following is the use of the thread pool to achieve the agent, according to the truth, when the pool to exit shutdown (), listening to the socket also to shutdown, but hundred lines of code, do not reluctantly, with the CTRL + C, let the operating system to reclaim resources.

What is the embodiment of PHP not good at network programming? First I use the stream_socket_xxx related function, why not use the socket extension? Because of a problem with the socket extension, see: https://github.com/krakjoe/pthreads/issues/581 and Stream_set_timeout to stream_socket_ Recvfrom These advanced operations, which do not work, see : http://php.net/manual/en/function.stream-set-timeout.php and these, you need to consider when writing an agent. For example, when connecting to a remote target server, there is no timeout control, it is easy to run the thread pool full.

test, the use of curl can be, right, currently only support remote DNS resolution, why?" Because this toy late but want to realize wo Dou learn to surf the net of yo: Curl--socks5-hostname 127.0.0.1:1080  http ://ip.cn

Class Pipe extends threaded {private $client;
  Private $remote;
    Public function __construct ($client, $remote) {$this->client = $client; 
  $this->remote = $remote; Public Function Run () {for (;;)
        {$data = Stream_socket_recvfrom ($this->client, 4096);
        if ($data = = False | | strlen ($data) = = 0) {break;
        } $sendBytes = Stream_socket_sendto ($this->remote, $data);
        if ($sendBytes <= 0) {break;
    } stream_socket_shutdown ($this->client, STREAM_SHUT_RD);
  Stream_socket_shutdown ($this->remote, STREAM_SHUT_WR);
  Class Client extends threaded {public $fd; 
  Public function __construct ($FD) {$this->fd = $FD;
    The public Function run () {$data = Stream_socket_recvfrom ($this->fd, 2);
    $data = Unpack (' c* ', $data);
      if ($data [1]!== 0x05) {stream_socket_shutdown ($this->fd, stream_shut_rdwr);
 Echo ' protocol is incorrect. ', Php_eol;     Return
    } $nmethods = $data [2];
    $data = Stream_socket_recvfrom ($this->fd, $nmethods);
    Stream_socket_sendto ($this->fd, "\x05\x00");
    $data = Stream_socket_recvfrom ($this->fd, 4);
    $data = Unpack (' c* ', $data);
    $addressType = $data [4];
      if ($addressType = = 0x03) {//Domain $domainLength = unpack (' C ', Stream_socket_recvfrom ($this->fd, 1)) [1];
      $data = Stream_socket_recvfrom ($this->fd, $domainLength + 2);
      $domain = substr ($data, 0, $domainLength);
    $port = Unpack ("n", substr ($data,-2)) [1];
      else {Stream_socket_shutdown ($this->fd, stream_shut_rdwr);
    Echo ' Please use remote DNS resolution. ', Php_eol;
    Stream_socket_sendto ($this->fd, "\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00");
    echo "{$domain}:{$port}", Php_eol;
    $remote = Stream_socket_client ("tcp://{$domain}:{$port}");
      if ($remote = = False) {Stream_socket_shutdown ($this->fd, stream_shut_rdwr);
    Return } $pool = $this;worker->pipepool;
    $pipe 1 = new Pipe ($remote, $this->fd);

    $pipe 2 = new Pipe ($this->fd, $remote);
    $pool->submit ($pipe 1);
  $pool->submit ($pipe 2);
  Class Proxyworker extends Worker {public $pipePool;
  Public function __construct ($pipePool) {$this->pipepool = $pipePool;
}} $server = Stream_socket_server (' tcp://0.0.0.0:1080 ', $errno, $ERRSTR);

if ($server = = False) exit ($ERRSTR);
$pipePool = new Pool (worker::class);

$pool = new Pool (' Proxyworker ', [$pipePool]); for (;;)
  {$fd = @stream_socket_accept ($server, 60);
  if ($FD = = false) continue;
$pool->submit (New Client ($FD)); }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.