Over 100 lines of PHP code are implemented for the socks5 proxy server [2] and phpsocks5. More than 100 lines of PHP code implement socks5 proxy server [2], phpsocks5100 multiple lines of PHP code implement socks5 proxy server. this time swoole is used for pure asynchronous writing and the state machine is used for data processing. Project 100 implement the socks5 proxy server with multiple lines of PHP code [2], phpsocks5
Over 100 lines of PHP code are used to implement the socks5 proxy server. this time, swoole is used for pure asynchronous writing and the state machine is used to process data. Currently, it is under pressure to access open source China wood, but it is under great pressure to access NetEase News. I found that I wrote proxies in other languages, and it was a lot of pressure to access NetEase News. Ga, learning is not refined.
I don't know much about swoole. I don't know how to handle socket shutdown. I only close reading/writing, and how to handle connection timeout and read/write timeout. I can see on the Internet that it is troublesome to use the timer. so, although I am using the proxy for this time, there is usually no problem, but there is still some way to go from the product-level proxy.
To use multiple cores, use the process mode and set the number of workers to the number of CPUs.
<? Phpclass Client {public $ connected = true; public $ data = ''; public $ remote = null; public $ status = 0;} class Server {public $ clients = []; public function start () {$ server = new swoole_server ('0. 0.0.0 ', 8388, SWOOLE_BASE, SWOOLE_SOCK_TCP); $ server-> set (['max _ Conn' => 1000, 'daemonize' => 1, 'reactor _ num' => 1, 'Worker _ num' => 1, 'Dispatch _ mode' => 2, 'buffer _ output_size '=> 128*1024*1024,' Open_cpu_affinity '=> 1, 'open _ tcp_nodelay' => 1, 'log _ file' => 's5 S5 _ server. log',]); $ server-> on ('connect ', [$ this, 'onconnect']); $ server-> on ('receive ', [$ this, 'onreceive ']); $ server-> on ('close', [$ this, 'onclose']); $ server-> start ();} public function onConnect ($ server, $ fd, $ fromID) {$ this-> clients [$ fd] = new Client ();} public function onReceive ($ server, $ fd, $ fromID, $ data) {($ this-> cl Ients [$ fd])-> data. = $ data; $ this-> parse ($ server, $ fd);} public function onClose ($ server, $ fd, $ fromID) {$ client = $ this-> clients [$ fd]; $ client-> connected = false;} private function parse ($ server, $ fd) {$ client = $ this-> clients [$ fd]; switch ($ client-> status) {case 0: {if (strlen ($ client-> data)> = 2) {$ request = unpack ('C * ', substr ($ client-> data, 0, 2); if ($ request [1]! = 0x05) {echo 'protocol incorrect :'. $ request [1], PHP_EOL; $ server-> close ($ fd); break;} $ nmethods = $ request [2]; if (strlen ($ client-> data) >=2 + $ nmethods) {$ client-> data = substr ($ client-> data, 2 + $ nmethods ); $ server-> send ($ fd, "\ x05 \ x00"); $ client-> status = 1 ;}} case 1: {if (strlen ($ client-> data) <5) break; $ request = unpack ('C * ', $ client-> data ); $ aType = $ request [4]; if ($ aType = 0x03) {// do Main $ domainLen = $ request [5]; if (strlen ($ client-> data) <5 + $ domainLen + 2) {break ;} $ domain = substr ($ client-> data, 5, $ domainLen); $ port = unpack ('N', substr ($ client-> data, 5 + $ domainLen, 2) [1]; $ client-> data = substr ($ client-> data, 5 + $ domainLen + 2 );} else if ($ aType = 0x01) {// ipv4 $ domain = long2ip (unpack ('N', substr ($ client-> data, 4, 4 )) [1]); $ port = unpack ('N', substr ($ client-> Data, 8, 2) [1]; $ client-> data = substr ($ client-> data, 10);} atype not supported by else {echo: '. $ aType, PHP_EOL; $ server-> close ($ fd); break;} $ remote = new swoole_client (SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC); $ remote-> on ('connect ', function ($ cli) use ($ client, $ server, $ fd, $ remote) {$ server-> send ($ fd, "\ x05 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00"); $ client-> status = 2; $ client-> remote = $ remote;}); $ remot E-> on ("error", function (swoole_client $ cli) use ($ server, $ fd) {// $ server-> send ($ fd ,""); // todo cannot connect to remote echo 'Connect to remote error. ', PHP_EOL; $ server-> close ($ fd) ;}); $ remote-> on ('receive', function ($ cli, $ data) use ($ server, $ fd, $ client) {if (! $ Client-> connected) {echo 'connection has been closed. ', PHP_EOL; return ;}$ server-> send ($ fd, $ data) ;}); $ remote-> on ('close', function ($ cli) use ($ server, $ fd, $ client) {$ client-> remote = null;}); if ($ aType = 0x03) {swoole_async_dns_lookup ($ domain, function ($ host, $ ip) use ($ remote, $ port, $ server, $ fd) {// todo processing when the host is empty. It seems that non-existing domain names are resolved to the local Internet ip address, strange if (empty ($ ip) | empty ($ host) {echo "host :{$ host}, ip: {$ ip} \ n "; $ server-> close ($ fd); return ;}$ remote-> connect ($ ip, $ port );});} else {$ remote-> connect ($ domain, $ port) ;}} case 2: {if (strlen ($ client-> data) === 0) {break ;} if ($ client-> remote === null) {echo 'remote connection has been closed. ', PHP_EOL; break;} $ sendByteCount = $ client-> remote-> send ($ client-> data ); if ($ sendByteCount = false | $ sendByteCount <strlen ($ client-> data) {echo 'data length: ', strlen ($ client-> data ), 'Send byte count: ', $ sendByteCount, PHP_EOL; echo $ client-> data, PHP_EOL; $ server-> close ($ fd );} $ client-> data = '';}}} (new Server ()-> start ();
Listen 100 lines of PHP code to implement the socks5 proxy server. this time, swoole is used for pure asynchronous writing and the state machine is used for data processing. Contents...