The 100-line PHP code implements the socks5 proxy server and the 100-line socks5. 100 lines of PHP code to implement the socks5 proxy server, 100 lines of socks5 two days ago on the B Station saw a guy paper 100 yuan to assemble a computer to play LOL smooth picture quality, whimsy 100 lines of code can (simple) implement 100 lines of PHP code to implement the socks5 proxy server and 100 lines of socks5
Two days ago, I saw a guy who made up 100 yuan of paper on the B Station and made a smooth picture of LOL. I was wondering what fun it would be if I had 100 lines of code (simple. I am mainly engaged in php development, so I have this article.
Of course, because php (not swoole extension) itself is not good at network server programming, this proxy is just a toy, a little away from daily use. If you want to use a stable and reliable encryption proxy (so you can learn to access the Internet), you can use this: https://github.com/momaer/asocks-goto also use the Gox code.
It is difficult to find multiple threads in php during writing. For example, I started to create a thread for each connection. But this thread has to be saved (such as saved to the array), such as the official example of this: https://github.com/krakjoe/pthreads/blob/master/examples/SocketServer.php to put in the $ clients array, otherwise, you can try (curl-L an address that requires 301) to know what is going on.
In the real world, do something here to ensure clients not running are destroyed, but how to destroy a connection that is no longer running is not mentioned. Well. I tried to put $ clients into a class and pass the class to the thread class. Then, when the thread class is about to end, the connection corresponding to $ clients will be dropped to unset.
Then, the following is the proxy implemented by using the thread pool. in principle, shutdown () is required for the pool to exit, and shutdown is required for listening to the socket. However, if there are hundreds of lines of code, you won't be forced, with ctrl + c, let the operating system recycle resources.
Where is php not good at network programming? First, I used stream_socket_XXX related functions. why not use socket extension? Because of socket expansion problems, see: https://github.com/krakjoe/pthreads/issues/581 and stream_set_timeout for stream_socket_recvfrom these advanced operations, does not work, see: http://php.net/manual/en/function.stream-set-timeout.php and these, need to consider when writing the agent. For example, when connecting to the remote target server, there is no timeout control, and it is easy to run the thread pool full.
For testing, use curl. By the way, only remote dns resolution is supported Currently. why? Because this toy later but to achieve hedou learning 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;} s Tream_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 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 '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; $ 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: 100', $ errno, $ errstr ); if ($ server = false) exit ($ errstr); $ pipePool = new Pool (200, Worker: class); $ pool = new Pool (50, 'xyworker', [$ pipePool]); for (;) {$ fd = @ stream_socket_accept ($ server, 60); if ($ fd = false) continue; $ pool-> submit (new Client ($ fd ));}
Two days ago, I saw a guy on the B Station who made 100 yuan of paper and assembled a computer. LOL the quality was smooth, and the whimsical 100 lines of code could be (simple) real...