Okay, while I may not be able to give you a complete solution with tested code, I should be able to help you out, having worked on a similar project previously.
The CONNECT method which you are receiving from HTTP clients is documented in RFC2616, as the means by which SSL connections are tunneled through HTTP connections. This method is sent by a HTTP client to a proxy server, followed by the destination host and destination port number - For example:
CONNECT ssl.webserver.com:443 HTTP/1.0
At this point, the HTTP proxy should initiate a connection to the designated port on the destination host and, if successful, return a 200 HTTP success code. The secure communication can then take place over the established connection.
With regard to making all this happen in your code, there is a patch available for the HTTP::Daemon module within the IO::Socket::SSL module which changes the inheritance of HTTP::Daemon to make use of IO::Socket::SSL in place of IO::Socket. Also too, if you have no luck with this, there are a couple of other patches for HTTP::Daemon which I can seen that are designed to achieve your goal and can also post these if required.
From IO-Socket-SSL-0.81\diffs\libwww-perl\HTTP_Daemon.pm.diff ...
*** /usr/local/perl5.005_03/lib/site_perl/5.005/HTTP/Daemon.pm.orig
+ Wed Jun 9 19:41:53 1999
--- /usr/local/perl5.005_03/lib/site_perl/5.005/HTTP/Daemon.pm Wed
+Jun 9 19:42:43 1999
***************
*** 63,69 ****
$VERSION = sprintf("%d.%02d", q$Revision: 1.21 $ =~ /(\d+)\.(\d+)/);
use IO::Socket ();
! @ISA=qw(IO::Socket::INET);
$PROTO = "HTTP/1.1";
--- 63,71 ----
$VERSION = sprintf("%d.%02d", q$Revision: 1.21 $ =~ /(\d+)\.(\d+)/);
use IO::Socket ();
! use IO::Socket::SSL;
! #@ISA=qw(IO::Socket::INET);
! @ISA=qw(IO::Socket::SSL);
$PROTO = "HTTP/1.1";
***************
*** 156,162 ****
use vars qw(@ISA $DEBUG);
use IO::Socket ();
! @ISA=qw(IO::Socket::INET);
*DEBUG = \$HTTP::Daemon::DEBUG;
use HTTP::Request ();
--- 158,165 ----
use vars qw(@ISA $DEBUG);
use IO::Socket ();
! #@ISA=qw(IO::Socket::INET);
! @ISA=qw(IO::Socket::SSL);
*DEBUG = \$HTTP::Daemon::DEBUG;
use HTTP::Request ();
Also see the demo file from the IO::Socket::SSL distribution, IO-Socket-SSL-0.81\demo\daemon.pl, which makes use of HTTP::Daemon in this fashion.
Good luck!
| [reply] [d/l] [select] |
Hello.
I've tried your hints by doing the changes of Daemon.pm and use my script but not with desired success.
Has anyone perhaps sample-code for proxying client-requests with CONNECT-method to establish ssl and what additional changes have to do?
I'll be very glad, if someone can post it here.
Best regards,
Andreas
my $UA = LWP::UserAgent->new;
$UA->agent("Mozilla/4.0");
$UA->protocols_allowed(['http','https']);
my $SRV = HTTP::Daemon->new(LocalPort => 3128);
while (my $conn = $SRV->accept) {
while (my $request = $conn->get_request) {
my $resp = $UA->simple_request($request);
$conn->send_response($resp);
}
$conn->close;
}
Debugoutput in request to local webserver and https://www.nodeworks.com looks like:
LWP::UserAgent::send_request: GET http://127.0.0.1/
LWP::UserAgent::_need_proxy: Not proxied
LWP::UserAgent::send_request: http URLs are among LWP::UserAgent=HASH(
+0x1fe594)'s allowed protocols (http https)
LWP::Protocol::http::request: ()
LWP::Protocol::collect: read 639 bytes
LWP::Protocol::collect: read 817 bytes
LWP::UserAgent::send_request: GET http://127.0.0.1/apache_pb.gif
LWP::UserAgent::_need_proxy: Not proxied
LWP::UserAgent::send_request: http URLs are among LWP::UserAgent=HASH(
+0x1fe594)'s allowed protocols (http https)
LWP::Protocol::http::request: ()
LWP::UserAgent::send_request: CONNECT http://www.nodeworks.com:443
LWP::UserAgent::_need_proxy: Not proxied
LWP::UserAgent::send_request: http URLs are among LWP::UserAgent=HASH(
+0x1fe594)'s allowed protocols (http https)
LWP::Protocol::http::request: ()
LWP::UserAgent::send_request: CONNECT http://www.nodeworks.com:443
LWP::UserAgent::_need_proxy: Not proxied
LWP::UserAgent::send_request: http URLs are among LWP::UserAgent=HASH(
+0x1fe594)'s allowed protocols (http https)
LWP::Protocol::http::request: ()
| [reply] [d/l] [select] |
According to the manual page for HTTP::Daemon it uses a IO::Socket::INET object that gets blessed into the daemon class. I looked at the code, and aside from force-setting Listen and Proto arguments before handing off to the parent class' constructor, this is the case.
According to the manual page for IO::Socket::SSL, it too is an almost straight sub-class of IO::Socket::INET. Thus, it should in theory be possible to create an object of the IO::Socket::SSL class, bless it into HTTP::Daemon manually, and use it as an ordinary daemon object. I say in theory because the SSL class manpage warns that it doesn't have the full set of methods provided for just yet, so if the HTTP::Daemon class happens to try to use one of the few that aren't available, chaos may well ensue. But it is certainly worth a try.
I myself would be interested to hear about your results, as I've been meaning to try my RPC::XML::Server class out with SSL underneath.
--rjray
| [reply] |
Well I made some progress based on these suggestions. What I did so far is this:
- Copied HTTP::Daemon and modified it as rob_au suggested to make an SSL version;
- Used that base to create an SSL proxy in addition to the existing HTTP proxy I already had. This was done by subclassing the proxy class I already had and overriding the creation of the daemon with the SSL version;
- Created a server certificate. This is where most of the time went. Creation of server certificates was a bit new to me and not really clearly documented in the OpenSSL docs.
At this point I had two proxy server classes: one for HTTP and one for SSL. I built two stub servers using those and fired them up. The results so far are that I can connect to the SSL proxy fine and it's able to see the HTTP traffic going back and forth if I send it the requests explicitly. But I can't get the server to be used as a true proxy by setting it in the browser. When I do that, OpenSSL complains when it sees the clear text CONNECT request, spitting out this proxy error with DEBUG on:
error message: 'SSL_accept: 'error:1407609B:SSL routines:SSL23_GET_CLI
+ENT_HELLO:https proxy request
So it looks like OpenSSL wants some special set up for proxies I'm not seeing just yet ... either that or it explicitly prohibits them. | [reply] [d/l] |
++ rob_au and rjray.
I'd like to add that if you don't mind using additional software then you can instantly turn any non-SSL service into SSL-enabled using stunnel. It is not a Perl solution but it is probably the simpliest.
--
Ilya Martynov
(http://martynov.org/)
| [reply] |