Home>Article>Backend Development> PHP simply implements socks5 proxy server

PHP simply implements socks5 proxy server

*文
*文 Original
2017-12-29 18:58:44 15999browse

1What fun thing can be achieved (simply) with 00 lines of code? This article uses an example to show how to simply implement the socks5 proxy server module with 100 lines of PHP code. I hope it will be helpful to everyone.

Of course, since PHP (not counting the swoole extension) itself is not good at network server programming, this agent is just a toy and is a bit far away from daily use. .

During the writing process, I found that PHP multi-threading is still difficult. For example, I started to want to create a new thread for each connection. But this thread must be saved (for example, saved in an array) and placed in the $clients array. Otherwise, you can try (curl -L an address that requires 301) and you will know what happens.

Then, the following is an agent implemented using a thread pool. Logically speaking, the pool needs to be shut down() when exiting, and the listening socket must also be shut down. However, with a hundred lines of code, there is no need to Reluctantly, with ctrl + c, let the operating system reclaim resources.

Why is it that PHP is not good at network programming? First of all, I used the stream_socket_XXX related functions. Why not use socket extension? Because there is a problem with the socket extension. However, stream_set_timeout has no effect on advanced operations such as stream_socket_recvfrom. And these need to be considered when writing an agent. For example, when connecting to a remote target server, there is no timeout control, and the thread pool can easily become full.

For testing, just use curl. By the way, currently only remote dns resolution is supported. Why? Because this toy will need to be used to access the Internet later: 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)); }

Related recommendations:

php uses swoole to update client data in real time

What are the steps to install swoole under Windows?

PHP learning CURL crawler example

The above is the detailed content of PHP simply implements socks5 proxy server. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn