GIT repositories

Index page of all the GIT repositories that are clonable form this server via HTTPS. Übersichtsseite aller GIT-Repositories, die von diesem Server aus über git clone (HTTPS) erreichbar sind.

Services

A bunch of service scripts to convert, analyse and generate data. Ein paar Services zum Konvertieren, Analysieren und Generieren von Daten.

GNU octave web interface

A web interface for GNU Octave, which allows to run scientific calculations from netbooks, tables or smartphones. The interface provides a web form generator for Octave script parameters with pre-validation, automatic script list generation, as well presenting of output text, figures and files in a output HTML page. Ein Webinterface für GNU-Octave, mit dem wissenschaftliche Berechnungen von Netbooks, Tablets oder Smartphones aus durchgeführt werden können. Die Schnittstelle beinhaltet einen Formulargenerator für Octave-Scriptparameter, mit Einheiten und Einfabevalidierung. Textausgabe, Abbildungen und generierte Dateien werden abgefangen und in einer HTML-Seite dem Nutzer als Ergebnis zur Verfügung gestellt.

Länder blocken mit GeoIP und iptables unter Ubuntu

Blocking countries using GeoIP and iptables on Ubuntu

Um meine Firewall Logs ein wenig zu filtern (und da die meisten Attacken nicht aus Europa kommen) habe ich auf meinem Ubuntu mal die xtables addons installiert, um nach geoip einen Vorfilter definieren zu können. Leider war es mit aptitude install xtables-addons-common nicht getan, denn die Lookup-Dateien haben noch gefehlt. Nach ein wenig Googlen (Referenzen weiter unten angegeben) ergab sich dieses Updatescript (falls es jemand brauchen kann):

Setup

Die zu kopierenden Skripte sind weiter unten gelistet.

To filter my firewall logs a bit (and as the most attacks don't come from European countries in my case) I used the xtables extension for iptables filtering on my Ubuntu 11.10 home server. Unfortunately the setup was not done by just installing xtables-addons-common with aptitude, as the country IP database was missing. After some googling (references given below) I implemented a quick and dirty shell script to download and update it:

Setup

The files to copy are listed below.

sudo aptitude install xtables-addons-common libtext-csv-xs-perl
sudo mkdir /usr/share/xt_geoip
sudo cp update.sh /usr/share/xt_geoip
sudo cp xt_geoip_build.pl /usr/share/xt_geoip
sudo . /usr/share/xt_geoip/update.sh
xt_geoip
├── BE
│   ├── A1.iv4
.   .   ...
│   ├── ZW.iv4
│   └── ZW.iv6
├── LE
│   ├── A1.iv4
.   .   ...
│   └── ZW.iv6
├── dl
│   ├── GeoIPCountryCSV.zip
│   └── GeoIPv6.csv.gz
├── update.sh
└── xt_geoip_build.pl

3 directories, 1466 files

Beispiel

Hier werden einfach alle Anfragen (alle Ports), die nicht aus Deutschland, Frankreich oder Großbritannien kommen, ignoriert. Damit es keine Probleme im LAN gibt (sollte eigentlich nicht sein), schieben wir noch ein accept fürs LAN an erste Stelle. Die UFW ist dadurch nicht beeinflusst, außer dass bereits vorgefilterte Anfragen reinkommen.

Example

Block all incoming traffic not coming from Germany, France or Great Britain. To prevent trouble during the setup, accept incoming from class C networks. We insert these rules at position 1 and 2, so that ufw filters are processed later on.

iptables -I INPUT 1 -s 192.168.0.0/24 -j ACCEPT
iptables -I INPUT 2 -m state --state NEW -m geoip ! --source-country DE,GB,FR -j DROP

Dateien

Der Pfad des xtables Addons ist hardcoded (/usr/share/xt_geoip). Die Lookup-Dateien müssen in den Unterverzeichnissen LE (little endian) und BE (big endian) stehen. Also habe ich das Update-Script und ein Hilfsscript (perl) in /usr/share/xt_geoip platziert (damit alles beisammen ist). Update.sh legt LE und BE an falls diese noch nicht existieren. Auch ein Download-Verzeichnis dl wird erstellt. Darin werden die komprimierten CSV IP Tabellen gespeichert. Diese sollte man auch nicht löschen, weil wget -N die Dateien nur herunterläd falls sie sich geändert haben, das spart den Jungs von www.maxmind.com Traffic. Das Perlsscript ist die Originaldatei aus den xtables-addons Quellen und hier nur als Deko nochmals gelistet.

Files

The paths for the xtables addon are hardcoded to /usr/share/xt_geoip. The lookup files have to be in the directories /usr/share/xt_geoip/BE (big endian) and /usr/share/xt_geoip/LE (little endian). So I placed the update script and an auxiliary build script in the base directory. The update script will generate a subdirectory dl, and the output directories LE and BE if not existing yet. The perl script is the original conversion script of the xtables-addons source and just listed here for convenience.

update.sh

#/bin/sh
 
cd $(dirname $0) || exit 1;
BASE_DIR=$(pwd);
DL_DIR=$BASE_DIR/dl
 
mkdir -p $DL_DIR >/dev/null 2>&1
cd $DL_DIR || exit 1;
 
# Get data (only if modified)
wget -N http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz || exit 1;
wget -N http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip || exit 1;
 
if [ -f GeoIPv6.csv.gz ]; then
  rm GeoIPv6.csv >/dev/null 2>&1
  gzip -dc GeoIPv6.csv.gz > GeoIPv6.csv || exit 1;
fi
 
if [ -f GeoIPCountryCSV.zip ]; then
  rm  GeoIPCountryWhois.csv >/dev/null 2>&1
  unzip GeoIPCountryCSV.zip >/dev/null || exit 1;
fi
 
echo "Building ..."
cat *.csv | perl $BASE_DIR/xt_geoip_build.pl -D $DL_DIR || exit 1;
rm *.csv
 
echo "Copying to $BASE_DIR ..."
rm -rf $BASE_DIR/LE && mv -f $DL_DIR/LE $BASE_DIR/
rm -rf $BASE_DIR/BE && mv -f $DL_DIR/BE $BASE_DIR/
 
echo "Ready."

xt_geoip_build.pl

#!/usr/bin/perl
#
#   Converter for MaxMind CSV database to binary, for xt_geoip
#   Copyright © Jan Engelhardt <jengelh@medozas.de>, 2008-2011
#
#   Use -b argument to create big-endian tables.
#
use Getopt::Long;
use IO::Handle;
use Text::CSV_XS; # or trade for Text::CSV
use strict;
 
my $csv = Text::CSV_XS->new({
    allow_whitespace => 1,
    binary => 1,
    eol => $/,
}); # or Text::CSV
my $target_dir = ".";
 
&Getopt::Long::Configure(qw(bundling));
&GetOptions(
    "D=s" => \$target_dir,
);
 
if (!-d $target_dir) {
    print STDERR "Target directory $target_dir does not exist.\n";
    exit 1;
}
foreach (qw(LE BE)) {
    my $dir = "$target_dir/$_";
    if (!-e $dir && !mkdir($dir)) {
        print STDERR "Could not mkdir $dir: $!\n";
        exit 1;
    }
}
 
&dump(&collect());
 
sub collect
{
    my %country;
 
    while (my $row = $csv->getline(*ARGV)) {
        if (!defined($country{$row->[4]})) {
            $country{$row->[4]} = {
                name => $row->[5],
                pool_v4 => [],
                pool_v6 => [],
            };
        }
        my $c = $country{$row->[4]};
        if ($row->[0] =~ /:/) {
            push(@{$c->{pool_v6}},
                 [&ip6_pack($row->[0]), &ip6_pack($row->[1])]);
        } else {
            push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]);
        }
        if ($. % 4096 == 0) {
            print STDERR "\r\e[2K$. entries";
        }
    }
 
    print STDERR "\r\e[2K$. entries total\n";
    return \%country;
}
 
sub dump
{
    my $country = shift @_;
 
    foreach my $iso_code (sort keys %$country) {
        &dump_one($iso_code, $country->{$iso_code});
    }
}
 
sub dump_one
{
    my($iso_code, $country) = @_;
    my($file, $fh_le, $fh_be);
 
    printf "%5u IPv6 ranges for %s %s\n",
        scalar(@{$country->{pool_v6}}),
        $iso_code, $country->{name};
 
    $file = "$target_dir/LE/".uc($iso_code).".iv6";
    if (!open($fh_le, "> $file")) {
        print STDERR "Error opening $file: $!\n";
        exit 1;
    }
    $file = "$target_dir/BE/".uc($iso_code).".iv6";
    if (!open($fh_be, "> $file")) {
        print STDERR "Error opening $file: $!\n";
        exit 1;
    }
    foreach my $range (@{$country->{pool_v6}}) {
        print $fh_be $range->[0], $range->[1];
        print $fh_le &ip6_swap($range->[0]), &ip6_swap($range->[1]);
    }
    close $fh_le;
    close $fh_be;
 
    printf "%5u IPv4 ranges for %s %s\n",
        scalar(@{$country->{pool_v4}}),
        $iso_code, $country->{name};
 
    $file = "$target_dir/LE/".uc($iso_code).".iv4";
    if (!open($fh_le, "> $file")) {
        print STDERR "Error opening $file: $!\n";
        exit 1;
    }
    $file = "$target_dir/BE/".uc($iso_code).".iv4";
    if (!open($fh_be, "> $file")) {
        print STDERR "Error opening $file: $!\n";
        exit 1;
    }
    foreach my $range (@{$country->{pool_v4}}) {
        print $fh_le pack("VV", $range->[0], $range->[1]);
        print $fh_be pack("NN", $range->[0], $range->[1]);
    }
    close $fh_le;
    close $fh_be;
}
 
sub ip6_pack
{
    my $addr = shift @_;
    $addr =~ s{::}{:!:};
    my @addr = split(/:/, $addr);
    my @e = (0) x 8;
    foreach (@addr) {
        if ($_ eq "!") {
            $_ = join(':', @e[0..(8-scalar(@addr))]);
        }
    }
    @addr = split(/:/, join(':', @addr));
    $_ = hex($_) foreach @addr;
    return pack("n*", @addr);
}
 
sub ip6_swap
{
    return pack("V*", unpack("N*", shift @_));
}

Referenzen

References