Last active
October 21, 2016 11:06
-
-
Save zwjzxh520/659e8ead2334860a92757e2252c66c42 to your computer and use it in GitHub Desktop.
PHP 简易socks5客户端。支持密码方式验证
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* PHP 简易socks5客户端。支持密码方式验证 | |
*/ | |
$user = 'root'; | |
$pass = '123456'; | |
$port = 80; | |
$host = 'www.baidu.com'; | |
$socks5 = new socks5('127.0.0.1', 1088); | |
$socks5->setSocksAuth($user, $pass); | |
$socks5->connect('www.baidu.com', 80); | |
if (empty($socks5->lastError)) { | |
$data = "GET / HTTP/1.1\r\n". | |
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\r\n". | |
"Connection: close\r\n". | |
"Host: www.baidu.com\r\n\r\n"; | |
$socks5->send($data); | |
$response = $socks5->receive(); | |
echo $response; | |
} else { | |
echo $socks5->lastError; | |
} | |
class socks5 { | |
protected $socksHost = ''; | |
protected $socksPort = 1080; | |
protected $socksAuth = ''; | |
protected $socks; | |
protected $timeout = 5; | |
public $lastError = ''; | |
public function __construct($socksHost, $socksPort = 1080) | |
{ | |
$this->socksHost = $socksHost; | |
$this->socksPort = $socksPort; | |
} | |
public function setSocksAuth($username, $password) | |
{ | |
$this->socksAuth = pack('C2', 0x01, strlen($username)) . $username . pack('C', strlen($password)) . $password; | |
} | |
public function connect($host, $port) | |
{ | |
$chrPort = chr($port >> 8) . chr($port & 255); | |
$address = gethostbyname($host); | |
$address = implode('', array_map('chr', explode('.', $address))); | |
$target = "\5\1\0\1" . $address . $chrPort; | |
$fsock = fsockopen($this->socksHost, $this->socksPort); | |
socket_set_timeout($fsock, $this->timeout); | |
$request = "\5\1"; | |
if (empty($this->socksAuth)) { | |
$request .= "\0"; | |
} else { | |
$request .= "\2"; | |
} | |
if (fputs($fsock, $request) != strlen($request)) { | |
$this->lastError = '1. 数据发送失败!'; | |
return false; | |
} | |
$firstResponse = fgets($fsock, 3); | |
if (strlen($firstResponse) != 2 && ($firstResponse != "\5\0" || $firstResponse != "\5\2")) { | |
$this->lastError = '2. 数据接收异常!接收:'.$this->bin($firstResponse); | |
return false; | |
} | |
if ($firstResponse == "\5\2") { | |
if (empty($this->socksAuth)) { | |
$this->lastError = '3. 未设置用户名和密码'; | |
return false; | |
} else { | |
fputs($fsock, $this->socksAuth); | |
$secondResponse = fgets($fsock, 3); | |
if ($secondResponse != "\1\0") { | |
$this->lastError = '3. 用户名和密码不正确'; | |
return false; | |
} | |
} | |
} | |
if ($firstResponse == pack("C*", 5, 255)) { | |
$this->lastError = '4. 请检查服务器是否需要用户名/密码验证'; | |
return false; | |
} | |
if (fputs($fsock, $target) != strlen($target)) { | |
$this->lastError = '4. 数据包未能成功发送'; | |
return false; | |
} | |
$response = fgets($fsock, 5); | |
if ($response != "\5\0\0\1" ) { | |
$this->lastError = '5. 目标服务器'.$host.':'.$port.'连接失败'; | |
return false; | |
} | |
$this->socks = $fsock; | |
return true; | |
} | |
static public function bin($response) { | |
return implode(' ', unpack('C*', $response)); | |
} | |
static public function output($response) { | |
echo self::bin($response).PHP_EOL; | |
} | |
public function send($data) | |
{ | |
return fwrite($this->socks, $data); | |
} | |
public function receive() | |
{ | |
$response = ''; | |
while (!feof($this->socks)) { | |
$response .= fread($this->socks, 1024); | |
} | |
if ($response) { | |
$response = substr($response, 6); | |
} | |
return $response; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment