infostars / socks-react
异步 SOCKS 代理连接客户端和服务器实现,通过 SOCKS5 或 SOCKS4(a) 代理服务器隧道任何 TCP/IP 协议,基于 ReactPHP 构建。
Requires
- php: >=5.3
- react/promise: ^2.1 || ^1.2
- react/socket: ^1.1
Requires (Dev)
- clue/block-react: ^1.1
- clue/connection-manager-extra: ^1.0 || ^0.7
- phpunit/phpunit: ^6.0 || ^5.7 || ^4.8.35
- react/event-loop: ^1.0 || ^0.5 || ^0.4 || ^0.3
README
异步 SOCKS 代理连接客户端和服务器实现,通过 SOCKS5 或 SOCKS4(a) 代理服务器隧道任何 TCP/IP 协议,基于 ReactPHP 构建。
SOCKS 代理协议族(SOCKS5、SOCKS4 和 SOCKS4a)通常用于通过中介("代理")隧道 HTTP(S) 流量,以隐藏原始地址(匿名性)或绕过地址封锁(地理封锁)。虽然许多(公共)SOCKS 代理服务器通常仅限于 HTTP(S) 端口 80
和 443
,但技术上可以使用它来隧道任何 TCP/IP 协议(HTTP、SMTP、IMAP 等)。此库提供简单的 API 来为您创建这些隧道连接。因为它实现了 ReactPHP 的标准 ConnectorInterface
,因此可以简单地替换为正常连接器。这使得将 SOCKS 代理支持添加到几乎所有现有的高级协议实现变得相当简单。除了客户端,它还提供了一个简单的 SOCKS 服务器实现,允许您使用自定义业务逻辑构建自己的 SOCKS 代理服务器。
- 异步执行连接 - 并行发送任意数量的 SOCKS 请求,并在结果到来时立即处理它们的响应。基于 Promise 的设计提供了一个 合理的 接口来处理超出范围响应和可能的连接错误。
- 标准接口 - 通过实现 ReactPHP 的标准
ConnectorInterface
,可以轻松集成现有高级组件。 - 轻量级、SOLID 设计 - 提供了一个薄抽象层,它是 足够好 的,不会妨碍您。基于经过良好测试的组件和已确立的概念,而不是重新发明轮子。
- 良好的测试覆盖率 - 附带自动化测试套件,并定期与野外的实际代理服务器进行测试。
目录
快速入门示例
安装后,您可以使用以下代码通过本地 SOCKS 代理服务器连接到 google.com:
$loop = React\EventLoop\Factory::create(); $connector = new React\Socket\Connector($loop); $client = new Clue\React\Socks\Client('127.0.0.1:1080', $connector); $client->connect('tcp://www.google.com:80')->then(function (ConnectionInterface $stream) { $stream->write("GET / HTTP/1.0\r\n\r\n"); }); $loop->run();
如果您还没有运行任何其他 SOCKS 代理服务器,您可以使用以下代码创建一个监听在 localhost:1080
的 SOCKS 代理服务器:
$loop = React\EventLoop\Factory::create(); // start a new SOCKS proxy server $server = new Clue\React\Socks\Server($loop); // listen on localhost:1080 $socket = new React\Socket\Server('127.0.0.1:1080', $loop); $server->listen($socket); $loop->run();
另请参阅 示例。
用法
客户端
Client
负责与您的 SOCKS 服务器实例进行通信。其构造函数简单接受一个 SOCKS 代理 URI 和一个用于连接到 SOCKS 代理服务器地址的连接器。
在其最简单形式中,您可以像这样传递 ReactPHP 的 Connector
:
$connector = new React\Socket\Connector($loop); $client = new Client('127.0.0.1:1080', $connector);
如果您使用默认的SOCKS端口1080,可以省略端口号。
$client = new Client('127.0.0.1', $connector);
如果您需要自定义连接器设置(DNS解析、TLS参数、超时、代理服务器等),您可以显式传递一个自定义的ConnectorInterface
实例。
$connector = new React\Socket\Connector($loop, array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' ) )); $client = new Client('my-socks-server.local:1080', $connector);
这是本包中的两个主要类之一。因为它实现了ReactPHP的标准ConnectorInterface
,它可以简单地替换为普通连接器。相应地,它只提供了一个公共方法,即connect()
方法。方法connect(string $uri): PromiseInterface<ConnectionInterface, Exception>
可用于建立流连接。它返回一个Promise,成功时以ConnectionInterface满足,出错时以Exception
拒绝。这使得向几乎所有高级组件添加SOCKS代理支持变得相当简单。
- $client = new SomeClient($connector); + $proxy = new Client('127.0.0.1:1080', $connector); + $client = new SomeClient($proxy);
普通 TCP 连接
SOCKS代理通常用于向目标发送HTTP(S)请求。然而,这实际上是在更高的协议层上执行的,而这个连接器实际上是一个通用的普通TCP/IP连接器。如上所述,您可以直接调用其connect()
方法来建立流式普通TCP/IP连接,并使用任何高级协议,如下所示。
$client->connect('tcp://www.google.com:80')->then(function (ConnectonInterface $stream) { echo 'connected to www.google.com:80'; $stream->write("GET / HTTP/1.0\r\n\r\n"); // ... });
您可以直接使用Client
,或者您可能想要将此连接器包装在ReactPHP的Connector
中。
$connector = new React\Socket\Connector($loop, array( 'tcp' => $client, 'dns' => false )); $connector->connect('tcp://www.google.com:80')->then(function (ConnectonInterface $stream) { echo 'connected to www.google.com:80'; $stream->write("GET / HTTP/1.0\r\n\r\n"); // ... });
请参阅第一个示例。
也可以省略tcp://
方案。传递任何其他方案将拒绝承诺。
可以通过取消其挂起的承诺来取消挂起的连接尝试。
$promise = $connector->connect($uri); $promise->cancel();
在挂起的承诺上调用cancel()
将取消到SOCKS服务器的底层TCP/IP连接以及/或SOCKS协议协商,并拒绝产生的承诺。
安全的 TLS 连接
如果您想在与目标之间建立安全的TLS连接(以前称为SSL),例如使用到目标网站的HTTPS,则也可以使用此类。您可以简单地将此连接器包装在ReactPHP的Connector
或低级SecureConnector
中。
$connector = new React\Socket\Connector($loop, array( 'tcp' => $client, 'dns' => false )); // now create an SSL encrypted connection (notice the $ssl instead of $tcp) $connector->connect('tls://www.google.com:443')->then(function (ConnectionInterface $stream) { // proceed with just the plain text data // everything is encrypted/decrypted automatically echo 'connected to SSL encrypted www.google.com'; $stream->write("GET / HTTP/1.0\r\n\r\n"); // ... });
请参阅第二个示例。
如果您使用低级SecureConnector
,则也可以省略tls://
方案。传递任何其他方案将拒绝承诺。
可以通过取消其挂起的承诺来取消挂起的连接尝试,就像通常那样。
请注意,安全TLS连接实际上是在此SOCKS客户端实现之外完全处理的。
您还可以选择将额外的SSL上下文选项传递给构造函数,如下所示。
$connector = new React\Socket\Connector($loop, array( 'tcp' => $client, 'tls' => array( 'verify_peer' => false, 'verify_peer_name' => false ), 'dns' => false ));
HTTP 请求
HTTP运行在本低级SOCKS实现之上。如果您想发出HTTP请求,可以添加对clue/reactphp-buzz的依赖。它可以通过通过SOCKS代理服务器发出所有HTTP请求与该库交互。这对于普通HTTP和TLS加密的HTTPS请求都有效。
协议版本
本库支持SOCKS5和SOCKS4(a)协议版本。它侧重于通过SOCKS代理服务器连接到目标主机的最常用核心功能。在此模式下,SOCKS代理服务器充当一个通用代理,允许高级应用协议通过它工作。
默认情况下,Client
通过SOCKS5与SOCKS服务器通信。这样做是因为SOCKS5是SOCKS协议家族的最新版本,通常在供应商之间有最好的支持。您还可以省略默认的socks://
URI方案。同样,socks5://
URI方案充当默认的socks://
URI方案的别名。
// all three forms are equivalent $client = new Client('127.0.0.1', $connector); $client = new Client('socks://127.0.0.1', $connector); $client = new Client('socks5://127.0.0.1', $connector);
如果您想明确设置协议版本为SOCKS4(a),您可以使用URI方案socks4://
作为SOCKS URI的一部分。
$client = new Client('socks4://127.0.0.1', $connector);
DNS 解析
默认情况下,Client
根本不执行任何DNS解析,而只是简单地将您尝试连接到的任何主机名转发到SOCKS服务器。因此,远程SOCKS服务器负责通过DNS查找任何主机名(这种默认模式因此被称为远程DNS解析)。如上所述,这种模式由SOCKS5和SOCKS4a协议支持,但不支持原始的SOCKS4协议,因为该协议缺乏通信主机名的途径。
另一方面,所有SOCKS协议版本都支持向SOCKS服务器发送目标IP地址。在此模式下,您要么必须坚持只使用IP(这通常不可行),要么在本地进行任何DNS查找,并且仅传输解析后的目标IP(这种模式因此称为本地DNS解析)。
默认的远程DNS解析在您的本地Client
无法解析目标主机名(因为它没有直接访问互联网)或如果它不应该解析目标主机名(因为其出站DNS流量可能被截获,特别是在使用Tor匿名网络时)时非常有用。
如上所述,Client
默认使用远程DNS解析。但是,将Client
包装在ReactPHP的Connector
中实际上执行本地DNS解析,除非明确定义否则。鉴于远程DNS解析假定是首选模式,所有其他示例都明确禁用DNS解析,如下所示
$connector = new React\Socket\Connector($loop, array( 'tcp' => $client, 'dns' => false ));
如果您想明确使用本地DNS解析(例如,在明确使用SOCKS4时),您可以使用以下代码
// set up Connector which uses Google's public DNS (8.8.8.8) $connector = new React\Socket\Connector($loop, array( 'tcp' => $client, 'dns' => '8.8.8.8' ));
请参阅第四个示例。
可以通过取消其挂起的承诺来取消挂起的连接尝试。
请注意,本地DNS解析实际上完全由本SOCKS客户端实现之外处理。
认证
本库支持SOCKS5服务器用户名/密码认证,如RFC 1929中定义。
在客户端,只需传递您用于认证的用户名和密码(见下文)。对于每个进一步的连接,客户端只需向服务器发送一个标志,表示有可用的认证信息。只有在服务器在初始握手期间请求认证时,实际的认证凭据才会发送到服务器。
请注意,密码以明文形式传输到SOCKS代理服务器,因此不应在您担心窃听的网络中使用此方法。
您可以将认证信息作为SOCKS URI的一部分传递。
$client = new Client('username:password@127.0.0.1', $connector);
请注意,如果用户名和密码包含特殊字符,则两者都必须进行百分编码。
$user = 'he:llo'; $pass = 'p@ss'; $client = new Client( rawurlencode($user) . ':' . rawurlencode($pass) . '@127.0.0.1', $connector );
如果SOCKS代理服务器需要用户名/密码认证,则认证细节将以明文形式传输到SOCKS代理服务器。如果缺少认证细节或远程SOCKS代理服务器不接受,它应拒绝每个连接尝试,并返回异常错误代码
SOCKET_EACCES
(13)。
认证仅支持协议版本 5(SOCKS5),因此将认证传递给 Client
强制使用协议版本 5,并会在您显式设置其他版本时提出警告。
// throws InvalidArgumentException new Client('socks4://user:pass@127.0.0.1', $connector);
代理链
Client
负责创建与 SOCKS 服务器的连接,然后该服务器连接到目标主机。
Client -> SocksServer -> TargetHost
有时可能需要通过另一个 SOCKS 服务器建立出站连接。例如,如果您想隐藏原始地址,这可能会很有用。
Client -> MiddlemanSocksServer -> TargetSocksServer -> TargetHost
Client
使用任何 ConnectorInterface
实例来建立出站连接。为了通过另一个 SOCKS 服务器连接,您可以使用来自另一个 SOCKS 客户端的另一个 SOCKS 连接器,如下所示
// https via the proxy chain "MiddlemanSocksServer -> TargetSocksServer -> TargetHost" // please note how the client uses TargetSocksServer (not MiddlemanSocksServer!), // which in turn then uses MiddlemanSocksServer. // this creates a TCP/IP connection to MiddlemanSocksServer, which then connects // to TargetSocksServer, which then connects to the TargetHost $middle = new Client('127.0.0.1:1080', new Connector($loop)); $target = new Client('example.com:1080', $middle); $connector = new React\Socket\Connector($loop, array( 'tcp' => $target, 'dns' => false )); $connector->connect('tls://www.google.com:443')->then(function ($stream) { // … });
请参阅第三个示例。
可以通过取消其挂起的承诺来取消挂起的连接尝试。
代理链可以在服务器端和/或客户端发生。
-
如果您要求客户端通过多个代理进行链式连接,则每个代理服务器实际上对链式连接一无所知。这意味着这是一个仅客户端的属性。
-
如果您要求服务器通过另一个代理进行链式连接,则客户端实际上对链式连接一无所知。这意味着这是一个仅服务器的属性,并且不属于此类。例如,您可以在下面的
Server
类中找到它,或者当您使用Tor 网络时,有些类似。
连接超时
默认情况下,Client
不为建立远程连接实现任何超时。您的底层操作系统可能对挂起和/或空闲的 TCP/IP 连接施加限制,范围从几分钟到几小时不等。
许多用例需要更多对超时的控制,并且可能需要更小的值,通常只有几秒。
您可以使用 ReactPHP 的 Connector
或低级别的 TimeoutConnector
来装饰任何给定的 ConnectorInterface
实例。它提供了相同的 connect()
方法,但会自动拒绝底层连接尝试,如果它花费了太长时间。
$connector = new Connector($loop, array( 'tcp' => $client, 'dns' => false, 'timeout' => 3.0 )); $connector->connect('tcp://google.com:80')->then(function ($stream) { // connection succeeded within 3.0 seconds });
请参阅示例。
可以通过取消其挂起的承诺来取消挂起的连接尝试。
请注意,连接超时实际上完全由本 SOCKS 客户端实现之外来处理。
SOCKS over TLS
所有SOCKS 协议版本都支持基于 TCP/IP 的连接和更高层次的协议。这意味着您还可以使用安全 TLS 连接在 SOCKS 代理服务器之间传输敏感数据。这意味着窃听者或代理服务器都无法解密您的数据。
然而,客户端和代理之间的初始 SOCKS 通信通常是通过未加密的普通 TCP/IP 连接进行的。这意味着窃听者可能能够看到您连接到的位置,也可能能够看到您的SOCKS 认证细节。
作为替代,您可以在开始初始 SOCKS 通信之前与 SOCKS 代理建立安全 TLS 连接。这意味着窃听者将无法看到您想要连接到的目标地址或您的SOCKS 认证细节。
您可以使用 sockss://
URI 方案或使用显式的SOCKS 协议版本,如下所示
$client = new Client('sockss://127.0.0.1:1080', new Connector($loop)); $client = new Client('socks4s://127.0.0.1:1080', new Connector($loop));
请参阅示例 32。
类似地,您还可以将其与认证结合使用
$client = new Client('sockss://user:pass@127.0.0.1:1080', new Connector($loop));
请注意,对于大多数使用场景,应使用安全的TLS连接。SOCKS over TLS被认为是高级用法,在实际应用中很少使用。特别是,SOCKS服务器必须接受安全的TLS连接,有关更多详细信息,请参阅服务器SOCKS over TLS。此外,PHP不支持单个连接上的“双重加密”。这意味着在通过SOCKS over TLS打开的通信通道上启用安全TLS连接可能不受支持。
请注意,SOCKS协议不支持TLS的概念。上面的方法可以合理地工作,因为TLS仅用于客户端和代理服务器之间的连接,而SOCKS协议数据在其他方面是相同的。这表明这可能在多个TLS路径上对代理链的支持也有限。
Unix 域套接字
所有SOCKS协议版本都支持转发基于TCP/IP的连接和高级协议。在某些高级情况下,可能需要让您的SOCKS服务器监听Unix域套接字(UDS)路径而不是IP:端口组合。例如,这允许您依靠文件系统权限而不是必须依赖明确的认证。
您可以使用socks+unix://
URI方案,或者使用以下方式显式指定SOCKS协议版本。
$client = new Client('socks+unix:///tmp/proxy.sock', new Connector($loop)); $client = new Client('socks4+unix:///tmp/proxy.sock', new Connector($loop));
类似地,您还可以将其与认证结合使用
$client = new Client('socks+unix://user:pass@/tmp/proxy.sock', new Connector($loop));
请注意,Unix域套接字(UDS)被认为是高级用法,PHP对此的支持有限。特别是,启用安全TLS可能不受支持。
请注意,SOCKS协议不支持UDS路径的概念。上述方法可以合理地工作,因为UDS仅用于客户端和代理服务器之间的连接,而路径实际上不会通过协议传递。这表明这也不支持在多个UDS路径上代理链。
服务器
服务器负责接受来自SOCKS客户端的传入通信并将请求的连接转发到目标主机。它默认支持SOCKS5和SOCKS4(a)协议版本。它还与主EventLoop
和TCP/IP套接字服务器注册一切。
$loop = React\EventLoop\Factory::create(); $server = new Clue\React\Socks\Server($loop); // listen on localhost:$port $socket = new React\Socket\Server($port, $loop); $server->listen($socket); $loop->run();
此外,Server
构造函数接受可选参数,以显式配置要使用的连接器和需要认证。有关更多详细信息,请继续阅读...
服务器连接器
服务器使用ReactPHP的ConnectorInterface
实例为每个传入连接请求建立传出连接。
如果您需要自定义连接器设置(DNS解析、TLS参数、超时、代理服务器等),您可以显式传递一个自定义的ConnectorInterface
实例。
$connector = new React\Socket\Connector($loop, array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' ) )); $server = new Clue\React\Socks\Server($loop, $connector);
如果您想通过另一个SOCKS代理转发传出连接,也可以传递一个Client
实例作为连接器,有关更多详细信息,请参阅服务器代理链。
内部,服务器使用ReactPHP的常规connect()
方法,但也会传递原始客户端IP作为?source={remote}
参数。该source
参数包含完整的远程URI,包括协议和任何认证细节,例如socks://user:pass@1.2.3.4:5678
或socks4://1.2.3.4:5678
(对于旧版SOCKS4(a))。您可以使用此参数进行日志记录,或通过提供自定义的ConnectorInterface
实现来限制某些客户端的连接请求。
服务器认证
默认情况下,Server
不需要从客户端进行任何认证。您可以通过启用认证支持,使得客户端在转发任何连接之前需要传递有效的用户名和密码。
在Server
上设置认证强制要求每个进一步连接的客户端使用协议版本5(SOCKS5)。如果客户端尝试使用任何其他协议版本、未发送认证详情或者认证详情无法被验证,连接将被拒绝。
如果您只想接受静态认证详情,可以简单地将包含认证详情的额外关联数组传递给Server
,如下所示
$server = new Clue\React\Socks\Server($loop, null, array( 'tom' => 'password', 'admin' => 'root' ));
另请参阅示例#12。
如果您想要更多控制认证,可以传递一个返回布尔值的认证器函数,如下面的同步示例
$server = new Clue\React\Socks\Server($loop, null, function ($user, $pass, $remote) { // $remote is a full URI à la socks://user:pass@192.168.1.1:1234 // or sockss://user:pass@192.168.1.1:1234 for SOCKS over TLS // or may be null when remote is unknown (SOCKS over Unix Domain Sockets) // useful for logging or extracting parts, such as the remote IP $ip = parse_url($remote, PHP_URL_HOST); return ($user === 'root' && $pass === 'secret' && $ip === '127.0.0.1'); });
由于您的认证机制可能需要一些时间来实际检查提供的认证凭证(例如查询远程数据库或web服务),服务器也支持基于Promise的接口。虽然这最初可能看起来更复杂,但实际上它提供了一种非常强大的方式来处理大量并发连接,而不会阻塞任何连接。您可以从认证器函数中返回一个Promise
,该Promise将返回布尔值,如下面的异步示例
$server = new Clue\React\Socks\Server($loop, null, function ($user, $pass) use ($db) { // pseudo-code: query database for given authentication details return $db->query( 'SELECT 1 FROM users WHERE name = ? AND password = ?', array($username, $password) )->then(function (QueryResult $result) { // ensure we find exactly one match in the database return count($result->resultRows) === 1; }); });
服务器代理链
Server
负责创建与目标主机的连接。
Client -> SocksServer -> TargetHost
有时可能需要通过另一个SOCKS服务器建立出站连接。例如,如果您的目标SOCKS服务器需要认证,但您的客户端不支持发送认证信息(例如,像大多数网络浏览器),这可能会很有用。
Client -> MiddlemanSocksServer -> TargetSocksServer -> TargetHost
Server
使用任何ConnectorInterface
的实例来建立出站连接。为了通过另一个SOCKS服务器连接,您可以使用上面的Client
SOCKS连接器。您可以创建一个SOCKS Client
实例,如下所示
$loop = React\EventLoop\Factory::create(); // set next SOCKS server example.com:1080 as target $connector = new React\Socket\Connector($loop); $client = new Clue\React\Socks\Client('user:pass@example.com:1080', $connector); // start a new server which forwards all connections to the other SOCKS server $server = new Clue\React\Socks\Server($loop, $client); // listen on localhost:1080 $socket = new React\Socket\Server('127.0.0.1:1080', $loop); $server->listen($socket); $loop->run();
另请参阅示例#21。
代理链可以在服务器端和/或客户端发生。
-
如果您要求客户端通过多个代理链式连接,那么每个代理服务器实际上对链式连接一无所知。这意味着这是一个客户端特有的属性,而不是这个类的一部分。例如,您可以在上面的
Client
类中找到这个。 -
如果您要求服务器通过另一个代理链式连接,那么客户端实际上对链式连接一无所知。这意味着这是一个服务器特有的属性,可以像上面那样实现。
服务器SOCKS over TLS
SOCKS5和SOCKS4(a)协议版本都支持转发基于TCP/IP的连接和高级协议。这意味着您也可以使用安全TLS连接在SOCKS代理服务器之间传输敏感数据。这意味着任何监听者或代理服务器都无法解密您的数据。
然而,客户端和代理之间的初始SOCKS通信通常是通过未加密的纯TCP/IP连接。这意味着监听者可能能够看到客户端连接到的位置,也可能能够看到SOCKS认证详情的明文。
作为替代方案,您可以监听基于TLS的SOCKS连接,这样客户端在开始初始SOCKS通信之前必须先与您的SOCKS代理建立安全的TLS连接。这意味着任何窃听者都无法看到客户端想要连接的目的地址或其SOCKS认证详情。
您只需这样在tls://
URI方案上启动您的监听套接字
$loop = React\EventLoop\Factory::create(); $server = new Clue\React\Socks\Server($loop); // listen on tls://127.0.0.1:1080 with the given server certificate $socket = new React\Socket\Server('tls://127.0.0.1:1080', $loop, array( 'tls' => array( 'local_cert' => __DIR__ . '/localhost.pem', ) )); $server->listen($socket); $loop->run();
请参阅示例31。
请注意,对于大多数用例,应使用安全的TLS连接。SOCKS over TLS被视为高级用法,在实践中的应用非常罕见。
请注意,SOCKS协议不支持TLS的概念。上述方法可以合理地工作,因为TLS仅用于客户端和代理服务器之间的连接,而SOCKS协议数据在其他方面保持不变。这意味着这也不支持在多个TLS路径上代理链式连接。
服务器Unix域套接字
SOCKS5和SOCKS4(a)协议版本都支持转发基于TCP/IP的连接和高级协议。在某些高级情况下,让您的SOCKS服务器在Unix域套接字(UDS)路径上监听,而不是IP:端口组合可能很有用。例如,这允许您依靠文件系统权限,而不是必须依赖明确的认证。
您只需这样在unix://
URI方案上启动您的监听套接字
$loop = React\EventLoop\Factory::create(); $server = new Clue\React\Socks\Server($loop); // listen on /tmp/proxy.sock $socket = new React\Socket\Server('unix:///tmp/proxy.sock', $loop); $server->listen($socket); $loop->run();
请注意,Unix域套接字(UDS)被视为高级用法,而SOCKS协议不支持UDS路径的概念。上述方法可以合理地工作,因为UDS仅用于客户端和代理服务器之间的连接,并且路径实际上不会通过协议传递。这意味着这也不支持在多个UDS路径上代理链式连接。
服务器
使用 PHP SOCKS 服务器
- 如果您正在寻找面向最终用户的SOCKS服务器守护进程,您可能想使用LeProxy或clue/psocksd。
- 如果您正在寻找SOCKS服务器实现,请考虑使用上述
Server
类。
使用 SSH 作为 SOCKS 服务器
如果您已经设置了SSH服务器,您可以轻松将其用作SOCKS隧道端点。在您的客户端上,只需启动SSH客户端并使用-D <port>
选项启动本地SOCKS服务器(引用手册页:一个本地 "动态" 应用层端口转发
)。
如果您的本地系统上已经运行了SSH守护进程,您可以通过创建到本地系统的回环连接来启动本地SOCKS服务器
$ ssh -D 1080 localhost
或者,您可以通过一个运行SSH守护进程的远程主机启动本地SOCKS服务器隧道
$ ssh -D 1080 example.com
现在您可以直接这样使用这个SSH SOCKS服务器
$client = new Client('127.0.0.1:1080', $connector);
请注意,上述操作将允许本地系统上的所有用户无需认证即可通过您的SOCKS服务器进行连接,这可能是您需要的,也可能不是。作为替代方案,较新的OpenSSH客户端版本也支持Unix域套接字(UDS)路径,这样您就可以依靠Unix文件系统权限了
$ ssh -D/tmp/proxy.sock example.com
现在您可以直接这样使用这个SSH SOCKS服务器
$client = new Client('socks+unix:///tmp/proxy.sock', $connector);
作为手动设置的一种替代方案,您还可以考虑使用clue/reactphp-ssh-proxy,该工具会自动为您创建SSH隧道。它实现了相同的
ConnectorInterface
,因此支持任一代理协议应该相对简单。
使用 Tor(匿名网络)隧道 SOCKS 连接
Tor匿名网络客户端软件旨在加密您的流量,并通过多个节点的网络路由以隐藏其来源。它默认在TCP端口号9050上提供SOCKS5和SOCKS4(a)接口,这允许您通过匿名网络传输任何流量。
$client = new Client('127.0.0.1:9050', $connector);
在大多数常见场景中,您可能希望坚持使用默认的远程DNS解析,并且不希望您的客户端解析目标主机名,因为这会导致DNS信息泄露给任何观察您本地流量的人。此外,Tor通过.onion
伪顶级域名提供隐藏服务,这些服务需要Tor进行解析。
安装
建议通过Composer安装此库。对Composer不熟悉?
本项目遵循SemVer。这将安装最新支持版本
$ composer require clue/socks-react:^1.0
有关版本升级的详细信息,请参阅CHANGELOG。
本项目旨在在所有平台上运行,因此不要求任何PHP扩展,并支持从PHP 5.3到当前PHP 7+和HHVM的运行。强烈建议使用PHP 7+来运行本项目。
测试
要运行测试套件,您首先需要克隆此存储库,然后通过Composer安装所有依赖项
$ composer install
要运行测试套件,请转到项目根目录并运行
$ php vendor/bin/phpunit
测试套件包含一些依赖有效互联网连接的测试,您也可以这样运行
$ php vendor/bin/phpunit --exclude-group internet
许可证
本项目采用宽松的MIT许可证。
您知道我可以提供定制开发服务,并为发行版赞助和贡献发放发票吗?请联系我(@clue)获取详细信息。
更多信息
- 如果您想了解更多关于
ConnectorInterface
及其通常实现的信息,请参阅底层react/socket组件的文档。 - 如果您想了解更多关于处理数据流的信息,请参阅底层react/stream组件的文档。
- 除了SOCKS5 / SOCKS4(a)代理之外,您还可以考虑使用HTTP CONNECT代理。您可以使用clue/reactphp-http-proxy,它也提供了相同的
ConnectorInterface
实现,因此支持任一代理协议应该相对简单。 - 作为 SOCKS5 / SOCKS4(a) 代理的替代方案,您也可以考虑使用 SSH 代理(SSH 隧道)。您可能会想使用 clue/reactphp-ssh-proxy,它也提供了一个相同的
ConnectorInterface
实现,因此支持任一代理协议应该相当简单。 - 如果您处理的是公共代理,您可能需要与质量参差不齐且不可靠的代理一起工作。您可能会考虑使用 clue/reactphp-connection-manager-extra,它允许重试不可靠的代理,意味着连接超时、同时与多个连接器工作等功能。
- 如果您正在寻找面向最终用户的SOCKS服务器守护进程,您可能想使用LeProxy或clue/psocksd。