aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpsyc://loupsycedyglgamf.onion/~lynX <ircs://psyced.org/youbroketheinternet>2016-08-10 15:28:56 +0000
committerpsyc://loupsycedyglgamf.onion/~lynX <ircs://psyced.org/youbroketheinternet>2016-08-10 15:28:56 +0000
commita727e7f29a0b56121f825beb64074dad90a64752 (patch)
tree0e088f977c1ddf292af48d506f5a6372af57940d
parent25a19f76a99cc8e536fd19b533daea2c32213747 (diff)
downloadperlpsyc-a727e7f29a0b56121f825beb64074dad90a64752.tar.gz
perlpsyc-a727e7f29a0b56121f825beb64074dad90a64752.zip
how come httpd2psyc was missing?
-rwxr-xr-xbin/httpd2psyc230
1 files changed, 230 insertions, 0 deletions
diff --git a/bin/httpd2psyc b/bin/httpd2psyc
new file mode 100755
index 0000000..0875c14
--- /dev/null
+++ b/bin/httpd2psyc
@@ -0,0 +1,230 @@
1#!/usr/local/bin/perl -I/usr/depot/lib/perl5
2
3sub debug() { 0 }
4sub chat() { 1 }
5
6use IO::Socket;
7use POSIX qw( mkfifo ); # optional, for -s option
8use Pod::Usage qw( pod2usage );
9use Term::ANSIColor qw( :constants ); # optional but pervasive
10use Net::PSYC qw( :event ); # needed for event loop
11use Getopt::Std qw( getopt );
12getopt('timbls');
13
14my $bind = $opt_b || "psyc://$ENV{USER}\@127.0.0.1:4088/\$httpd";
15my $target = $opt_t || "psyc://127.0.0.1:4404/\@httpd";
16
17
18## SANDWICHES ##
19
20sub say {
21 print BOLD, GREEN, @_, RESET, "\n";
22}
23
24sub reallyquit { exit; }
25sub quit {
26 # error condition can be triggered several times
27 return if $quitting++;
28 tellpsyc(chat? "_request_leave_httpd": "_notice_stopping_httpd", "[_command] stopping on [_nick].");
29 tellpsyc("_request_circuit_shutdown", "Seeyasoon.");
30 add(2, 't', \&reallyquit);
31}
32
33sub tellpsyc {
34 my ($mc, $text, $var, $value) = @_;
35 say "tellpsyc: ", $text if debug & 4;
36 return unless $target;
37 if (length $text > 1000) {
38 $mc = "_error_excessive_data$mc";
39 $text = "[_amount_data] bytes of excess data ignored. Check console.";
40 $var = "_amount_data";
41 $value = length $text;
42 }
43 sendmsg($target, $mc, $text, $value? { $var => $value } : \%pv);
44}
45
46sub fifoerror {
47 return if $quitting;
48 my $msg = "FIFO error: $_";
49 say $msg;
50 tellpsyc('_notice_warning_httpd', $msg);
51 if ($opt_d) {
52 sleep 7;
53 goto REOPEN;
54 }
55 return &quit;
56}
57
58sub fifoparse {
59 $_ = <$fifo>;
60 chomp; chomp;
61 say "fifoparse($!): $_" if debug & 1;
62 fifoerror unless $_;
63 print $log $_, "\n" if $log;
64 # if httpd is giving us non-json input, we just send it as is
65 unless ( /^{ (.*)},$/ ) {
66 tellpsyc('_notice_access_httpd_raw', $_);
67 return;
68 }
69 $_ = $1;
70 @_ = split( /"([^"]*)":"([^"]*)", / );
71 my %m = %pv;
72 while (@_) {
73 $e = shift; $k = shift; $v = shift;
74 print STDERR "JSON parse error: '$e' in { $_ }" if $e;
75 print "\t", GREEN, $k, RESET, "\t", $v, "\n" if debug & 8;
76 $m{$k} = $v;
77 }
78 $m{_network_traffic} = $m{_network_traffic_incoming} + $m{_network_traffic_outgoing};
79 # only forward to psyced when not a transfer continuation
80# if ( $m{_status_HTTP} eq 206 ) {
81# print CYAN, " +", $m{_network_traffic}, " ", RESET;
82# return;
83# }
84# print RED, "_", RESET;
85 print BOLD, $m{_status_HTTP}, " ", CYAN, $m{_network_address_IP}, "\t",
86 RESET, $m{_network_traffic}, "\t", BOLD, YELLOW, $m{_item_path},
87 " ", GREEN, $m{_version_agent_HTTP}, RESET, "\n";
88 # only forward messages about large files...... YMMV
89 return if $opt_s and $m{_network_traffic} < $opt_s || $m{_status_HTTP} eq 206;
90 sendmsg($target, '_notice_access_httpd', "[_network_address_IP] fetches [_item_path] ([_network_traffic] bytes) using [_version_agent_HTTP]", \%m);
91}
92
93sub keyparse {
94 $_ = <STDIN>;
95 say "keyparse: ", $_ if debug & 2;
96 return &quit if /^\s*q\s*$/i;
97 return system('/usr/bin/clear') if /^\.$/;
98 # should be _converse
99 return tellpsyc("_message_public", $1) if m!^\s*/\s+(.*\S.*)$!;
100}
101
102sub msg {
103 my ($source, $mc, $data, $vars) = @_;
104 say "psyc: $mc from $source" if debug & 4;
105 if ($mc =~ /^_(message|converse)/) {
106 # message echo will pass through here. legitimate users of
107 # your PSYC server can send a message back to the localhost
108 # process, so you may see an answer from somebody.
109 if (exists $vars->{_nick}) {
110 $_ = "<". $vars->{_nick} ."> ". YELLOW . $data;
111 } else {
112 $_ = "(". $source .") ". YELLOW . $data;
113 }
114 } elsif (chat and $mc =~ /^_notice.*_httpd/) {
115 return; # do not display our own notices
116 } else {
117 $_ = psyctext($data, $vars);
118 }
119 print BOLD, MAGENTA, $_, RESET, "\n";
120}
121
122sub idlebilly {
123 tellpsyc('_notice_warning_idle_httpd', "[_command] has detected idling [_nick] httpd.");
124}
125
126sub mkdirhier {
127 my $d = shift;
128 if (-d $d) {
129# print STDERR BLUE, "(directory $d already exists)\n", RESET;
130 } else {
131 if (system('/bin/mkdir', '-p', $d)) {
132 undef $!;
133 die "Could not make directory hierarchy: $!"
134 if system('mkdirhier', $d);
135 }
136 }
137}
138
139## MAIN ###
140
141 say "httpd2psyc - a real-time httpd log analyzer with PSYC notification";
142 $nick = shift || 'default';
143 if ($opt_h) {
144 pod2usage;
145 }
146
147 $pv{_nick} = $nick;
148 $pv{_command} = $0;
149 bind_uniform( $bind );
150 register_uniform();
151 say "Listening for PSYC controls on $bind";
152 say "Sending PSYC notifications to $target";
153
154 $|=1;
155
156 $fifopath = $opt_m || "/var/run/httpd.fifo";
157 if (not -p $fifopath) {
158 $fifopath =~ m#(.*)/[^/]+$#;
159 mkdirhier( $1 ) if $1;
160 undef $!;
161 die "Could not mkfifo $fifopath $!" unless mkfifo $fifopath, 0600;
162# system('chgrp', 'www', $fifopath);
163# chmod 0660, $fifopath;
164 }
165 say "Monitoring $fifopath for HTTP events";
166REOPEN:
167 if (open($fifo, $fifopath)) {
168 add($fifo, 'r', \&fifoparse);
169 add($fifo, 'e', \&fifoerror);
170 } else {
171 die "Cannot read from $fifopath: $!";
172 }
173 die "Cannot write to $opt_l: $!"
174 if $opt_l and not open($log, '>>', $opt_l);
175 add(\*STDIN, 'r', \&keyparse);
176 add($opt_i, 'i', \&idlebilly) if $opt_i;
177 tellpsyc(chat? "_request_enter_httpd": "_notice_starting_httpd", "[_command] starting on [_nick].");
178 start_loop();
179 exit;
180
181__END__
182
183=pod
184
185=head1 NAME
186
187httpd2psyc - a real-time httpd log analyzer with PSYC notification
188
189=head1 SYNOPSIS
190
191 httpd2psyc [<options>] [<nickname>]
192
193 Options:
194 -m <path> (m)onitor a FIFO for interesting HTTP events
195 -t <uniform> PSYC (t)arget address to send notifications to
196 -d (D)aemon: reopen FIFO whenever httpd closes it (on restart)
197 -s <bytes> Threshold of traffic (s)ize before forwarding is triggered
198 -b <uniform> PSYC address to (b)ind to
199 -l <logfile> Keep a transaction (l)og - BEWARE OF GDPR!
200 -i <seconds> Send a PSYC warning if httpd has been (i)dle too long
201
202=head1 DESCRIPTION
203
204HTTP logfile to PSYC gateway. Works by sending httpd logfile output
205into a FIFO and having this script pick it up. For optimal rendering
206you should configure your httpd to output JSON-PSYC format, using
207something like this:
208
209 LogFormat "{ \"_time_JSON\":\"%{%Y-%m-%d}tT%{%T}t.%{msec_frac}tZ\", \"_system_process\":\"%D\", \"_item_size\":\"%B\", \"_item_path\":\"%f\", \"_network_address_IP\":\"%a\", \"_site_HTTP\":\"%V\", \"_request_HTTP\":\"%U\", \"_query_HTTP\":\"%q\", \"_method_HTTP\":\"%m\", \"_status_HTTP\":\"%>s\", \"_version_agent_HTTP\":\"%{User-agent}i\", \"_uniform_referrer\":\"%{Referer}i\", \"_network_traffic_incoming\":\"%I\", \"_network_traffic_outgoing\":\"%O\", }," jsonpsyc
210 CustomLog /var/run/httpd.fifo jsonpsyc
211
212You should run 'httpd2psyc -m /var/run/httpd.fifo' first so that
213it takes care of mkfifo.
214
215=head1 PRIVACY
216
217Remember that you are not supposed to store any IP numbers or other
218personal data if you intend to be GDPR compliant. This is just for
219realtime monitoring.
220
221=head1 AUTHORS
222
223carlo von lynX.
224
225=head1 COPYRIGHT
226
227This program is free software, published under the Affero GNU Public
228License. A disclaimer isn't necessary in my country, nor do I need
229to mention the current year to assert a copyright.
230