-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathproxy.pl
More file actions
144 lines (121 loc) · 3.41 KB
/
proxy.pl
File metadata and controls
144 lines (121 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/perl
#
# Peteris Krumins (peter@catonmat.net)
# http://www.catonmat.net -- good coders code, great reuse
#
# A simple TCP proxy that implements IP-based access control
# It proxies data from Growatt ShineLink to the Growatt servers
# and stores relevant data in a temporary file.
#
# Written for the article "Turn any Linux computer into SOCKS5
# proxy in one command," which can be read here:
#
# http://www.catonmat.net/blog/linux-socks5-proxy
#
use warnings;
use strict;
use IO::Socket;
use IO::Select;
use Data::Hexify;
my @allowed_ips = ('1.2.3.4', '5.6.7.8', '127.0.0.1', '192.168.0.1');
my $ioset = IO::Select->new;
my %socket_map;
my $debug = 1;
sub new_conn {
my ($host, $port) = @_;
return IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port
) || die "Unable to connect to $host:$port: $!";
}
sub new_server {
my ($host, $port) = @_;
my $server = IO::Socket::INET->new(
LocalAddr => $host,
LocalPort => $port,
ReuseAddr => 1,
Listen => 100
) || die "Unable to listen on $host:$port: $!";
}
sub new_connection {
my $server = shift;
my $client = $server->accept;
my $client_ip = client_ip($client);
unless (client_allowed($client)) {
print "Connection from $client_ip denied.\n" if $debug;
$client->close;
return;
}
print "Connection from $client_ip accepted.\n" if $debug;
my $remote = new_conn('server.growatt.com', 5279);
$ioset->add($client);
$ioset->add($remote);
$socket_map{$client} = $remote;
$socket_map{$remote} = $client;
}
sub close_connection {
my $client = shift;
my $client_ip = client_ip($client);
my $remote = $socket_map{$client};
$ioset->remove($client);
$ioset->remove($remote);
delete $socket_map{$client};
delete $socket_map{$remote};
$client->close;
$remote->close;
print "Connection from $client_ip closed.\n" if $debug;
}
sub client_ip {
my $client = shift;
return inet_ntoa($client->sockaddr);
}
sub client_allowed {
my $client = shift;
my $client_ip = client_ip($client);
return grep { $_ eq $client_ip } @allowed_ips;
}
sub save_to_file {
my $msg = shift;
my $filename = 'report.txt';
print ("Write", Hexify($msg), "\n");
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $msg;
close $fh;
}
sub save_to_file2 {
my $msg = shift;
my $filename = 'report13.txt';
print ("Write", Hexify($msg), "\n");
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $msg;
close $fh;
}
print "Starting a server on 0.0.0.0:5279\n";
my $server = new_server('0.0.0.0', 5279);
$ioset->add($server);
while (1) {
for my $socket ($ioset->can_read) {
if ($socket == $server) {
new_connection($server);
}
else {
next unless exists $socket_map{$socket};
my $remote = $socket_map{$socket};
my $buffer;
my $read = $socket->sysread($buffer, 4096);
if ($read) {
$remote->syswrite($buffer);
print ("Read" , Hexify(\$buffer), "\n");
if (substr($buffer, 6, 2) eq "\x51\x04" && length($buffer) > 100) {
save_to_file($buffer);
}
if (substr($buffer, 6, 2) eq "\x51\x03" && length($buffer) > 100) {
save_to_file2($buffer);
}
}
else {
close_connection($socket);
}
}
}
}