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)


