Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
IO::Socket::Socks::WraUser(Contributed Perl DocumIO::Socket::Socks::Wrapper(3)

NAME
       IO::Socket::Socks::Wrapper - Add	SOCKS support for any perl object /
       package / program

SYNOPSIS
	       use IO::Socket::Socks::Wrapper {
		       ProxyAddr => 'localhost',
		       ProxyPort => 1080
	       };

	       connect($socket,	$name);	# will make connection through a socks proxy

DESCRIPTION
       "IO::Socket::Socks::Wrapper" allows to wrap up the network connections
       into socks proxy. It can	wrap up	any network connection,	connection
       from separate packages or even connection from separate object. It can
       also play well with your	preferred event	loop and do not	block it.

METHODS
   import( CFG )
       import()	is invoked when	"IO::Socket::Socks::Wrapper" loaded by `use'
       command.	Later it can be	invoked	manually to change proxy. Global
       overriding will not work	in the packages	that was loaded	before calling
       IO::Socket::Socks::Wrapper->import(). So, for this purposes `use
       IO::Socket::Socks::Wrapper' with	$hashref argument should be before any
       other `use' statements.

       CFG syntax

       Global wrapping

       Only $hashref should be specified. $hashref is a	reference to a hash
       with key/value pairs same as IO::Socket::Socks constructor options, but
       without (Connect|Bind|Udp)Addr and (Connect|Bind|Udp)Port. To disable
       wrapping	$hashref could be scalar with false value.

	       # we can	wrap all connections
	       use IO::Socket::Socks::Wrapper {	# should be before any other `use'
		       ProxyAddr => 'localhost',
		       ProxyPort => 1080,
		       SocksDebug => 1,
		       Timeout => 10
	       };

	       # except	Net::FTP
	       IO::Socket::Socks::Wrapper->import(Net::FTP:: =>	0); # direct network access

       Wrapping	package	that inherits from IO::Socket

       Examples	are: Net::FTP, Net::POP3, Net::HTTP

	       'pkg' =>	$hashref

       Where pkg is a package name that	is responsible for connections.	For
       example if you want to wrap LWP http connections, then module name
       should be Net::HTTP, for	https connections it should be Net::HTTPS or
       even LWP::Protocol::http::Socket	and LWP::Protocol::https::Socket
       respectively (see examples below). You really need to look at the
       source code of the package which	you want to wrap to determine the name
       for wrapping. Or	use global wrapping which will wrap all	that can. Use
       `SocksDebug' to verify that wrapping works. For $hashref	description
       see above.

	       # we can	wrap connection	for separate packages
	       # if package inherited from IO::Socket
	       # let's wrap Net::FTP and Net::HTTP

	       use IO::Socket::Socks::Wrapper (
		       Net::FTP	=> {
			       ProxyAddr => '10.0.0.1',
			       ProxyPort => 1080,
			       SocksDebug => 1,
			       Timeout => 15
		       },
		       Net::FTP::dataconn => {
			       ProxyAddr => '10.0.0.1',
			       ProxyPort => 1080,
			       SocksDebug => 1,
			       Timeout => 15
		       },
		       Net::HTTP => {
			       ProxyAddr => '10.0.0.2',
			       ProxyPort => 1080,
			       SocksVersion => 4,
			       SocksDebug => 1,
			       Timeout => 15
		       }
	       );
	       use Net::FTP;
	       use Net::POP3;
	       use LWP;	# it uses Net::HTTP for	http connections
	       use strict;

	       my $ftp = Net::FTP->new();	# via socks5://10.0.0.1:1080
	       my $lwp = LWP::UserAgent->new();	# via socks4://10.0.0.2:1080
	       my $pop = Net::POP3->new();	# direct network access

	       ...

	       # change	proxy for Net::HTTP
	       IO::Socket::Socks::Wrapper->import(Net::HTTP:: => {ProxyAddr => '10.0.0.3', ProxyPort =>	1080});

       And if package has no separate module you should	load module with this
       package manually

	       # we can	wrap connection	for packages that hasn't separate modules
	       # let's make more direct	LWP::UserAgent wrapping

	       # we need to associate LWP::Protocol::http::Socket and LWP::Protocol::https::Socket packages
	       # with socks proxy
	       # this packages do not have separate modules
	       # LWP::Protocol::http and LWP::Protocol::https modules includes this packages respectively
	       # IO::Socket::Socks::Wrapper should has access to @ISA of each package which want to be wrapped
	       # when package == module	it can load packages automatically and do its magic
	       # but in	the case like this loading will	fail
	       # so, we	should load this modules manually

	       use LWP::Protocol::http;
	       use LWP::Protocol::https;
	       use IO::Socket::Socks::Wrapper (
		       LWP::Protocol::http::Socket => {
			       ProxyAddr => 'localhost',
			       ProxyPort => 1080,
			       SocksDebug => 1,
			       Timeout => 15
		       },
		       LWP::Protocol::https::Socket => {
			       ProxyAddr => 'localhost',
			       ProxyPort => 1080,
			       SocksDebug => 1,
			       Timeout => 15
		       }
	       );
	       use LWP;

	       # then use lwp as usual
	       my $ua =	LWP::UserAgent->new();

	       # in this case Net::HTTP	and Net::HTTPS objects will use	direct network access
	       # but LWP::UserAgent objects will use socks proxy

       Wrapping	package	that uses built-in connect()

       Examples	are: Net::Telnet

	       'pkg' =>	$hashref

       Syntax is the same as for wrapping package that inherits	from
       IO::Socket except for one point.	 Replacing of built-in connect()
       should be performed before package being	actually loaded. For this
       purposes	you should specify "_norequire"	key with true value for
       $hashref	CFG. This will prevent package loading,	so you need to require
       this package manually after.

	       # we can	wrap packages that uses	bult-in	connect()
	       # Net::Telnet for example

	       use IO::Socket::Socks::Wrapper (
		       Net::Telnet => {
			       _norequire => 1,	# should tell do not load it
						# because buil-in connect should be overrided
						# before package being compiled
			       ProxyAddr => 'localhost',
			       ProxyPort => 1080,
			       SocksDebug => 1
		       }
	       );
	       use Net::Telnet;	# and load it after manually

       Wrapping	package	that uses IO::Socket object or class object inherited
       from IO::Socket as internal socket handle

       Examples	are: HTTP::Tiny	(HTTP::Tiny::Handle::connect)

	       'pkg::sub()' => $hashref

       Where sub is a name of subroutine contains IO::Socket object
       creation/connection.  Parentheses required. For pkg and $hashref
       description see above.

	       # we can	wrap packages that is not inherited from IO::Socket
	       # but uses IO::Socket object as internal	socket handle

	       use HTTP::Tiny; # HTTP::Tiny::Handle package is in HTTP::Tiny module
	       use IO::Socket::Socks::Wrapper (
		       # HTTP::Tiny::Handle::connect sub invokes IO::Socket::INET->new
		       # see HTTP::Tiny	sourse code
		       'HTTP::Tiny::Handle::connect()' => { # parentheses required
			       ProxyAddr => 'localhost',
			       ProxyPort => 1080,
			       SocksVersion => 4,
			       Timeout => 15
		       }
	       );

	       # via socks
	       my $page	= HTTP::Tiny->new->get('http://www.google.com/')->{content};

	       # disable wrapping for HTTP::Tiny
	       IO::Socket::Socks::Wrapper->import('HTTP::Tiny::Handle::connect()' => 0);
	       # and get page without socks
	       $page = HTTP::Tiny->new->get('http://www.google.com/')->{content};

       Wrapping	objects

       To wrap object connection you should use	wrap_connection($obj,
       $hashref) subroutine, which may be imported manually. $obj may be any
       object that uses	IO::Socket for tcp connections creation. This
       subroutine will return new object which you should use. Returned	object
       is object of IO::Socket::Socks::Wrapped class and it has	all methods
       that original object has. You can also use original object as before,
       but it will create direct connections without proxy. For	more details
       see IO::Socket::Socks::Wrapped documentation. For $hashref description
       see above.

	       # we can	wrap connection	for separate object
	       # if package internally uses IO::Socket for connections (for most this is true)

	       use IO::Socket::Socks::Wrapper 'wrap_connection';
	       use Net::SMTP;

	       my $smtp	= wrap_connection(Net::SMTP->new('mailhost'), {
		       ProxyAddr => 'localhost',
		       ProxyPort => 1080,
		       SocksDebug => 1
	       });

	       # $smtp now uses	socks5 proxy for connections
	       $smtp->to('postmaster');
	       $smtp->data();
	       $smtp->datasend("To: postmaster\n");
	       $smtp->datasend("\n");
	       $smtp->datasend("A simple test message\n");
	       $smtp->dataend();

       Integration with	event loops

       Note: integration with "kqueue" based event loops known to be broken

       When you	are using some event loop like AnyEvent	or POE it is important
       to prevent any long blocking operations.	 By default
       IO::Socket::Socks::Wrapper blocks your program while it making
       connection and SOCKS handshake with a proxy.  If	you are	using fast
       proxy on	localhost this is not big problem, because connection to proxy
       and making SOCKS	handshake will not get some significant	time. But
       usually SOCKS proxy located somewhere in	the other part of the Earth
       and is not so fast. So your event loop will suffer from this delays and
       even may	misbehaves.

       Since version 0.11 IO::Socket::Socks::Wrapper introduces	several	hooks,
       so you can integrate it with any	event loop and make event loop happy.
       In the CFG you should specify additional	parameter with name
       "_io_handler" and value is a reference to subroutine, which should
       return reference	to a hash. Possible keys in this hash are:

       init_io_watcher => sub {	my ($handle, $r_cb, $w_cb) = @_	}
	   Value should	be a reference to subroutine in	which you'll make some
	   IO watcher initialization for your event loop if needed.  When it
	   will	be time	to call	this sub IO::Socket::Socks::Wrapper will pass
	   to it 3 arguments: $handle -	this is	IO::Socket object, $r_cb -
	   read	callback that should be	called when $handle will become	ready
	   for reading,	$w_cb -	write callback that should be called when
	   $handle will	become ready for writing.

	   This	parameter is optional.

	   Let's start example to make it clear. For our example we will use
	   some	fictional IO loop called "Some::IOLoop", which has same
	   methods and behavior	as Mojo::IOLoop

	   Beginning looks like

		   use IO::Socket::Socks::Wrapper {
			   ProxyAddr   => $s_host,
			   ProxyPort   => $s_port,
			   _io_handler => sub {
			   # ...

	   Here	in the sub you can define some variable	which you will use in
	   the closures	below

				   # ...
				   my $reactor = Some::IOLoop->singleton->reactor;

				   return {
					   init_io_watcher => sub {
						   my ($hdl, $r_cb, $w_cb) = @_;

						   # initialize	IO watcher
						   $reactor->io($hdl =>	sub {
							   my $writable	= pop;

							   if ($writable) {
								   $w_cb->();
							   }
							   else	{
								   $r_cb->();
							   }
						   });
					   },
					   # ...

       set_read_watcher	=> sub { my ($handle, $r_cb) = @_ }
	   Value should	be a reference to subroutine in	which you'll start
	   read	watcher	for passed $handle. When $handle will be ready for
	   read	$r_cb should be	called.

	   This	parameter is not optional. Let's continue our example.

	   Watcher already created above and all we need to do is to start
	   watching for	reading	and stop watching for writing

					   # ...
					   set_read_watcher => sub {
						   my ($hdl, $cb) = @_;
						   $reactor->watch($hdl, 1, 0);
					   },
					   # ...

       unset_read_watcher => sub { my ($handle)	= @_ }
	   Value should	be  a reference	to subroutine in which you'll stop
	   read	watcher	for passed $handle.

	   This	parameter is not optional

					   # ...
					   unset_read_watcher => sub {
						   my $hdl = shift;
						   $reactor->watch($hdl, 0, 0);
					   },
					   # ...

       set_write_watcher => sub	{ my ($handle, $w_cb) =	@_ }
	   Value should	be a reference to subroutine in	which you'll start
	   write watcher for passed $handle. When handle will be ready for
	   write $w_cb should be called.

	   This	parameter is not optional

					   # ...
					   set_write_watcher =>	sub {
						   my ($hdl, $cb) = @_;
						   $reactor->watch($hdl, 0, 1);
					   },
					   # ...

       unset_write_watcher => sub { my ($handle) = @_ }
	   Value should	be a reference to subroutine in	which you'll stop
	   write watcher for passed $handle.

	   This	parameter is not optional

					   # ...
					   unset_write_watcher => sub {
						   my $hdl = shift;
						   $reactor->watch($hdl, 0, 0);
					   },
					   # ...

       destroy_io_watcher => sub { my ($handle)	= @_  }
	   Value should	be a reference to subroutine in	which you'll destroy
	   watcher for passed $handle if needed.

	   This	parameter is optional

					   # ...
					   destroy_io_watcher => sub {
						   my $hdl = shift;
						   $reactor->remove($hdl);
					   }
					   # ...

	   And we are done

				   # ...
				   }
			   }
		   };

       And here	is how it may be implemented with AnyEvent

	       use IO::Socket::Socks::Wrapper {
		       ProxyAddr   => $s_host,
		       ProxyPort   => $s_port,
		       _io_handler => sub {
			       # watcher variable for closures
			       my $w;

			       return {
				       # we don't need init_io_watcher
				       # and destroy_io_watcher	for AnyEvent

				       set_read_watcher	=> sub {
					       # because all initialization done here
					       my ($hdl, $cb) =	@_;

					       $w = AnyEvent->io(
						       poll => 'r',
						       fh   => $hdl,
						       cb   => $cb
					       )
				       },
				       unset_read_watcher => sub {
					       # and destroying	here
					       undef $w;
				       },
				       set_write_watcher => sub	{
					       # and here
					       my ($hdl, $cb) =	@_;

					       $w = AnyEvent->io(
						       poll => 'w',
						       fh   => $hdl,
						       cb   => $cb
					       )
				       },
				       unset_write_watcher => sub {
					       # and here
					       undef $w;
				       }
			       }
		       }
	       };

NOTICE
       Default timeout for wrapped connect is timeout value for	socket on
       which we	trying to connect. This	timeout	value checked only for sockets
       inherited from IO::Socket. For example "LWP::UserAgent->new(timeout =>
       5)" creates socket with timeout 5 sec, so no need to additionally
       specify timeout for "IO::Socket::Socks::Wrapper". If socket timeout not
       specified or socket not inherited from IO::Socket then default timeout
       will be 180 sec.	You can	specify	your own value using "Timeout" option.
       Set it to zero if you don't want	to limit connection attempt time.

BUGS
       Wrapping	doesn't	work with XS based modules, where connection done
       inside C	part. WWW::Curl	for example.

       Since "IO::Socket::IP" version 0.08 till	version	0.35 it	used
       "CORE::connect" internally, which can't be wrapped by global wrapping.
       And many	modules	nowadays uses IO::Socket::IP as	socket class. So if
       you have	problems with global wrapping make sure	you have
       "IO::Socket::IP"	0.35+

SEE ALSO
       IO::Socket::Socks, IO::Socket::Socks::Wrapped

COPYRIGHT
       Oleg G <oleg@cpan.org>.

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

perl v5.32.0			  2017-02-16	 IO::Socket::Socks::Wrapper(3)

NAME | SYNOPSIS | DESCRIPTION | METHODS | NOTICE | BUGS | SEE ALSO | COPYRIGHT

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=IO::Socket::Socks::Wrapper&sektion=3&manpath=FreeBSD+12.2-RELEASE+and+Ports>

home | help