Skip to content

Instantly share code, notes, and snippets.

@zwjzxh520
Last active October 21, 2016 11:06
Show Gist options
  • Save zwjzxh520/659e8ead2334860a92757e2252c66c42 to your computer and use it in GitHub Desktop.
Save zwjzxh520/659e8ead2334860a92757e2252c66c42 to your computer and use it in GitHub Desktop.
PHP 简易socks5客户端。支持密码方式验证
<?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