line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/env perl |
2
|
1
|
|
|
1
|
|
1514
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
48
|
|
3
|
1
|
|
|
1
|
|
9
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
4
|
1
|
|
|
1
|
|
1751
|
use HTTP::Proxy; |
|
1
|
|
|
|
|
135693
|
|
|
1
|
|
|
|
|
49
|
|
5
|
1
|
|
|
1
|
|
954
|
use Config::Tiny; |
|
1
|
|
|
|
|
1016
|
|
|
1
|
|
|
|
|
28
|
|
6
|
1
|
|
|
1
|
|
7
|
use HTTP::Proxy::Selective; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
7
|
1
|
|
|
1
|
|
6
|
use LWP::UserAgent; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
21
|
|
8
|
1
|
|
|
1
|
|
1576
|
use IO::Socket::SSL; |
|
1
|
|
|
|
|
88538
|
|
|
1
|
|
|
|
|
11
|
|
9
|
1
|
|
|
1
|
|
248
|
use IO::Socket::INET; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
16
|
|
10
|
1
|
|
|
1
|
|
828
|
use Net::SSLeay; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
37
|
|
11
|
1
|
|
|
1
|
|
8
|
use File::Temp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
458
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# For PAR |
14
|
|
|
|
|
|
|
my $sep = '/'; |
15
|
|
|
|
|
|
|
if ($^O =~ /WIN32/i) { |
16
|
|
|
|
|
|
|
$sep = "\\"; |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
require join($sep, qw/HTTP Proxy Engine NoFork.pm/); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Monkeypatch HTTP::Proxy to handle CONNECT as I want to. |
21
|
|
|
|
|
|
|
my ($key, $cert); |
22
|
|
|
|
|
|
|
{ |
23
|
|
|
|
|
|
|
my $key_temp = File::Temp->new( UNLINK => 0 ); |
24
|
|
|
|
|
|
|
print $key_temp q{-----BEGIN RSA PRIVATE KEY----- |
25
|
|
|
|
|
|
|
MIIEowIBAAKCAQEAshDKYNsCd+ETRUITIg1U3Tg4uy/vXJkN3ZZS14LSbcFpnwzi |
26
|
|
|
|
|
|
|
nMxFD4A/g/dSphHWxl/yZegDVz3ZWIV0En62YC7PfYwJWWd/4YLvDenQAEWz7cNT |
27
|
|
|
|
|
|
|
kBzXqQwqirjDqEKXDyQQZ4jFLR3EwYafjrD99h71JEjuOa+ZZ0rgLu2CPhH5MxEV |
28
|
|
|
|
|
|
|
WjSz0tSFU77bZNZKdYFdeKtZv0Ez4JGyTlVu8dwfsnfMpoyVL/c4xCXsJ+kNcnLA |
29
|
|
|
|
|
|
|
p4RGjYrUTmh/XrYK07QuPjUhPPXylTYKrzYCchjMRZjAmz5EvXSbXl6CTn0JOUEt |
30
|
|
|
|
|
|
|
YVvkJGNdd14jKez5ioDf1+gnX7nh20uog6ks9QIDAQABAoIBACBNfXk+od7/fNB2 |
31
|
|
|
|
|
|
|
oSPvSTLsjRYgJwskVOia6aJhAC2bBb8txjptsCWUvXECQAMSf2TzaPTltx1vgetW |
32
|
|
|
|
|
|
|
Im1sgUdHlqqO6e9HIGLXruhWPz6dZnu+kH03TkRDicAqrovqsJ61iyhNHoAFw3jc |
33
|
|
|
|
|
|
|
JDvtjdTFXvFbLaRXX7vmUG8S9SqvKIMwDIlURJlW71RwsbrkVskc3Ioq7VVWbc5Z |
34
|
|
|
|
|
|
|
cUwGLZv7WJidKTmsoFXClT5sVCj+GMvIHM2Ib8rwZsv9vdzY1oPNt3CIIWaoD3ea |
35
|
|
|
|
|
|
|
PADlqK80tx43vHdZhb50QZk41Rs6fcecaL0gU9wMMxQAzvEISLswgS3bPAiU0bkT |
36
|
|
|
|
|
|
|
WggocUECgYEA3VCKGJlEn598ELqicp1NLiel+u0EVIdPUbkDJQfLijyN/UI5Kz5J |
37
|
|
|
|
|
|
|
02lV5SLZ2F7Cnj9X+prMy3G/TcLMZz3gemhrrdBEUt+RbeBWdDP5pGsTOPmb+Cq6 |
38
|
|
|
|
|
|
|
ocDAPGQkIVsK5nmP/4z5Y3ldpJPUhbV6aOhVA4o8d4dz0ebLn44N3+UCgYEAzfkJ |
39
|
|
|
|
|
|
|
yB681UT9ne6zwfRX32aE8Hy4aGnBMgB4UP7508e87anDYcK+WnRgtSEPCqYnfngC |
40
|
|
|
|
|
|
|
tZA7bNMN1HEG65CYKssZD3FqqPepw6c/7siLdxgcJ+/q5XEjjn0aWQu0Aj/qnCWZ |
41
|
|
|
|
|
|
|
9Z5Fq78cZKu6TR7Z1wja02cXdZ/4JrIXnx27p9ECgYAPMV85jxQB7T3kHBvYyGmq |
42
|
|
|
|
|
|
|
+HfRgQHiF6PfVVcc7KsRY1TQBQLNsCn7RGjsIPdZfi/YEzsj7gqPEND0MqI7mCjX |
43
|
|
|
|
|
|
|
3mE9/mUiV0yxgUwOEB9cJSmdqK0HXU+QmR3ZR3qfe5OE/OVgwrnAFW3TRX66axnr |
44
|
|
|
|
|
|
|
J7/mTVAXWIof57skyeiz7QKBgQCJEA71T5cDKJzIat7N02ZiMBuI2MXyHWXFe1CV |
45
|
|
|
|
|
|
|
PYdL6Z+MW6q7tFbtZIIyJiSXRogDfaL35VnWCgAq/WfIe/j2iR5NC4EZnW0n2HUP |
46
|
|
|
|
|
|
|
1f4Qq0eZP+sE8aviltdgqAwKbzQU4mS4cLEWH9+qEiiwRzZZBPhxMyoGSQRd46ca |
47
|
|
|
|
|
|
|
aDPG8QKBgGcfirAer9OGH0TOktK2fzfkZlV7mgmPtjp7ia1DnTgozZCq26j5Bwuy |
48
|
|
|
|
|
|
|
g9hcGJT7XwPVChY4A3pLX87Xx08TBlcLpKAorY8tP7maxHa0Dpg8/tErmwNyPE/A |
49
|
|
|
|
|
|
|
g0oXuSr48qa6mkrQMqkmCcouNT4MKuvFiQ70DB+kwJ5hB2pM75bS |
50
|
|
|
|
|
|
|
-----END RSA PRIVATE KEY----- |
51
|
|
|
|
|
|
|
}; |
52
|
|
|
|
|
|
|
$key = $key_temp->filename; |
53
|
|
|
|
|
|
|
close($key_temp); |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my $cert_temp = File::Temp->new( UNLINK => 0 ); |
56
|
|
|
|
|
|
|
print $cert_temp q{-----BEGIN CERTIFICATE----- |
57
|
|
|
|
|
|
|
MIIEhjCCA26gAwIBAgIJALsLM/f4lmkHMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD |
58
|
|
|
|
|
|
|
VQQGEwJHQjEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xGzAZBgNV |
59
|
|
|
|
|
|
|
BAoTEkJvYiBUIEZpc2ggZG90IE5ldDEUMBIGA1UEAxMLVG9tYXMgRG9yYW4xJDAi |
60
|
|
|
|
|
|
|
BgkqhkiG9w0BCQEWFWJvYnRmaXNoQGJvYnRmaXNoLm5ldDAeFw0wODA4MDYxNjI5 |
61
|
|
|
|
|
|
|
MTFaFw0zNTEyMjMxNjI5MTFaMIGIMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9u |
62
|
|
|
|
|
|
|
ZG9uMQ8wDQYDVQQHEwZMb25kb24xGzAZBgNVBAoTEkJvYiBUIEZpc2ggZG90IE5l |
63
|
|
|
|
|
|
|
dDEUMBIGA1UEAxMLVG9tYXMgRG9yYW4xJDAiBgkqhkiG9w0BCQEWFWJvYnRmaXNo |
64
|
|
|
|
|
|
|
QGJvYnRmaXNoLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIQ |
65
|
|
|
|
|
|
|
ymDbAnfhE0VCEyINVN04OLsv71yZDd2WUteC0m3BaZ8M4pzMRQ+AP4P3UqYR1sZf |
66
|
|
|
|
|
|
|
8mXoA1c92ViFdBJ+tmAuz32MCVlnf+GC7w3p0ABFs+3DU5Ac16kMKoq4w6hClw8k |
67
|
|
|
|
|
|
|
EGeIxS0dxMGGn46w/fYe9SRI7jmvmWdK4C7tgj4R+TMRFVo0s9LUhVO+22TWSnWB |
68
|
|
|
|
|
|
|
XXirWb9BM+CRsk5VbvHcH7J3zKaMlS/3OMQl7CfpDXJywKeERo2K1E5of162CtO0 |
69
|
|
|
|
|
|
|
Lj41ITz18pU2Cq82AnIYzEWYwJs+RL10m15egk59CTlBLWFb5CRjXXdeIyns+YqA |
70
|
|
|
|
|
|
|
39foJ1+54dtLqIOpLPUCAwEAAaOB8DCB7TAdBgNVHQ4EFgQUOzPRmC5xIBWKeeOT |
71
|
|
|
|
|
|
|
sam6S+s5l8swgb0GA1UdIwSBtTCBsoAUOzPRmC5xIBWKeeOTsam6S+s5l8uhgY6k |
72
|
|
|
|
|
|
|
gYswgYgxCzAJBgNVBAYTAkdCMQ8wDQYDVQQIEwZMb25kb24xDzANBgNVBAcTBkxv |
73
|
|
|
|
|
|
|
bmRvbjEbMBkGA1UEChMSQm9iIFQgRmlzaCBkb3QgTmV0MRQwEgYDVQQDEwtUb21h |
74
|
|
|
|
|
|
|
cyBEb3JhbjEkMCIGCSqGSIb3DQEJARYVYm9idGZpc2hAYm9idGZpc2gubmV0ggkA |
75
|
|
|
|
|
|
|
uwsz9/iWaQcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZmk7GGuI |
76
|
|
|
|
|
|
|
xiI/ctxD7DY9j7K9nbb6geie/BUHhAkK6MFX+wU9/txA19MhxZo/j/pZyWFs1ocH |
77
|
|
|
|
|
|
|
DFk+DGk1cbxyJVa5EhIRaGygKDfkD3RO21rbvkqOeEONnqAkrXbD0C2RaO/yPpQh |
78
|
|
|
|
|
|
|
Eo7MzmVnDSJC03MRPMSmcOf4/+FdgXNmI7fJ6uqH1poVuISvcyVaufSIiwz1rmCw |
79
|
|
|
|
|
|
|
U3f1B/1R70Fj7X5yj+pd2BQHUHzfwk6kSwBXbnqzA8zReOorrCkGuier9wzB2OUT |
80
|
|
|
|
|
|
|
5EFOcIb3iNvk445bowUsH7pCGUYh3dJqWjIQ39BMfyO5K2SaOzldF0Z9VoK/lCOE |
81
|
|
|
|
|
|
|
eCRh+7VA074hiw== |
82
|
|
|
|
|
|
|
-----END CERTIFICATE----- |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
}; |
85
|
|
|
|
|
|
|
$cert = $cert_temp->filename; |
86
|
|
|
|
|
|
|
close($cert_temp); |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
sub _handle_CONNECT { |
89
|
0
|
|
|
0
|
|
|
my ($self, $served) = @_; |
90
|
0
|
|
|
|
|
|
my $last = 0; |
91
|
0
|
|
|
|
|
|
my $conn = $self->client_socket; |
92
|
0
|
|
|
|
|
|
my $req = $self->request; |
93
|
0
|
|
|
|
|
|
my $upstream = IO::Socket::INET->new( PeerAddr => $req->uri->host_port ); |
94
|
0
|
0
|
0
|
|
|
|
unless( $upstream and $upstream->connected ) { |
95
|
|
|
|
|
|
|
# 502 Bad Gateway / 504 Gateway Timeout |
96
|
|
|
|
|
|
|
# Note to implementors: some deployed proxies are known to |
97
|
|
|
|
|
|
|
# return 400 or 500 when DNS lookups time out. |
98
|
0
|
|
|
|
|
|
my $response = HTTP::Response->new( 200 ); |
99
|
0
|
|
|
|
|
|
$response->content_type( "text/plain" ); |
100
|
0
|
|
|
|
|
|
$self->response($response); |
101
|
0
|
|
|
|
|
|
return $last; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# send the response headers (FIXME more headers required?) |
105
|
0
|
|
|
|
|
|
my $response = HTTP::Response->new(200); |
106
|
0
|
|
|
|
|
|
$self->response($response); |
107
|
0
|
|
|
|
|
|
$self->{$_}{response}->select_filters( $response ) for qw( headers body ); |
108
|
|
|
|
|
|
|
|
109
|
0
|
|
|
|
|
|
$self->_send_response_headers( $served ); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# we now have a TCP connection to the upstream host |
112
|
0
|
|
|
|
|
|
$last = 1; |
113
|
0
|
|
|
|
|
|
my $class = ref($conn); |
114
|
1
|
|
|
1
|
|
6
|
{ no strict 'refs'; unshift(@{$class . "::ISA"}, 'IO::Socket::SSL'); } # Forcibly change classes the socket inherits from |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
114
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
115
|
0
|
0
|
|
|
|
|
$class->start_SSL($conn, |
116
|
|
|
|
|
|
|
SSL_server => 1, |
117
|
|
|
|
|
|
|
SSL_key_file => $key, |
118
|
|
|
|
|
|
|
SSL_cert_file => $cert, # Turn our client socket into SSL. |
119
|
|
|
|
|
|
|
) or warn("Could not start SSL"); |
120
|
0
|
|
|
|
|
|
${*$conn}{'httpd_nomore'} = 0; # Pay no attention to the Connection: close header behind the curtain. |
|
0
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
{ # Build a method to fiddle with the request object we get from the client, as it needs to http->https |
122
|
0
|
|
|
|
|
|
my $old_setrequest_method = \&HTTP::Proxy::request; |
|
0
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
my $new_request_method = sub { |
124
|
0
|
|
|
0
|
|
|
my ($self, $new_req) = @_; |
125
|
0
|
0
|
|
|
|
|
if ($new_req) { |
126
|
1
|
|
|
1
|
|
2512
|
use Data::Dumper; |
|
1
|
|
|
|
|
8894
|
|
|
1
|
|
|
|
|
258
|
|
127
|
0
|
0
|
0
|
|
|
|
if (!$new_req->uri->scheme or $new_req->uri->scheme eq 'http') { |
128
|
0
|
|
|
|
|
|
$new_req->uri->scheme('https'); |
129
|
0
|
|
|
|
|
|
$new_req->uri->host($new_req->header('Host')); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
0
|
|
|
|
|
|
$old_setrequest_method->($self, $new_req); |
133
|
0
|
|
|
|
|
|
}; |
134
|
|
|
|
|
|
|
# And monkeypatch it into HTTP proxy, using local to restrict it by lexical scope |
135
|
|
|
|
|
|
|
# so that it goes away once we exit the block (i.e. the CONNECT method finishes). |
136
|
1
|
|
|
1
|
|
13
|
no warnings qw[once redefine]; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
77
|
|
137
|
0
|
|
|
|
|
|
local *HTTP::Proxy::request = $new_request_method; |
138
|
1
|
|
|
1
|
|
6
|
use warnings qw[once redefine]; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
220
|
|
139
|
0
|
|
|
|
|
|
$self->serve_connections($conn); |
140
|
|
|
|
|
|
|
} |
141
|
0
|
|
|
|
|
|
$conn->stop_SSL($conn); |
142
|
0
|
|
|
|
|
|
return $last; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
{ |
145
|
1
|
|
|
1
|
|
7
|
no warnings qw(once redefine); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
632
|
|
146
|
|
|
|
|
|
|
*HTTP::Proxy::_handle_CONNECT = \&_handle_CONNECT; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
our %http_proxy_defaults = ( |
150
|
|
|
|
|
|
|
port => 3128, |
151
|
|
|
|
|
|
|
max_clients => 10, |
152
|
|
|
|
|
|
|
max_requests_per_child => 100, |
153
|
|
|
|
|
|
|
min_spare_servers => 1, |
154
|
|
|
|
|
|
|
max_spare_servers => 5, |
155
|
|
|
|
|
|
|
keep_alive => 0, |
156
|
|
|
|
|
|
|
max_keep_alive_requests => 1, |
157
|
|
|
|
|
|
|
keep_alive_timeout => 60, |
158
|
|
|
|
|
|
|
engine => 'NoFork', |
159
|
|
|
|
|
|
|
); |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub _generate_proxy_config { |
162
|
0
|
|
|
0
|
|
|
my %in_params = @_; |
163
|
0
|
|
|
|
|
|
my %params; |
164
|
0
|
|
|
|
|
|
foreach my $k (keys %http_proxy_defaults) { |
165
|
0
|
0
|
|
|
|
|
$params{$k} = exists $in_params{$k} ? $in_params{$k} : $http_proxy_defaults{$k}; |
166
|
|
|
|
|
|
|
} |
167
|
0
|
|
|
|
|
|
return %params; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
my $_help = q{No config file passed on command line. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Please create a file in a text editor which looks like this: |
173
|
|
|
|
|
|
|
# Note that more options are available, please see example_config.ini in the distribution for usage. |
174
|
|
|
|
|
|
|
port = 3128 |
175
|
|
|
|
|
|
|
debug = 1 |
176
|
|
|
|
|
|
|
#upstream_proxy = proxy.example.com:8080 |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
[search.cpan.org] |
179
|
|
|
|
|
|
|
/s/=/tmp/css |
180
|
|
|
|
|
|
|
/stuff/=/tmp/stuff |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
[www.google.com] |
183
|
|
|
|
|
|
|
/js/=/tmp/js |
184
|
|
|
|
|
|
|
/some/file.jpg=/tmp/somefile.jpg |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
and save it in your editor. Then re-run selective_proxy, appending the configuration file name. |
187
|
|
|
|
|
|
|
}; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub main { |
190
|
0
|
|
|
0
|
|
|
my $conf_file = shift(@ARGV); |
191
|
0
|
0
|
|
|
|
|
die($_help) unless ($conf_file); |
192
|
0
|
0
|
|
|
|
|
die("Config file passed on command line ($conf_file) could not be read.\n") unless (-r $conf_file); |
193
|
|
|
|
|
|
|
|
194
|
0
|
|
|
|
|
|
my %config = %{ Config::Tiny->read( $conf_file ) }; |
|
0
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
|
196
|
0
|
|
|
|
|
|
my $root_config = delete $config{_}; |
197
|
0
|
|
|
|
|
|
my $debug = delete $root_config->{debug}; |
198
|
0
|
|
|
|
|
|
my $upstream_proxy = delete $root_config->{upstream_proxy}; |
199
|
|
|
|
|
|
|
|
200
|
0
|
|
|
|
|
|
my $proxy = HTTP::Proxy->new( |
201
|
0
|
|
|
|
|
|
_generate_proxy_config( %{$root_config} ), |
202
|
|
|
|
|
|
|
max_connections => 0, # Not lettng the users stamp on this.. |
203
|
|
|
|
|
|
|
); |
204
|
0
|
|
|
|
|
|
$proxy->init; |
205
|
0
|
0
|
|
|
|
|
die("No agent") unless $proxy->{agent}; |
206
|
0
|
0
|
|
|
|
|
warn("Upstream proxy: $upstream_proxy") if $upstream_proxy; |
207
|
0
|
0
|
|
|
|
|
$proxy->{agent}->proxy([qw/http https/], $upstream_proxy) if $upstream_proxy;; |
208
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
$proxy->push_filter( |
210
|
|
|
|
|
|
|
method => 'GET, HEAD', |
211
|
|
|
|
|
|
|
request => HTTP::Proxy::Selective->new(\%config, $debug) |
212
|
|
|
|
|
|
|
); |
213
|
0
|
|
|
|
|
|
warn("Starting proxy at " . $proxy->url . "\n"); |
214
|
0
|
|
|
|
|
|
$proxy->start; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
main() unless caller(); |
218
|
|
|
|
|
|
|
main() if $ENV{PAR_0}; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
1; |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
__END__ |