100行PHP代碼實現socks5Proxy 伺服器_php技巧

來源:互聯網
上載者:User

前兩天在B站上看到一個小夥紙100元組裝個電腦打LOL畫質流暢,突發奇想100行代碼能(簡單)實現個啥好玩的。我主要是做php開發的,於是就有了本文。

當然,由於php(不算swoole擴充)本身不擅長做網路服務端編程,所以這個代理,只是個玩具,離日常使用有點距離。如果想使用穩定可靠的加密(所以能禾鬥學上網)代理,可以用這個:https://github.com/momaer/asocks-go也是100來行代碼使用go實現。

寫的過程中發現php多線程還是難的。比如我開始想每個串連建立一個線程。但這個線程得儲存起來(比如儲存到數組),比如官方例子中的這個:https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php 要放到$clients這個數組裡,不然,你試試(curl -L一個要301的地址)就知道出現什麼情況了。

這個例子說了in the real world, do something here to ensure clients not running are destroyed 但是,如何把不再啟動並執行串連銷毀卻沒有講。恩。我試了把$clients放到一個類裡,把類傳給線程類,然後線上程類要結束時把$clients裡對應的串連給unset掉,無果。

那,以下就是使用線程池來實現的代理,按道理講,退出時池要shutdown(),監聽socket也要shutdown的,但百行代碼,就不勉強了,隨著ctrl + c,就讓作業系統來回收資源吧。

php不擅長網路編程體現在哪裡呢?首先我用的是stream_socket_XXX相關的函數,為啥不用socket擴充呢?因為socket擴充有問題,參見:https://github.com/krakjoe/pthreads/issues/581 而stream_set_timeout對stream_socket_recvfrom這些進階操作,不起作用,參見:http://php.net/manual/en/function.stream-set-timeout.php 而這些,在寫代理時都需要考慮的。比如串連遠程目標伺服器時,沒有逾時控制,很容易就線程池跑滿了。

測試的話,使用curl即可,對了,目前只支援遠程dns解析,為啥呢?因為這個玩具後期可是要實現禾鬥學上網的喲: 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;   }  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 '協議不正確.', 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 '請使用遠程dns解析.', 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;    $pipe1 = new Pipe($remote, $this->fd);    $pipe2 = new Pipe($this->fd, $remote);    $pool->submit($pipe1);    $pool->submit($pipe2);  }}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(200, Worker::class);$pool = new Pool(50, 'ProxyWorker', [$pipePool]);for( ; ; ) {  $fd = @stream_socket_accept($server, 60);  if ($fd === false)    continue;  $pool->submit(new Client($fd));}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.