#!/usr/bin/perl use warnings; use strict; use POE qw(Component::Server::TCP); use POE::Component::SSLify qw(Server_SSLify SSLify_Options); my @allowed_ips = ('127.0.0.1', '172.16.0.17', '172.16.0.1', '172.16.0.225'); my $listen_address = '172.16.0.224'; my $listen_port = '1337'; my $listen_conns = '-1'; my $listen_alias = 'rc-listener'; my $output = '/home/projects/perl/rc-listener/unknown-commands.txt'; my $ssl = 1; my $ssl_certfile = '/home/projects/perl/rc-listener/cert.crt'; my $ssl_keyfile = '/home/projects/perl/rc-listener/cert.key'; my $ssl_version = 'default'; POE::Component::Server::TCP->new( # Listen options Address => $listen_address, Port => $listen_port, Concurrency => $listen_conns, Alias => $listen_alias, # Server handlers Error => \&handle_server_error, Started => \&handle_server_started, Stopped => \&handle_server_stopped, # Client handlers ClientPreConnect => \&handle_client_pre_connect, ClientConnected => \&handle_client_connect, ClientDisconnected => \&handle_client_disconnect, ClientInput => \&handle_client_input, ClientError => \&handle_client_error, ClientFlushed => \&handle_client_flushed, ); # Start the server. POE::Kernel->run(); exit 0; sub handle_client_pre_connect { my ($session, $heap, $socket) = @_[SESSION, HEAP, ARG0]; my $session_id = $session->ID; my $remote_ip = $heap->{remote_ip}; my $remote_port = $heap->{remote_port}; my $remote = "[${remote_ip}]:${remote_port}"; unless (client_allowed($remote_ip)){ warn "ERROR > Connection from ${remote} with Session-ID ${session_id} denied by IP Policy.\n"; return undef; } if($ssl){ eval { SSLify_Options($ssl_keyfile, $ssl_certfile, $ssl_version) }; if($@){ warn "ERROR > Server unable to load key or certificate file.\n"; return undef; } my $ssl_socket = eval { Server_SSLify($socket) }; if($@){ warn "ERROR > Server unable to make an SSL connection.\n"; return undef; } return $ssl_socket; } else { return $socket; } } sub handle_client_connect { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; my $session_id = $session->ID; my $client = $heap->{client}; my $remote_ip = $heap->{remote_ip}; my $remote_port = $heap->{remote_port}; my $remote = "[${remote_ip}]:${remote_port}"; $client->put("Welcome ${remote} your Session-ID is ${session_id}"); $client->put("Type 'help' for a complete list of accepted commands"); warn "WARN > Client ${remote} connected with Session-ID ${session_id}\n"; } sub handle_client_disconnect { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; my $session_id = $session->ID; my $client = $heap->{client}; my $remote_ip = $heap->{remote_ip}; my $remote_port = $heap->{remote_port}; my $remote = "[${remote_ip}]:${remote_port}"; warn "WARN > Client ${remote} with Session-ID ${session_id} disconnected\n"; } sub handle_client_input { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; my $session_id = $session->ID; my $client = $heap->{client}; my $remote_ip = $heap->{remote_ip}; my $remote_port = $heap->{remote_port}; my $remote = "[${remote_ip}]:${remote_port}"; if ($input eq "quit") { $client->put("Goodbye ${remote}"); $_[KERNEL]->yield("shutdown"); return; } if ($input eq "ping") { $client->put("pong"); return; } if ($input eq "whoami") { $client->put("Your IP Address is ${remote_ip}"); $client->put("Your port is ${remote_port}"); return; } if ($input eq "help") { $client->put("Really? C'mon, just type something!"); return; } open(my $fh, '>>', $output) or die "Could not open file '$output' $!"; print $fh "${input}\n"; #$heap->{client}->put("Received input: ".$input); warn "WARN > Client ${remote} Session-ID ${session_id}: ${input}\n"; } sub handle_client_error { my ($syscall_name, $err_num, $err_str) = @_[ARG0..ARG2]; warn "ERROR > Client: ${err_num} - ${err_str}\n"; } sub handle_client_flushed { my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0]; my $session_id = $session->ID; my $client = $heap->{client}; my $remote_ip = $heap->{remote_ip}; my $remote_port = $heap->{remote_port}; my $remote = "[${remote_ip}]:${remote_port}"; warn "INFO > Client ${remote} flushed\n"; } sub handle_server_started { warn "INFO > Server [${listen_address}]:${listen_port} started\n"; } sub handle_server_stopped { warn "INFO > Server [".$listen_address."]:".$listen_port." stopped\n"; } sub handle_server_error { my ($syscall_name, $err_num, $err_str) = @_[ARG0..ARG2]; warn "ERROR > Server: ${err_num} - ${err_str}\n"; } sub client_allowed { my $client_ip = shift; return grep { $_ eq $client_ip || $_ eq '0/0' || $_ eq '0.0.0.0/0' } @allowed_ips; }