infostars/socks-react

异步 SOCKS 代理连接客户端和服务器实现,通过 SOCKS5 或 SOCKS4(a) 代理服务器隧道任何 TCP/IP 协议,基于 ReactPHP 构建。

v1.0.0 2018-11-20 11:16 UTC

This package is auto-updated.

Last update: 2024-09-20 20:21:42 UTC


README

异步 SOCKS 代理连接客户端和服务器实现,通过 SOCKS5 或 SOCKS4(a) 代理服务器隧道任何 TCP/IP 协议,基于 ReactPHP 构建。

SOCKS 代理协议族(SOCKS5、SOCKS4 和 SOCKS4a)通常用于通过中介("代理")隧道 HTTP(S) 流量,以隐藏原始地址(匿名性)或绕过地址封锁(地理封锁)。虽然许多(公共)SOCKS 代理服务器通常仅限于 HTTP(S) 端口 80443,但技术上可以使用它来隧道任何 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:5678socks4://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服务器守护进程,您可能想使用LeProxyclue/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服务器守护进程,您可能想使用LeProxyclue/psocksd