commit 0b90b27eb871a2c94c8336c2b5dd61f1d185bc05 Author: Daniel Berteaud Date: Sun Apr 28 21:43:50 2013 +0200 First commit diff --git a/createlinks b/createlinks new file mode 100644 index 0000000..7f08e63 --- /dev/null +++ b/createlinks @@ -0,0 +1,16 @@ +#!/usr/bin/perl -w + +use esmith::Build::CreateLinks qw(:all); + +templates2events("/etc/rc.d/init.d/masq", "fail2ban-update"); +templates2events("/etc/fail2ban/jail.conf", "fail2ban-conf"); +templates2events("/etc/fail2ban/fail2ban.conf", "fail2ban-conf"); +safe_symlink("adjust", "root/etc/e-smith/events/fail2ban-update/services2adjust/masq"); +safe_symlink("adjust", "root/etc/e-smith/events/fail2ban-conf/services2adjust/fail2ban"); + +service_link_enhanced("fail2ban", "S92", "7"); +service_link_enhanced("fail2ban", "K08", "6"); +service_link_enhanced("fail2ban", "K08", "0"); +safe_touch("root/var/service/fail2ban/down"); +safe_symlink("../daemontools" , 'root/etc/rc.d/init.d/supervise/fail2ban'); +safe_symlink("/var/service/fail2ban" , 'root/service/fail2ban'); diff --git a/root/etc/e-smith/db/configuration/defaults/fail2ban/status b/root/etc/e-smith/db/configuration/defaults/fail2ban/status new file mode 100644 index 0000000..86981e6 --- /dev/null +++ b/root/etc/e-smith/db/configuration/defaults/fail2ban/status @@ -0,0 +1 @@ +enabled diff --git a/root/etc/e-smith/templates/etc/fail2ban/fail2ban.conf/10All b/root/etc/e-smith/templates/etc/fail2ban/fail2ban.conf/10All new file mode 100644 index 0000000..b7cc31c --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/fail2ban.conf/10All @@ -0,0 +1,4 @@ +[Definition] +loglevel = 3 +logtarget = STDOUT +socket = /var/run/fail2ban/fail2ban.sock diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/00Default b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/00Default new file mode 100644 index 0000000..db4574b --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/00Default @@ -0,0 +1 @@ +[DEFAULT] diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/05IgnoreIP b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/05IgnoreIP new file mode 100644 index 0000000..a182f7a --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/05IgnoreIP @@ -0,0 +1,22 @@ +{ + +use esmith::NetworksDB; +my $n = esmith::NetworksDB->open_ro() || + die "Couldn't open networks DB\n"; + +my @ip = (127.0.0.1); + +# Add hosts which can access the server-manager to the whitelist +push @ip, " $_" foreach (split /[,;], (${'httpd-admin'}{'ValidFrom'} || '')); + +if (($fail2ban{FilterLocalNetworks} || 'disabled' eq 'enabled' ){ + foreach my $network ($n->networks){ + my $key = $network->key; + my $mask = $network->prop('Mask); + push @ip, "$key/$mask"; + } +} + +$OUT .= "ignoreip = " . join(" ", @ip); + +} diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10BanTime b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10BanTime new file mode 100644 index 0000000..89b80b9 --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10BanTime @@ -0,0 +1,7 @@ +{ + +my $bantime = $fail2ban{'BanTime'} || '600'; + +$OUT .= "bantime = $bantime"; + +} diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10FindTime b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10FindTime new file mode 100644 index 0000000..84b0966 --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/10FindTime @@ -0,0 +1,7 @@ +{ + +my $findtime = $fail2ban{'FindTime'} || '600'; + +$OUT .= "findtime = $findtime"; + +} diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/15MaxRetries b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/15MaxRetries new file mode 100644 index 0000000..cfe387b --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/15MaxRetries @@ -0,0 +1,6 @@ +{ +my $maxretry = $fail2ban{'MaxRetry'} || '3'; + +$OUT .= "maxretry = $maxretry"; + +} diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/20Backend b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/20Backend new file mode 100644 index 0000000..294cb23 --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/20Backend @@ -0,0 +1 @@ +backend = auto diff --git a/root/etc/e-smith/templates/etc/fail2ban/jail.conf/30Service10ssh b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/30Service10ssh new file mode 100644 index 0000000..f1de667 --- /dev/null +++ b/root/etc/e-smith/templates/etc/fail2ban/jail.conf/30Service10ssh @@ -0,0 +1,12 @@ +{ + +my $port = $sshd{'TCPPort'} || '22'; +$OUT .=<<"EOF"; +[ssh] + +enabled = true +filter = sshd +action = smeserver[port=$port, protocol=tcp] +logpath = /var/log/sshd/current +EOF +} diff --git a/root/etc/e-smith/templates/etc/rc.d/init.d/masq/40Fail2Ban b/root/etc/e-smith/templates/etc/rc.d/init.d/masq/40Fail2Ban new file mode 100644 index 0000000..934ffbd --- /dev/null +++ b/root/etc/e-smith/templates/etc/rc.d/init.d/masq/40Fail2Ban @@ -0,0 +1,10 @@ + # A blacklist chain for fail2ban + /sbin/iptables --new-chain Fail2Ban + /sbin/iptables --new-chain Fail2Ban_1 + /sbin/iptables --append Fail2Ban -j Fail2Ban_1 + # TODO: add a prop to filter only external or internal and external interfaces + # Check for banned hosts after local_chk and state_chk + # TODO: add a prop to block established connections for banned host + # which means insert into position 1 instead of 3 + /sbin/iptables --insert INPUT 3 \ + -j Fail2Ban diff --git a/root/etc/e-smith/templates/etc/rc.d/init.d/masq/90adjustFail2Ban b/root/etc/e-smith/templates/etc/rc.d/init.d/masq/90adjustFail2Ban new file mode 100644 index 0000000..653e3e8 --- /dev/null +++ b/root/etc/e-smith/templates/etc/rc.d/init.d/masq/90adjustFail2Ban @@ -0,0 +1,26 @@ +{ + my $f2bdb = esmith::ConfigDB->open_ro('fail2ban'); + # Find the current Fail2Ban_$$ chain, and create a new one. + $OUT .=<<'EOF'; + OLD_Fail2Ban=$(get_safe_id Fail2Ban filter find) + NEW_Fail2Ban=$(get_safe_id Fail2Ban filter new) + /sbin/iptables --new-chain $NEW_Fail2Ban +EOF + + foreach my $ban ( $f2bdb->get_all_by_prop(type=>('ban')) ){ + $OUT .= " /sbin/iptables --append \$NEW_Fail2Ban" . + " -s " . $ban->key . " -j denylog\n" + if ( ($fail2ban{'status'} || 'disabled') eq 'enabled' ); + $OUT .= " /sbin/iptables --append \$NEW_Fail2Ban" . + " -j RETURN\n"; + } + + # Having created a new Fail2Ban chain, activate it and destroy the old. + $OUT .=<<'EOF'; + /sbin/iptables --replace Fail2Ban 1 \ + --jump $NEW_Fail2Ban + /sbin/iptables --flush $OLD_Fail2Ban + /sbin/iptables --delete-chain $OLD_Fail2Ban +EOF + +} diff --git a/root/etc/fail2ban/action.d/smeserver.conf b/root/etc/fail2ban/action.d/smeserver.conf new file mode 100644 index 0000000..d41215d --- /dev/null +++ b/root/etc/fail2ban/action.d/smeserver.conf @@ -0,0 +1,9 @@ + +[Definition] + +actionban = /sbin/e-smith/sme-fail2ban --host= --proto= --port= +actionunban = /sbin/e-smith/sme-fail2ban --host= --unban --proto= --port= + +[Init] +protocol = undef +port = undef diff --git a/root/sbin/e-smith/sme-fail2ban b/root/sbin/e-smith/sme-fail2ban new file mode 100644 index 0000000..cca134e --- /dev/null +++ b/root/sbin/e-smith/sme-fail2ban @@ -0,0 +1,119 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +use esmith::ConfigDB; +use Getopt::Long; + +our $f2bdb = esmith::ConfigDB->open('fail2ban'); +our %opts; + + +sub usage(){ + print<<"EOF"; + +Usage: $0 --host= [--unban] [--protocol=tcp|udp|icmp|all] [--port=] + + * --host must specify a valid IPv4 adress in the form 10.11.12.13 + * --protocol can be used to specify the protocol to block. Only tcp, udp, icmp and all are valid (default is all) + * --port can be used to specify the port to block. Only valid for tcp and udp. You can also specify a range + of port like 10000:20000 + * if --unban is specified, the given host will be removed from the blacklist + default is to add to the blacklist instead + +EOF +} + +# Check if port is valid +sub is_valid_port($){ + my $port = shift; + my $ret = 0; + if ($port =~ m/^(\d+)[\-:](\d+)$/){ + $ret = 1 if ($1 >= 0 && + $1 < 65636 && + $2 >= 0 && + $2 < 65636); + } + else{ + $ret = 1 if ($port > 0 && + $port < 65636); + } + return $ret; +} + +# Generate a random uniq ID +sub generate_uniq_id(){ + my @chars = ('a'..'z','0'..'9'); + my $id = ''; + my $round = 0; + foreach (1..10){ + foreach (1..15){ + $id .= $chars[rand @chars]; + } + my $eid = $f2bdb->get($id); + last unless ($eid); + } + die "Couldn't generate a valid uniq ID\n" + if ($id eq ''); + return $id; +} + +# default is to ban a host +$opts{unban} = '0'; + +GetOptions( + "host=s" => \$opts{host}, + "unban" => \$opts{unban}, + "protocol=s" => \$opts{proto}, + "port=i" => \$opts{port} +); + +# special "undef" value for port and proto +undef $opts{proto} if ($opts{proto} eq 'undef'); +undef $opts{port} if ($opts{port} eq 'undef'); + +# Check options are valid + +# host is required +my @req = qw(host); +foreach (@req){ + usage() && die unless (defined $opts{$_}); +} + +# host must look like an IP address +usage() && die + unless ($opts{host} =~ m/^(?:(?:[01]?\d?\d?|2[0-4]\d|25[0-5])(?:\.|$)){4}$/); + +# protocol must can only be undefined, tcp, udp or icmp +usage() && die + if ($opts{proto} && $opts{proto} !~ m/^tcp|udp|icmp|all$/); + +# port must be a valid port number, and is only valid for tcp and udp +usage && die + if ($opts{port} && (($opts{proto} && $opts{proto} !~ m/^tcp|udp$/) || !is_valid_port($opts{port}))); + +if ($opts{unban}){ + foreach ($f2bdb->get_all_by_prop(Host => $opts{host})){ + my $proto = $_->prop('Protocol') || ''; + my $port = $_->prop('Port') || ''; + next if ($opts{proto} && $proto ne $opts{proto}); + next if ($opts{port} && $port ne $opts{port} && $proto =~ m/^tcp|udp$/); + $_->delete(); + } +} +else{ + my $id = generate_uniq_id(); + $f2bdb->new_record($id, {type => 'ban'}); + $f2bdb->set_prop($id, 'Host', $opts{host}); + $f2bdb->set_prop($id, 'Protocol', $opts{proto}) + if ($opts{proto}); + $f2bdb->set_prop($id, 'Port', $opts{port}) + if ($opts{port}); + # Set the current timestamp + $f2bdb->set_prop($id, 'Timestamp', time()); +} + +die "An error occured while updating the firewall rules" + unless (system("/sbin/e-smith/signal-event fail2ban-update") == 0); + +exit(0); diff --git a/root/var/service/fail2ban/log/run b/root/var/service/fail2ban/log/run new file mode 100644 index 0000000..62cb970 --- /dev/null +++ b/root/var/service/fail2ban/log/run @@ -0,0 +1,6 @@ +#!/bin/sh + +exec \ + /usr/local/bin/setuidgid smelog \ + /usr/local/bin/multilog t s5000000 \ + /var/log/fail2ban diff --git a/root/var/service/fail2ban/run b/root/var/service/fail2ban/run new file mode 100644 index 0000000..b038711 --- /dev/null +++ b/root/var/service/fail2ban/run @@ -0,0 +1,3 @@ +#!/bin/sh + +exec /usr/bin/fail2ban-server -fx diff --git a/smeserver-fail2ban.spec b/smeserver-fail2ban.spec new file mode 100644 index 0000000..88efa6c --- /dev/null +++ b/smeserver-fail2ban.spec @@ -0,0 +1,54 @@ +%define version 0.0.1 +%define release 1.beta0 +%define name smeserver-fail2ban + + +Summary: fail2ban integration on SME Server +Name: %{name} +Version: %{version} +Release: %{release}%{?dist} +License: GPL +Group: Networking/Daemons +Source: %{name}-%{version}.tar.gz + +BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot +BuildArchitectures: noarch +BuildRequires: e-smith-devtools + +Requires: e-smith-base >= 5.2.0 +Requires: fail2ban + +%description +Configure fail2ban on SME Server + +%changelog +* Sun Apr 28 2013 Daniel Berteaud - 0.1.0-1.sme +- initial release + +%prep +%setup -q -n %{name}-%{version} + +%build +%{__mkdir_p} root/var/log/fail2ban +perl createlinks + +%install +/bin/rm -rf $RPM_BUILD_ROOT +(cd root ; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT) +/bin/rm -f %{name}-%{version}-filelist +/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \ + --file /var/service/fail2ban/run 'attr(0755,root,root)' \ + --file /var/service/fail2ban/log/run 'attr(0755,root,root)' \ + --dir /var/log/fail2ban 'attr(0750,smelog,smelog)' \ + > %{name}-%{version}-filelist + +%files -f %{name}-%{version}-filelist +%defattr(-,root,root) + +%clean +rm -rf $RPM_BUILD_ROOT + +%post + +%preun +