Hetzner - DokuWiki

Port Traffic Accounting

Inhaltsverzeichnis

HowTo: Port-Traffic-Accounting

iptable Script abändern

Original Firewall Script erzeugt mit dem IPTables-Skript-Generator von Tobias Bauer.
Hier habe ich jetzt mal Regeln für FTP, SSH, HTTP, SMTP und POP3 erstellt.


  1 #!/bin/sh
  2
  3 #####################################################
  4 # IPTables Firewall-Skript                          #
  5 #                                                   #
  6 # erzeugt mit dem IPTables-Skript-Generator auf     #
  7 #      tobias-bauer.de - Version 0.2                #
  8 # URL: http://linux.tobias-bauer.de/iptables.html #
  9 #                                                   #
 10 # Autor: Tobias Bauer                               #
 11 # E-Mail: exarkun@ist-root.org                      #
 12 #                                                   #
 13 # Das erzeugte Skript steht unter der GNU GPL!      #
 14 #                                                   #
 15 # ACHTUNG! Die Benutzung des Skriptes erfolgt auf   #
 16 # eigene Gefahr! Ich übernehme keinerlei Haftung    #
 17 # für Schäden die durch dieses Skript entstehen!    #
 18 #                                                   #
 19 #####################################################
 20
 21 # iptables suchen
 22 iptables=`which iptables`
 23
 24 # wenn iptables nicht installiert abbrechen
 25 test -f $iptables || exit 0
 26
 27 case "$1" in
 28    start)
 29       echo "Starte Firewall..."
 30       # alle Regeln löschen
 31       $iptables -t nat -F
 32       $iptables -t filter -F
 33       $iptables -X
 34
 35       # neue Regeln erzeugen
 36       $iptables -N garbage
 37       $iptables -I garbage -p TCP -j LOG --log-prefix="DROP TCP-Packet: " --log-level err
 38       $iptables -I garbage -p UDP -j LOG --log-prefix="DROP UDP-Packet: " --log-level err
 39       $iptables -I garbage -p ICMP -j LOG --log-prefix="DROP ICMP-Packet: " --log-level err
 40
 41       # Default Policy
 42       $iptables -P INPUT DROP
 43       $iptables -P OUTPUT DROP
 44       $iptables -P FORWARD DROP
 45
 46       # über Loopback alles erlauben
 47       $iptables -I INPUT -i lo -j ACCEPT
 48       $iptables -I OUTPUT -o lo -j ACCEPT
 49
 50       #####################################################
 51       # ausgehende Verbindungen
 52       # Port 21
 53       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 21 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 54       $iptables -I INPUT -i eth0 -p TCP --sport 21 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 55       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 20 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 56       $iptables -I INPUT -i eth0 -p TCP --sport 20 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 57       # Port 22
 58       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 59       $iptables -I INPUT -i eth0 -p TCP --sport 22 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 60       # Port 25
 61       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 25 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 62       $iptables -I INPUT -i eth0 -p TCP --sport 25 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 63       # Port 80
 64       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 65       $iptables -I INPUT -i eth0 -p TCP --sport 80 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 66       # Port 110
 67       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 110 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 68       $iptables -I INPUT -i eth0 -p TCP --sport 110 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 69       # ICMP
 70       $iptables -I OUTPUT -o eth0 -p ICMP --icmp-type echo-request -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 71       $iptables -I INPUT -i eth0 -p ICMP --icmp-type echo-request -m state --state ESTABLISHED,RELATED -j ACCEPT
 72
 73       #####################################################
 74       # eingehende Verbindungen
 75       # Port 21
 76       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 21 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 77       $iptables -I OUTPUT -o eth0 -p TCP --sport 21 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 78       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 1024:65535 -m state --state NEW -j ACCEPT
 79       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 20 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 80       $iptables -I OUTPUT -o eth0 -p TCP --sport 20 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 81       # Port 22
 82       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 83       $iptables -I OUTPUT -o eth0 -p TCP --sport 22 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 84       # Port 25
 85       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 25 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 86       $iptables -I OUTPUT -o eth0 -p TCP --sport 25 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 87       # Port 80
 88       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 89       $iptables -I OUTPUT -o eth0 -p TCP --sport 80 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 90       # Port 110
 91       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 110 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 92       $iptables -I OUTPUT -o eth0 -p TCP --sport 110 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
 93       # ICMP
 94       $iptables -I INPUT -i eth0 -p ICMP --icmp-type echo-request -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
 95       $iptables -I OUTPUT -o eth0 -p ICMP --icmp-type echo-request -m state --state ESTABLISHED,RELATED -j ACCEPT
 96
 97       #####################################################
 98       # Erweiterte Sicherheitsfunktionen
 99
100       #####################################################
101       # bestehende Verbindungen akzeptieren
102       $iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
103       $iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
104
105       #####################################################
106       # Garbage übergeben wenn nicht erlaubt
107       $iptables -A INPUT -m state --state NEW,INVALID -j garbage
108
109       #####################################################
110       # alles verbieten was bisher erlaubt war
111       $iptables -A INPUT -j garbage
112       $iptables -A OUTPUT -j garbage
113       $iptables -A FORWARD -j garbage
114       ;;
115    stop)
116       echo "Stoppe Firewall..."
117       $iptables -t nat -F
118       $iptables -t filter -F
119       $iptables -X
120       $iptables -P INPUT ACCEPT
121       $iptables -P OUTPUT ACCEPT
122       $iptables -P FORWARD ACCEPT
123       ;;
124    *)
125       echo "Usage: /etc/init.d/firewall (start|stop)"
126       exit 1
127       ;;
128 esac
129 exit 0


Um jetzt überhaupt den Traffic in einzelnen Gruppen einteilen zu können,
müssen wir erstmal eigene Chains erstellen.
Unter Zeile 39 tun wir dies:


35       # neue Regeln erzeugen
36       $iptables -N garbage
37       $iptables -I garbage -p TCP -j LOG --log-prefix="DROP TCP-Packet: " --log-level err
38       $iptables -I garbage -p UDP -j LOG --log-prefix="DROP UDP-Packet: " --log-level err
39       $iptables -I garbage -p ICMP -j LOG --log-prefix="DROP ICMP-Packet: " --log-level err
40       $iptables -N ssh
41       $iptables -A ssh -j ACCEPT
42       $iptables -N web
43       $iptables -A web -j ACCEPT
44       $iptables -N mail
45       $iptables -A mail -j ACCEPT
46       $iptables -N ftp
47       $iptables -A ftp -j ACCEPT


So, die neuen Chains sind erstellt. Diese Chains sind eigentlich nur ein kleiner Umweg.
Statt direkt zu ACCEPT zu springen, gehen die Pakete erst in die zugehörige Chain, werden dort gezählt,
und dann gehen sie zu ACCEPT.

Jetzt müssen nur noch die eigentlichen Regeln angepasst werden:
(Zeilennummerierung geht vom eigentlichen Script aus)


60       # Port 25
61       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 25 -m state --state NEW,ESTABLISHED,RELATED -j mail
62       $iptables -I INPUT -i eth0 -p TCP --sport 25 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j mail
63       # Port 80
64       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j web
65       $iptables -I INPUT -i eth0 -p TCP --sport 80 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j web
66       # Port 110
67       $iptables -I OUTPUT -o eth0 -p TCP --sport 1024:65535 --dport 110 -m state --state NEW,ESTABLISHED,RELATED -j mail
68       $iptables -I INPUT -i eth0 -p TCP --sport 110 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j mail

84       # Port 25
85       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 25 -m state --state NEW,ESTABLISHED,RELATED -j mail
86       $iptables -I OUTPUT -o eth0 -p TCP --sport 25 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j mail
87       # Port 80
88       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j web
89       $iptables -I OUTPUT -o eth0 -p TCP --sport 80 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j web
90       # Port 110
91       $iptables -I INPUT -i eth0 -p TCP --sport 1024:65535 --dport 110 -m state --state NEW,ESTABLISHED,RELATED -j mail
92       $iptables -I OUTPUT -o eth0 -p TCP --sport 110 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j mail


Hier wird nur als Ziel die neue Chain eingetragen (statt ACCEPT).
Man kann soviele Ports in auf eine Chain legen wie man möchte.`

Nun sollte man mit `iptables -vnx -L --line-numbers -t filter` die Verschiedenen Chains und
den dort angefallene Traffic sehen:

(Auszug)


Chain fail2ban-ssh (1 references)
num      pkts      bytes target     prot opt in     out     source               destination
1       14226  1170588 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
Chain garbage (4 references)
num      pkts      bytes target     prot opt in     out     source               destination
1          48     8484 LOG        icmp --  *      *       0.0.0.0/0            0.0.0.0/0           LOG flags 0 level 3 prefix `DROP ICMP-Packet: '
2        1275   464585 LOG        udp  --  *      *       0.0.0.0/0            0.0.0.0/0           LOG flags 0 level 3 prefix `DROP UDP-Packet: '
3         600    38146 LOG        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           LOG flags 0 level 3 prefix `DROP TCP-Packet: '
Chain mail (16 references)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0
Chain ssh (4 references)
num      pkts      bytes target     prot opt in     out     source               destination
1        1024   115028 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0
Chain web (4 references)
num      pkts      bytes target     prot opt in     out     source               destination
1         159    75949 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0


Daten dumpen

Diese Daten werden jetzt mit dem folgenden Script in die eine mysqlDB eingetragen:
Die Chains INPUT, FORWARD, OUTPUT, garbage und fail2ban-ssh werden nicht berücksichtigt.


#!/bin/bash
#####################################################
# Dump-Script for Port Traffic Accounting           #
# Filename: dump-traffic.sh                         #
#                                                   #
# Autor: Christoph Zölß / Deltaflyer                #
# E-Mail: deltaflyer@ki-ba.net                      #
#                                                   #
# Dieses Script steht unter der GNU GPL!            #
#                                                   #
# Benutzung das Scriptes auf eigene Gefahr.         #
#                                                   #
#####################################################
#crontab Eintrag:
#00 *    * * *   root    /path/to/dump-traffic.sh
# Database Name
DB="traffic"
# Database User
DBUSER="traffic"
# Passwort for DB User
DBPW='secret'
# Table for Traffic Data
DBTABLE="traffic"
### (should be) no need to change something below ###
DATE=`date +%s`
YEAR=`date +%Y`
MONTH=`date +%m`
DAY=`date +%d`
HOUR=`date +%H`


CHAINS=`iptables -vnx -L --line-numbers -t filter | grep Chain | grep -v -e INPUT -e FORWARD -e OUTPUT -e garbage -e fail2ban-ssh | awk '{ print $2 }'`
for i in `echo $CHAINS`; do
    BYTES=`iptables -vnxZ -L $i --line-numbers -t filter | tail -n2 | head -n12 | head -n1 | awk '{ print $3 }'`
    sql1="insert into $DBTABLE (year, month, day, hour, cat, bytes) VALUES ('$YEAR', '$MONTH', '$DAY', '$HOUR', '$i', '$BYTES')"
    echo $sql1 | mysql -u$DBUSER -p$DBPW -D$DB
done


Hier muss man nur noch die DB Variablen anpassen und einen Eintrag in der Crontab machen,
sodass das Script jede Stunde einmal ausgeführt wird.

Hier noch das Tabellen Layout und zwei Views für MySQL 5.0:

Tabellen Layout.


CREATE TABLE  `traffic`.`traffic` (
  `year` year(4) NOT NULL default '0000',
  `month` tinyint(2) unsigned zerofill NOT NULL default '00',
  `day` tinyint(2) unsigned zerofill NOT NULL default '00',
  `hour` tinyint(2) unsigned zerofill NOT NULL default '00',
  `cat` varchar(45) NOT NULL default ,
  `bytes` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`year`,`month`,`day`,`hour`,`cat`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


Traffic This Day.


CREATE ALGORITHM=UNDEFINED DEFINER=`traffic`@`localhost` SQL SECURITY DEFINER VIEW  `traffic`.`Traffic_ThisDay` AS
select sql_no_cache concat(`traffic`.`day`,_utf8'.',`traffic`.`month`,_utf8'.',`traffic`.`year`) AS `Date`,
`traffic`.`cat` AS `Kategorie`,
((sum(`traffic`.`bytes`) / 1024) / 1024) AS `Traffic (MB)`
from `traffic`
where ((`traffic`.`day` = date_format(curdate(),_utf8'%d'))
and (`traffic`.`month` = date_format(curdate(),_utf8'%m'))
and (`traffic`.`year` = date_format(curdate(),_utf8'%Y')))
group by `traffic`.`cat`;


Traffic This Month:


CREATE ALGORITHM=UNDEFINED DEFINER=`traffic`@`localhost` SQL SECURITY DEFINER VIEW  `traffic`.`Traffic_ThisMonth` AS
select sql_no_cache concat(`traffic`.`month`,_utf8'.',`traffic`.`year`) AS `Month`,
`traffic`.`cat` AS `Kategorie`,
((sum(`traffic`.`bytes`) / 1024) / 1024) AS `Traffic (MB)`
from `traffic`
where ((`traffic`.`month` = date_format(curdate(),_utf8'%m'))
and (`traffic`.`year` = date_format(curdate(),_utf8'%Y')))
group by `traffic`.`cat`;


Das Munin Plugin

So, und jetzt noch mein Munin Plugin ;)


#!/usr/bin/perl
#####################################################
# Munin Plugin for Port Traffic Accounting          #
# Filename: trafacc                                 #
#                                                   #
# Autor: Christoph Zölß / Deltaflyer                #
# E-Mail: deltaflyer@ki-ba.net                      #
#                                                   #
# Dieses Script steht unter der GNU GPL!            #
#                                                   #
# Benutzung das Scriptes auf eigene Gefahr.         #
#                                                   #
#####################################################
use DBI;
# Database Name and Host
my $db = 'DBI:mysql:traffic:localhost';
# Database User
my $db_user_name = 'traffic';
# Passwort for DB User
my $db_password = 'secret';


my ($cat, $bytes);
my $dbcon = DBI->connect($db, $db_user_name, $db_password);
($day, $month, $year, $hour) = (localtime)[3,4,5,2];
$year = $year+1900;
$month = $month+1;
my $sql1 = $dbcon->prepare(qq{
   select cat, bytes from traffic where year = $year and month = $month and day = $day and hour = $hour
   });
$sql1->execute();
if ($ARGV[0] and $ARGV[0] eq "config") {
    print "graph_title Port Traffic Accounting\n";
    print "graph_args --base 1024 -l 1\n";
    print "graph_category Network\n";
    print "graph_vlabel Bytes\n";
    while (my ($cat, $bytes) = $sql1->fetchrow_array())
    {
       print "$cat.label $cat\n";
    }
    exit 0;
}
while (my ($cat, $bytes) = $sql1->fetchrow_array())
{
   print "$cat.value $bytes\n";
}
$sql1->finish;
$dbcon->disconnect();


Hier müssen auch wieder die Variablen analog zum dump-script angepasst werden.

Das sollte es dann sein.

Wenn ihr Fragen / Wünsche / Anregungen habt, schickt mir ne Mail an
deltaflyer_AT_ki-ba_DOT_net

Deltaflyer 20:56, 14. Jun 2006 (CEST)



© 2016. Hetzner Online GmbH. Alle Rechte vorbehalten.