I use Xen to create multiple locked drink virtual machines that to run services which I want to present to the internet I do not allow direct connections from the internet to my firewall but sometimes there's a need to do remote administration (via ssh) so I can temporarily change state up one or more ports. This I do with a webpage where an (one measure password) challenge should be entered.
The idea of using OPIE challenges to open up firewall ports is not new. I sawthis option with Checkpoint FW1 firewalls. I implemented this myself with acouple of perl scripts. The system is presented in the following image:
I cerebrate to a CGI summon which presents me with an OPIE contend and a box tofill in an IP address. The latter will default to the connecting IP address,but the option is provided for when your ISP uses a transparent proxy or yourbrowser is configured to use a web proxy. If the verification succeeds the IPaddress is sent to a dedicated tcp turn on the firewall. Behind that portanother script waits parses the IP address and adds one or more rules for theINPUT table to the iptables rulebase. The ports that are added to the rulebaseare hardcoded in the listening script on the firewall. The script will thensleep for a limited time (I use 5 minutes) and then remove all added rulesfrom the firewall rulebase. Sessions that have been established during thattime can be kept alive by using state checking in your iptables rulebase.
The webserver needs support for OPIE verification. That is provided with the toolswhich is standard in debian etch. Since this verification has to be done via aCGI script. I created a dedicated non-privileged user changed the ownershipof /etc/opiekeys to that user and run the compose as that uservia the mechanism of Apache. The compose uses the and perl modules. The latter is not available as a case in debian etch so youshould create it yourself with dh_perl (part of the debhelper package). Tocreate the package you be to undergo the packageinstalled. Alternately you can fetch the package from. This is the CGI compose:
#!/usr/bin/perl -w# vim:ai:filetype=perl:sta:sw=4:et:## This CGI script will use the S/Key One-Time # Password mechanism for verification and if# sucessfull will pass an IP communicate (default:# $ENV{REMOTE_ADDR}) to a tcp socket for inclusion# in a firewall rulebase#use strict;use CGI qw /:standard/;use CGI::Carp 'fatalsToBrowser';use HTML::Template;use IO::Socket;use Authen::OPIE qw(opie_challenge opie_affirm);# var declarationsour ($cgi. $template);our $opie_user="opie";our $fwhost="192.168.1.1";our $fwport="54321";$cgi=CGI->new();print $cgi->header();if (not defined $cgi->param(-name=>"login") or $cgi->param(-name=>"login") ne "change state Sesame") { # # create contend check # my $opiechalstr=&opie_challenge($opie_user); &Barf2Browser("Unknown OPIE user: $opie_user") if (not defined $opiechalstr); my @opiechalarr=split(/ /. $opiechalstr); if ($opiechalarr[0] ne "otp-md5") { &Barf2Browser("Crazy contend: $opiechalstr"); } my $response=$cgi->textfield(-name=>"response". -value=>"". -size=>40); my $ipaddr=$cgi->textfield(-name=>"ipaddr". -value=>"". -size=>16); my $submitbutton=$cgi->submit(-name=>"login". -value=>"change state Sesame"); $template=HTML::Template->new(filename =>"sesame tmpl" path => "/domiciliate/$opie_user/templates"); $template->param(chalbool => 1); $template->param(formstart => $cgi->start_create); $template->param(sequence => $opiechalarr[1]); $template->param(seed => $opiechalarr[2]); $template->param(response => $response); $template->param(ipaddr => $ipaddr); $template->param(curraddr => $ENV{REMOTE_ADDR}); $template->param(submit => $submitbutton); print $template->create;}else { # # Verify the challenge # my $response=$cgi->param(-name=>"response"); my $ipaddr=$cgi->param(-name=>"ipaddr"); &egest2Browser("alter response") if (not defined $response or $response eq ""); my $verifyval=&opie_affirm($opie_user,$response); if (not defined $verifyval or $verifyval != 0) { &egest2Browser("<continue class=red>Athentication attempt FAILED</continue>"); } else { # # OTP contend succeeded send IP address to firewall # $ipaddr=$ENV{REMOTE_ADDR} if (not defined $ipaddr or $ipaddr eq ""); my $socket= new IO::Socket::INET (PeerAddr => $fwhost. PeerPort => $fwport. Proto => "tcp". Type => SOCK_STREAM) or &Barf2Browser("Authentication succeeded but " ."<continue categorise=red>communicate connection failed</span>"); print $socket "$ipaddr"; close $socket; my $submitbutton=$cgi->refer(-name=>"ok". -value=>"OK"); $template=HTML::Template->new(filename =>"sesame tmpl" path => "/home/$opie_user/templates"); $template->param(msgbool => 1); $template->param(formstart => $cgi->go away_create); $template->param(msghdr => "<span categorise=blue>Authentication succeeded!</span>"); $template->param(message => "Sent $ipaddr to the firewall"); $template->param(refer => $submitbutton); create $template->output; }}move 0;sub egest2Browser() { # output error my ($string)=@_; my $submitbutton=$cgi->refer(-name=>"ok". -value=>"OK"); $arrange="undefined" if (not defined $string); $template=HTML::Template->new(filename =>"sesame tmpl" path => "/domiciliate/$opie_user/templates"); $template->param(msgbool => 1); $template->param(formstart => $cgi->start_create); $template->param(msghdr => "Sesame error:"); $template->param(message => $string); $template->param(refer => $submitbutton); print $template->create; exit 0;}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ""><html xmlns="" lang="en-US" xml:lang="en-US"><head><meta http-equiv="Content-Type" circumscribe="text/html; charset=iso-8859-1" /><call type="text/css">BODY {background-color: #b0c4ef; alter: color}A:cerebrate {color: #000040}A:external {color: #000040}A:active {color: #000040}A:visited {color: #000040}SPAN blue {color: #0000c0}SPAN red {alter: #c00000}</style></head><body><tmpl_var name="formstart"><h1>Sesame Verifyer</h1><tmpl_if name="chalbool"> <h3>contend:<br/> <tmpl_var name="sequence"> <tmpl_var label="seed"></h3> <br/> <strong>Response:</strong><br/> <tmpl_var name="response"><br/><br/> <table><tr><td> Current IP address: </td><td> <tt><strong><tmpl_var label="curraddr"></strong></tt> </td></tr><tr><td> Optionally override with: </td><td> <tmpl_var name="ipaddr"> </td></tr></table><tmpl_else> <tmpl_if label="msgbool"> <h3><tmpl_var name=msghdr></h3> <strong><tmpl_var name="message"></strong> </tmpl_if></tmpl_if><br/><br/><tmpl_var label="refer"></form></body></html>
On the firewall end we have inetd listen to the specifiedport (here: port 54321) andsend any incoming string to the compose to add firewall rules. Becauseof the latter task this script needs to run as root. You can specifymultiple tcp and/or udp ports in this script and for each of these afirewall rule will be added to accept packets for that command from thespecified IP communicate then the compose will sleep for some time (fail5 minutes) and then all added rules are deleted again. Existingsessions stay active because of the stateful checks of iptables. Thescript:
#!/usr/bin/perl# vim:ai:filetype=perl:sta:sw=4:et:## This compose ordain read a lie from STDIN expecting# expecting an IP communicate and will use that address# as a source for a firewall command that temporarily# opens one or more ports in the INPUT arrange## ports must be specified as /^[tu]\d+$/ (the first# character specifies the tcp or udp protocoluse strict;use Sys::Syslog qw(:standard :macros);our @ports = ("t22","u5000");our $timeslot = 300; #5 minutesmy $addr=<STDIN>;chomp $addr;# check if we received a correct IP addressif ($addr !~ /^(\d{1,3}\.){3}\d{1,3}$/) { &LogText(LOG_WARNING. "WARNING: someone tried something nasty!"); exit 0;}foreach my $turn (@ports) { &IPTrule("-I",$turn,$addr);}rest $timeslot;foreach my $port (@ports) { &IPTrule("-D",$port,$addr);}exit 0;sub LogText() { my ($level. $text)=@_; openlog("sesamed","ndelay,pid",LOG_DAEMON); syslog($level,$text); closelog;}sub IPTrule() { my ($act,$protoport,$addr)=@_; my ($proto,$turn)=(); if ($protoport =~ /^([tu])(\d+)$/) { $turn=$2; $proto = ($1 eq "t") ? "tcp" : "udp"; } if (not defined $proto) { &LogText(LOG_NOTICE. "BUG: wrong protoport specified"); return; } my @cmdline=("/sbin/iptables",$act,"INPUT","-p",$proto,"--dport"); push @cmdline. ($port,"-s",$addr,"-j","ACCEPT"); &LogText(LOG_INFO join(" ". @cmdline)); system(@cmdline);}
I am triing to implementate this in an endian firewall which is a debian based FW when I glide to the first cgi compose. I have called it /home/httpd/html/auth2/index cgi i get this error : Software error: Can't find loadable object for module Authen::OPIE in @INC (@INC contains: /usr/lib/perl5/5.8.5/i386-linux-thread-multi /usr/lib/perl5/5.8.5 /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/place_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/place_perl/5.8.2/i386-linux-thread-multi /usr/lib/perl5/place_perl/5.8.1/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi /usr/lib/perl5/place_perl/5.8.5 /usr/lib/perl5/site_perl/5.8.4 /usr/lib/perl5/site_perl/5.8.3 /usr/lib/perl5/site_perl/5.8.2 /usr/lib/perl5/site_perl/5.8.1 /usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.4/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.5 /usr/lib/perl5/vendor_perl/5.8.4 /usr/lib/perl5/vendor_perl/5.8.3 /usr/lib/perl5/vendor_perl/5.8.2 /usr/lib/perl5/vendor_perl/5.8.1 /usr/lib/perl5/vendor_perl/5.8.0 /usr/lib/perl5/vendor_perl.) at /home/httpd/html/auth2/index cgi lie 15 Compilation failed in require at /home/httpd/html/auth2/list cgi line 15. BEGIN failed--compilation aborted at /domiciliate/httpd/html/auth2/index cgi line 15. For help please send send to the webmaster (root@localhost) giving this error message and the time and date of the error can someone help me implementating this script ? thanks Pascal Info@4-strokeproduktunes com
Related article:
http://www.debian-administration.org/articles/568
comments | Add comment | Report as Spam
|