Skip to content

Instantly share code, notes, and snippets.

@olegwtf
Last active December 29, 2015 22:09
Show Gist options
  • Save olegwtf/7734836 to your computer and use it in GitHub Desktop.
Save olegwtf/7734836 to your computer and use it in GitHub Desktop.
Coro based socks server through another socks server
use strict;
use Coro::PatchSet 0.04;
BEGIN {
package IO::Select;
use Coro::Select;
use IO::Select;
}
use IO::Socket::Socks qw(:constants :DEFAULT);
use Coro;
use Coro::Socket;
unshift @IO::Socket::Socks::ISA, 'Coro::Socket';
my $server = IO::Socket::Socks->new(SocksVersion => 5, ProxyAddr => 'localhost', Listen => 10)
or die $SOCKS_ERROR;
warn "Server started at ", $server->sockhost, ":", $server->sockport;
$server->blocking(0);
my $server_selector = IO::Select->new($server);
while (1) {
$server_selector->can_read();
my $client = $server->accept()
or next;
async_pool {
$client->ready()
or return;
my ($cmd, $host, $port) = @{$client->command};
if ($cmd == CMD_CONNECT) {
my $sock = IO::Socket::Socks->new(
ProxyAddr => 'x.x.x.x',
ProxyPort => 1080,
AuthType => 'userpass',
Username => 'xxxx',
Password => 'xxxx',
Timeout => 10,
ConnectAddr => $host,
ConnectPort => $port
);
if ($sock) {
$client->command_reply(REPLY_SUCCESS, $sock->sockhost, $sock->sockport);
my $selector = IO::Select->new($client, $sock);
my $buf;
SELECT:
while (1) {
my @ready = $selector->can_read();
for my $s (@ready) {
last SELECT unless $s->sysread($buf, 1024);
if ($s == $client) {
$sock->syswrite($buf);
}
else {
$client->syswrite($buf);
}
}
}
$sock->close();
}
else {
$client->command_reply(REPLY_HOST_UNREACHABLE, $host, $port);
}
}
else {
$client->command_reply(REPLY_CMD_NOT_SUPPORTED, $host, $port);
}
$client->close();
};
}
$server->close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment