100 Line PHP Code implementation SOCKS5 Proxy Server, 100 rows SOCKS5
Two days ago on the B station saw a small guy paper 100 yuan assembled a computer to play lol picture quality smooth, whim 100 lines of code can (simple) realize what fun. I mainly do PHP development, so I have this article.
Of course, because PHP (not swoole extension) itself is not good at doing network server programming, so this agent, just a toy, away from the daily use a little distance. If you want to use stable and reliable encryption (so can wo learn to surf the Internet) agent, you can use this: Https://github.com/momaer/asocks-go is also 100来 line code using GO implementation.
The process of writing found that PHP multithreading is still difficult. For example, I started thinking of creating a new thread for each connection. But this thread has to be saved (for example, saved to an array), as in the official example: Https://github.com/krakjoe/pthreads/blob/master/examples/socketserver.php to put in $clients this array, otherwise, you try (curl-l a 301 address) to know what happened.
This example says in the real world, does something here to ensure clients not running is destroyed but, How to destroy a connection that is no longer running is not said. Well. I tried to put the $clients into a class, the class passed to the thread class, and then the line class to end when the corresponding connection to the $clients unset off, no fruit.
That, the following is the use of the thread pool to implement the proxy, according to the truth, exit the pool to shutdown (), listen to the socket shutdown, but the hundred lines of code, it is not forced, with CTRL + C , let the operating system to reclaim resources.
php not good at network programming embodied in where?" First I use STREAM_SOCKET_XXX-related functions, why not use the socket extension? Because of a problem with the socket extension, see: Https://github.com/krakjoe/pthreads/issues/581 While 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 are all things to consider when writing proxies. For example, when connecting to a remote target server, there is no time-out control and it is easy to run full of thread pools.
Test, using curl can, right, currently only support remote DNS resolution, why? Because this toy later but to achieve wo study online 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; 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 not correct. ', 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));}
http://www.bkjia.com/PHPjc/1125264.html www.bkjia.com true http://www.bkjia.com/PHPjc/1125264.html techarticle 100 Line PHP code implementation SOCKS5 Proxy Server, 100 lines socks5 the first two days on the B station saw a small guy paper 100 yuan assembling a computer to play lol quality smooth, the whim of 100 lines of code can (simple) real ...