Skip to content

Commit

Permalink
Update SOCKS dependency to improve error reporting and cancellation
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Jul 19, 2019
1 parent a1e2b2f commit 7e8bcb9
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 31 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -16,7 +16,7 @@
"clue/commander": "^1.3",
"clue/connection-manager-extra": "^1.1",
"clue/http-proxy-react": "^1.4",
"clue/socks-react": "^0.8.7",
"clue/socks-react": "^1.0",
"react/http": "^0.8.3",
"react/http-client": "^0.5.9",
"react/socket": "^1.1"
Expand Down
26 changes: 13 additions & 13 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion src/ConnectorFactory.php
Expand Up @@ -59,7 +59,12 @@ public static function coerceProxyUri($uri)
throw new \InvalidArgumentException('Upstream proxy "' . $uri . '" can not be parsed as a valid URI');
}

if (!in_array($parts['scheme'], array('http', 'socks', 'socks5', 'socks4', 'socks4a'))) {
// deprecated, for BC only: map explicit SOCKS4a to SOCKS4, should be removed in the future
if ($parts['scheme'] === 'socks4a') {
$parts['scheme'] = 'socks4';
}

if (!in_array($parts['scheme'], array('http', 'socks', 'socks5', 'socks4'))) {
throw new \InvalidArgumentException('Upstream proxy scheme "' . $parts['scheme'] . '://" not supported');
}

Expand All @@ -82,6 +87,9 @@ public static function coerceProxyUri($uri)

$parts += array('user' => '', 'pass' => '');
$parts['host'] = $parts['user'] . ':' . $parts['pass'] . '@' . $parts['host'];
} elseif ($parts['scheme'] === 'socks') {
// deprecated, for BC only: map unspecified SOCKS to SOCKS4(a), should be SOCKS5 in the future
$parts['scheme'] = 'socks4';
}

return $parts['scheme'] . '://' . $parts['host'] . ':' . $parts['port'];
Expand Down
33 changes: 19 additions & 14 deletions src/LeProxyServer.php
Expand Up @@ -60,32 +60,37 @@ public function listen($listen, $allowUnprotected)
$socket = new Socket($parts['host'] . ':' . $parts['port'], $this->loop);
}

// start new proxy server which uses the given connector for forwarding/chaining
$unification = new ProtocolDetector($socket);
$http = new HttpProxyServer($this->loop, $unification->http, $this->connector);
$socks = new SocksServer(
$this->loop,
$unification->socks,
new SocksErrorConnector(
$this->connector,
!isset($parts['user']) && !isset($parts['pass']) && !$allowUnprotected
)
);

// require authentication if listening URI contains username/password
$auth = null;
if (isset($parts['user']) || isset($parts['pass'])) {
$auth = array(
rawurldecode($parts['user']) => isset($parts['pass']) ? rawurldecode($parts['pass']) : ''
);
}

// start new proxy server which uses the given connector for forwarding/chaining
$unification = new ProtocolDetector($socket);

// HTTP server with authentication required or protected mode by default
$http = new HttpProxyServer($this->loop, $unification->http, $this->connector);
if ($auth !== null) {
$http->setAuthArray($auth);
$socks->setAuthArray($auth);
} elseif (!$allowUnprotected) {
// no authentication required, so only allow local HTTP requests (protected mode)
// SOCKS works slightly differently and simply rejects every non-local connection attempt, see SocksErrorConnector
$http->allowUnprotected = false;
}

// SOCKS server works slightly differently and simply rejects every non-local connection attempt via SocksErrorConnector
$socks = new SocksServer(
$this->loop,
new SocksErrorConnector(
$this->connector,
!isset($parts['user']) && !isset($parts['pass']) && !$allowUnprotected
),
$auth
);
$socks->listen($unification->socks);

return $socket;
}
}
4 changes: 2 additions & 2 deletions tests/ConnectorFactoryTest.php
Expand Up @@ -9,10 +9,10 @@ public function testCoerceProxyUri()
$uris = array(
'host' => 'http://host:8080',
'host:1234' => 'http://host:1234',
'socks://host' => 'socks://host:8080',
'socks://host' => 'socks4://host:8080',
'socks://user:pass@host' => 'socks5://user:pass@host:8080',
'user@host' => 'http://user:@host:8080',
'socks4a://10.20.30.40:5060' => 'socks4a://10.20.30.40:5060',
'socks4a://10.20.30.40:5060' => 'socks4://10.20.30.40:5060',

'./proxy.sock' => 'http+unix://./proxy.sock',
'/tmp/proxy.sock' => 'http+unix:///tmp/proxy.sock',
Expand Down

0 comments on commit 7e8bcb9

Please sign in to comment.