每日一搏 | 100行 PHP 代碼實現 socks5 Proxy 伺服器

來源:互聯網
上載者: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 socketXXX相關的函數,為啥不用socket擴充呢?因為socket擴充有問題,參見:https://github.com/krakjoe/pthreads/issues/581 而stream settimeout對stream socketrecvfrom這些進階操作,不起作用,參見:http://php.net/manual/en/function.stream-set-timeout.php 而這些,在寫代理時都需要考慮的。比如串連遠程目標伺服器時,沒有逾時控制,很容易就線程池跑滿了。

測試的話,使用curl即可,對了,目前只支援遠程dns解析,為啥呢?因為這個玩具後期可是要實現禾鬥學上網的喲: curl --socks5-hostname 127.0.0.1:1080 http://ip.cn

```php Class Pipe extends Threaded { private $client; private $remote; public function _ construct($client, $remote) { $this->client = $client; $this->remote = $remote; } public function run() { for ( ; ; ) { $data = streamsocket recvfrom($this->client, 4096); if ($data === false || strlen($data) === 0) { break; } $sendBytes = streamsocket sendto($this->remote, $data); if ($sendBytes<= 0) { break; } } stream_socket_shutdown($this->client, STREAMSHUT RD); streamsocket shutdown($this->remote, STREAMSHUT_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 socketserver('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 socketaccept($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.