Iptables

M
  • 21 Kov '12

sveiki, gal zinote kokia programele, kad butu galima matyti grafines vizualizacijas iptables rezultatu? ty log failiukuose esancius duomenis grafiskai kad atvaizduotu kas blokuota ir pan.

V
  • 21 Kov '12

Firestart, fwbuilder?

M
  • 22 Kov '12

@Vladasl rašė:
Firestart, fwbuilder?

sios programos berods skirtos konfiguravimui, o man reikia kad atvaizduotu jau ju veikimo rezultatus vaizdziai pateiktu esancius log faile, nupiestu kokia diagrama ar procentaliai parodytu is kiek norejusiu patekti paketu buvo blokuota ar praleista

T
Techtronic
Mindaugas N.
  • 22 Kov '12

Perl varijantas:

#!/usr/bin/perl
use strict;
use warnings;
my @types = qw/nat mangle filter/;
$SIG{INT} = sub{print "\e[?25h\e[u"; exit}; 
print "\e[40;37m\e[2J\e[?25l";
while (1) {
  print "\e[0;0H";
  my %output = map {$_ => scalar `/sbin/iptables -t $_ -L -v -Z`} @types;
  foreach my $type (@types) {
    print "\e[01;34m------", uc($type), '-' x (73 - length($type)), "\n";
    $output{$type} =~ s/ pkts[^\n]*\n(\n|Zeroing)/$1/gs;
    foreach my $line (split /\n/, $output{$type}) {
      next if $line =~ m/^Zeroing/ || $line eq '';
      print $line =~ m/^\s*(\d+)/ || $line =~ m/(\d+) packets/
        ? ($1 > 0 
          ? ($line =~ m/DROP|DENY|REJECT/
            ? "\e[01;40;31m" 
            : "\e[01;40;32m")
          : "\e[00;40;37m")
        : "\e[00;40;33m";
      print "\e[K$line\e[01;40;37m\n"
    }
  }
  print "\e[s";
  sleep 1
}

As pats naudoju Vuurmuur http://www.vuurmuur.org/trac/ paskaityk, gal ir tau patiks kaip ir man.
Esu sukures skripta ant python (aciu Sirex uz pagalba!) kuris naudoja Dbus notifications, jeigu iptables numeta prisijungima, matau grazu popup ant desktop su visa reikalinga informacija

M
  • 22 Kov '12

jei kas zino daugiau naudingu dalyku kaip wuurmuur (dekui ankstesniam posteriui), parasykit irgi

M
  • 22 Kov '12

o gal yra kokiu programeliu, kad pabraizytu iptables rezultatus is log failiuku grafiskai, na tarkim kokia diagrama nubreztu ar pan.

T
Techtronic
Mindaugas N.
  • 22 Kov '12

Gali su RRDtool http://oss.oetiker.ch/rrdtool/
Bet nemoku gauti statistika is iptables

sudo /sbin/iptables -nvx -L INPUT | awk '/Chain INPUT/{print $7}'

Bet su tokia info nieko nepadarysi... Gali bandyti skaiciuoti rezultata pvz kiek per valanda uzblokavo packets ir panasiai.
Gal pravers kaip example bandant:

RRDTOOL='/usr/bin/rrdtool'
FILE='/home/minde/Projects/ipstatsping.rrd'
HOST='ubuntu.lt'
OUTPUT='/home/minde/Projects/ipstats/iptables.png'
# sukurti:
# $RRDTOOL create $FILE -s 60 \
# DS:ping:GAUGE:120:0:65535 \
# RRA:AVERAGE:0.5:1:2880

UPDATECMD=$(ping -c 3 -w 6 $HOST | grep rtt | awk -F "/" '{ print $5 }' )
$RRDTOOL update $FILE N:$UPDATECMD
$RRDTOOL graph $OUTPUT \
        -t "ubuntu.lt pingas" -v "Laikas ms" \
        --start="now-2h" \
        --end="now" \
        --height="100" \
        --width="250" \
        -c "BACK#000000" \
        -c "SHADEA#000000" \
        -c "SHADEB#000000" \
        -c "FONT#DDDDDD" \
        -c "CANVAS#202020" \
        -c "GRID#666666" \
        -c "MGRID#AAAAAA" \
        -c "FRAME#202020" \
        -c "ARROW#FFFFFF" \
        "DEF:ping_time=$FILE:ping:AVERAGE" \
        "CDEF:shading2=ping_time,0.98,*" "AREA:shading2#F90000:$HOST" \
        "GPRINT:ping_time:LAST:Last\: %5.2lf ms" \
        "GPRINT:ping_time:MIN:Min\: %5.2lf ms" \
        "GPRINT:ping_time:MAX:Max\: %5.2lf ms" \
        "GPRINT:ping_time:AVERAGE:Avg\: %5.2lf ms" \
        "CDEF:shading10=ping_time,0.90,*" "AREA:shading10#fe0004" \
        "CDEF:shading15=ping_time,0.85,*" "AREA:shading15#fe9400" \
        "CDEF:shading20=ping_time,0.80,*" "AREA:shading20#fed801" \
        "CDEF:shading25=ping_time,0.75,*" "AREA:shading25#d8fe00" \
        "CDEF:shading30=ping_time,0.70,*" "AREA:shading30#aefe00" \
        "CDEF:shading35=ping_time,0.65,*" "AREA:shading35#3bfe00" \
        "CDEF:shading40=ping_time,0.60,*" "AREA:shading40#00fe61" \
        "CDEF:shading45=ping_time,0.55,*" "AREA:shading45#00feba" \
        "CDEF:shading50=ping_time,0.50,*" "AREA:shading50#00f6fe" \
        "CDEF:shading55=ping_time,0.45,*" "AREA:shading55#00b6fe" \
        "CDEF:shading60=ping_time,0.40,*" "AREA:shading60#005dfe" \
        "CDEF:shading65=ping_time,0.35,*" "AREA:shading65#001dfe" \
        "CDEF:shading70=ping_time,0.30,*" "AREA:shading70#2a00fe" \
        "CDEF:shading75=ping_time,0.25,*" "AREA:shading75#2a00fe" \
        "CDEF:shading80=ping_time,0.20,*" "AREA:shading80#2a00fe" \
        "CDEF:shading85=ping_time,0.15,*" "AREA:shading85#2a00fe" >/dev/null

Atrodo taip

S
starka
don Pedrilio
  • 23 Kov '12

As pats naudoju Vuurmuur http://www.vuurmuur.org/trac/ paskaityk, gal ir tau patiks kaip ir man.
Esu sukures skripta ant python (aciu Sirex uz pagalba!) kuris naudoja Dbus notifications, jeigu iptables numeta prisijungima, matau grazu popup ant desktop su visa reikalinga informacija

gal galima pasidalinti skriptuku?

T
Techtronic
Mindaugas N.
  • 26 Kov '12

@starka rašė:
gal galima pasidalinti skriptuku?

Taip, bet keli perspejimai
Turi tureti ne syslogd o rsyslog (The enhanced syslogd for Linux and Unix rsyslog) http://www.rsyslog.com/ . Rsyslog config (vuurmuur):

:msg, contains, "vrmr: " -/var/log/iptables.log

Iptables tinkamai nustatytos.
Skriptas neturi limito, pvz jeigu numete 100 packets tai visus ir matysi ant desktop. Ir jis nera normaliai baigtas, reikia pataisyti regex ir panasiai...
Atrodo taip:

#!/usr/bin/python
import os
import time
#import subprocess
import ConfigParser
import re
import sys
import dbus

item = ('org.freedesktop.Notifications')
path = ('/org/freedesktop/Notifications')
interface = ('org.freedesktop.Notifications')
bus = dbus.SessionBus()
notif = bus.get_object(item, path)
notify = dbus.Interface(notif, interface)
config = ConfigParser.ConfigParser()
config.read("/home/minde/Projects/fw/config.ini")
log = config.get("config", "log")
file = open(log,'r')
st_results = os.stat(log)
st_size = st_results[6]
file.seek(st_size)

def extract(log):
    empty = "NULL"
    dict = {'time':empty, 'label':empty, 'info':empty, 'in':empty, 'mac':empty, 'out':empty, 'src':empty, 'spt':empty, 'dst':empty, 'tos':empty, 'prec':empty, 'ttl':empty, 'proto':empty, 'dpt':empty, 'df':empty, 'mf':empty, 'ce':empty, 'urg':empty, 'psh':empty, 'rst':empty, 'fin':empty, 'syn':empty, 'res':empty, 'id':empty, 'urgp':empty,'frag':empty,'window':empty, 'len':empty, 'proto':empty}
    match = re.search('[0-9]+-[0-9]+-[0-9]+\w+[0-9]+:[0-9]+:[0-9]+', log)
    if match!=None: dict["time"]=match.group(0).replace('T', ' ')[0:]
    match = re.search('RETURN|QUEUE|DROP|ACCEPT', log)
    if match!=None: dict["label"]=match.group(0)[0:]
    match = re.search('(RETURN|QUEUE|DROP|ACCEPT)(?:\W+\w+){0,6}?\W+(IN)', log)
    if match!=None: dict["info"]=match.group(0).replace(' IN', '')[5:]
    match = re.search('IN\=[a-z0-9]+', log)
    if match!=None: dict["in"]=match.group(0)[3:]
    match = re.search('MAC\=[a-z:0-9]+', log)
    if match!=None: dict["mac"]=match.group(0)[4:]
    match = re.search('OUT\=([0-9]+\.){3}[0-9]+', log)
    if match!=None: dict["out"]=match.group(0)[4:]
    match = re.search('SRC\=([0-9]+\.){3}[0-9]+', log)
    if match!=None: dict["src"]=match.group(0)[4:]
    match = re.search('DST\=([0-9]+\.){3}[0-9]+', log)
    if match!=None: dict["dst"]=match.group(0)[4:]
    match = re.search('TOS\=[a-z0-9]+', log)
    if match!=None: dict["tos"]=match.group(0)[4:]
    match = re.search('PREC\=[a-z0-9]+', log)
    if match!=None: dict["prec"]=match.group(0)[5:]
    match = re.search('TTL\=[0-9]+', log)
    if match!=None: dict["ttl"]=match.group(0)[4:]
    match = re.search('PROTO\=[A-Z0-9]+', log)
    if match!=None: dict["proto"]=match.group(0)[6:]
    match = re.search('SPT\=[0-9]+', log)
    if match!=None: dict["spt"]=match.group(0)[4:]
    match = re.search('DPT\=[0-9]+', log)
    if match!=None: dict["dpt"]=match.group(0)[4:]
    match = re.search('URGP\=[0-9]+', log)
    if match!=None: dict["urgp"]=match.group(0)[5:]
    match = re.search('FRAG\=[0-9]+', log)
    if match!=None: dict["frag"]=match.group(0)[5:]
    match = re.search('DF', log)
    if match!=None: dict["df"]=match.group(0)[0:]
    match = re.search('CE', log)
    if match!=None: dict["ce"]=match.group(0)[0:]
    match = re.search('MF', log)
    if match!=None: dict["mf"]=match.group(0)[0:]
    match = re.search('URG', log)
    if match!=None: dict["urg"]=match.group(0)[0:]
    match = re.search('PSH', log)
    if match!=None: dict["psh"]=match.group(0)[0:]
    match = re.search('RST', log)
    if match!=None: dict["rst"]=match.group(0)[0:]
    match = re.search('FIN', log)
    if match!=None: dict["fin"]=match.group(0)[0:]
    match = re.search('SYN', log)
    if match!=None: dict["syn"]=match.group(0)[0:]
    match = re.search('RES\=[a-z0-9]+', log)
    if match!=None: dict["res"]=match.group(0)[4:]
    match = re.search('ID\=[0-9]+', log)
    if match!=None: dict["id"]=match.group(0)[3:]
    match = re.search('WINDOW\=[0-9]+', log)
    if match!=None: dict['window']=match.group(0)[7:]
    return dict

while 1:
    where = file.tell()
    line = file.readline()
    if not line:
        time.sleep(.1)
        file.seek(where)
    else:
        naughty = extract(line)
        #subprocess.call(['/home/minde/bin/fw', line])
        if naughty['label'] == 'DROP':
            label = '<span color="#985336">DROP</span>'
        elif naughty['label'] == 'ACCEPT':
            label = '<span color="#009A24">ACCEPT</span>'
        elif naughty['label'] == 'QUEUE':
            label = '<span color="#ECB11C">QUEUE</span>'
        elif naughty['label'] == 'RETURN':
            label = '<span color="#EC1CE6">RETURN</span>'
        title = '<span color="#28A6F4">' + naughty['info'] + '</span>'
        timep = '<span color="#618295">' + naughty['time'] + '</span>'
        net_in = 'IN=<span color="#2F91CD">' + naughty['in']  + '</span>'
        net_out = 'OUT=<span color="#36912C">' + naughty['out'] + '</span>'
        net_mac = 'MAC=<span color="#357C60">' + naughty['mac'] + '</span>'
        net_src = 'SRC=<span color="#3D84AB">' + naughty['src'] + '</span>'
        net_dst = 'DST=<span color="#3D84AB">' + naughty['dst'] + '</span>'
        net_len = 'LEN=<span color="#3D84AB">' + naughty['len'] + '</span>' # TODO kartais len pakartoja 2 kartus
        net_tos = 'TOS=<span color="#3D84AB">' + naughty['tos'] + '</span>'
        net_prec = 'PREC=<span color="#3D84AB">' + naughty['prec'] + '</span>'
        net_ttl = 'TTL=<span color="#3D84AB">' + naughty['ttl'] + '</span>'
        net_id = 'ID=<span color="#3D84AB">' + naughty['id'] + '</span>'
        if naughty['res'] != "NULL":
            net_res = ' RES=<span color="#3D84AB">' + naughty['res'] + '</span>'
        else:
            net_res = ''
        if naughty['window'] != "NULL":
            net_window = 'WINDOW=<span color="#3D84AB">' + naughty['window'] + '</span>'
        else:
            net_window = ''
        if naughty['psh'] != "NULL":
            net_psh = ' <span color="#31DA13"><b>' + naughty['psh'] + '</b></span>'
        else:
            net_psh = ''
        if naughty['rst'] != "NULL":
            net_rst = ' <span color="#C3DA13"><b>' + naughty['rst'] + '</b></span>'
        else:
            net_rst = ''
        if naughty['syn'] != "NULL":
            net_syn = ' <span color="#DA3D13"><b>' + naughty['syn'] + '</b></span>'
        else:
            net_syn = ''
        if naughty['fin'] != "NULL":
            net_fin = ' <span color="#DA1362"><b>' + naughty['fin'] + '</b></span>'
        else:
            net_fin = ''
        if naughty['urg'] != "NULL":
            net_urg = ' <span color="#994CFE"><b>' + naughty['urg'] + '</b></span>'
        else:
            net_urg = ''
        if naughty['proto'] == 'TCP':
            net_proto = 'PROTO=<span color="#C95D58">TCP</span>'
        elif naughty['proto'] == 'UDP':
            net_proto = 'PROTO=<span color="#009A24">UDP</span>'
        elif naughty['proto'] == 'ICMP':
            net_proto = 'PROTO=<span color="#E4BD1B">ICMP</span>'
        else:
            net_proto = 'PROTO=<span color="#FF1500">' + naughty['proto'] + '</span>'
        net_spt = 'SPT=<span color="#007FFF"><b>' + naughty['spt'] + '</b></span>'
        net_dpt = 'DPT=<span color="#007FFF"><b>' + naughty['dpt'] + '</b></span>'
        if naughty['ce'] != "NULL":
            net_ce  = ' <span color="#7B9A36"><b>' + naughty['ce'] + '</b></span>'
        else:
            net_ce = ''
        if naughty['df'] != "NULL":
            net_df = ' <span color="#9A6636"><b>' + naughty['df'] + '</b></span>'
        else:
            net_df = ''
        if naughty['mf'] != "NULL":
            net_mf = ' <span color="#7C3544"><b>' + naughty['mf'] + '</b></span>'
        else:
            net_mf = ''
        if naughty['frag'] != "NULL":
            net_frag = 'FRAG=<span color="#369A43"><b>' + naughty['frag'] + '</b></span>'
        else:
            net_frag = ''

        naughty_icon = ''
        naughty_array = ''
        naughty_hint = ''
        naughty_time = 50000   # Use seconds x 1000
        naughty_app_name = ('Test Application')
        naughty_title = ('FW: ' + label + ' - ' + title)
        naughty_body = (timep + ' ' + net_in + ' ' + net_out + '\n' +
                        net_mac + '\n' +
                        net_src + ' ' + net_dst + ' ' + net_len + '\n' +
                        net_tos + ' ' + net_prec + ' ' + net_ttl + ' ' + net_id + net_ce + net_df + net_mf + net_frag + '\n' +
                        net_proto + ' ' + net_spt + ' ' + net_dpt + '\n' +                       # TODO: SEQ=0123456789 | ACK=0
                        net_window + net_res + net_urg + net_psh + net_rst + net_syn + net_fin   # TODO: ACK | URGP=0 ...
                        )
        print(naughty_body)
        notify.Notify(naughty_app_name, 0, naughty_icon, naughty_title, naughty_body, naughty_array, naughty_hint, naughty_time)

# FW: DROP "All in"
# +--------------------------------------------------------------------------+
# | Apr 16 00:30:45 megahard kernel: | NF: D(I,Priv) | IN=eth1 | OUT=        |
# +--------------------------------------------------------------------------+
# | MAC=00:80:8c:1e:12:60:00:10:76:00:2f:c2:08:00                            |
# +--------------------------------------------------------------------------+
# | SRC=211.251.142.65 | DST=203.164.4.223 | LEN=60                          |
# +--------------------------------------------------------------------------+
# | TOS=0x00 | PREC=0x00 | TTL=44  | ID=31526 | CE | DF | MF | FRAG=179      |
# +--------------------------------------------------------------------------+
# | PROTO=TCP | SPT=4515  | DPT=111  | SEQ=1168094040 | ACK=0                  |
# +--------------------------------------------------------------------------+
# | WINDOW=32120 | RES=0x03 | URG | ACK | PSH | RST | SYN | FIN | URGP=0     |    
# +--------------------------------------------------------------------------+
# IN=eth0                    Interface the packet was received from. Empty value for locally generated packets.
# OUT=                          Interface the packet was sent to. Empty value for locally received packets.
# MAC=
#     00:80:8c:1e:12:60:      Destination MAC=00:80:8c:1e:12:60,
#     00:10:76:00:2f:c2:      Source MAC=00:10:76:00:2f:c2,
#     08:00                   Type=08:00 (ethernet frame carried an IPv4 datagram)
# SRC=211.251.142.65          Source IP address
# DST=203.164.4.223          Destination IP address
# LEN=60                  Total length of IP packet in bytes
# TOS=0x00                  Type Of Service, "Type" field. Increasingly being replaced by DS and ECN.
# PREC=0x00                  Type Of Service, "Precedence" field. Increasingly being replaced by DS and ECN.
# TTL=44                  remaining Time To Live is 44 hops.
# ID=31526                  Unique ID for this IP datagram, shared by all fragments if fragmented.
# CE                          Presumably the "ECN CE" flag (Congestion Experienced).
#                              This seems to be wrong because according to RFC2481, 
#                              the CE bit is located in the TOS field.
# DF                          "Don't Fragment" flag.
# MF                          "More Fragments following" flag.
# FRAG=179                  Fragment offset in units of "8-bytes". In this case the byte 
#                              offset for data in this packet is 179*8=1432 bytes.
# OPT                        (0727..A200)     Enabled with: --log-ip-options
#                              IP options. This variable length field is rarely used. 
#                              Certain IP options, f.e. source routing, are often disallowed by netadmins. 
#                            Even harmless options like "Record Route" may only be allowed 
#                              if the transport protocol is ICMP, or not at all.
# PROTO=TCP                  Protocol name or number. Netfilter uses names for TCP, UDP, ICMP, AH and ESP. 
#                              Other protocols are identified by number. A list is in your /etc/protocols.  
#                              A complete list is in the file protocol-numbers
# SPT=4515                  Source port (TCP and UDP).  A list of port numbers is in your /etc/services.  
#                              A complete list is in the file port-numbers
# DPT=111                  Destination port (TCP and UDP).  See SPT above.
# SEQ=1168094040          Enabled with: --log-tcp-sequence
#                              Receive Sequence number. By cleverly chosing this number, 
#                              a cryptographic "cookie" can be implemented while still satisfying TCP protocol 
#                              requirements. These "SYN-cookies" defeat some types of SYN-flooding DoS attacks 
#                              and should be enabled on all systems running public TCP servers.
#                              echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# ACK=0                  Same as the Receive Sequence number, but for the other end of the TCP connection.
# WINDOW=32120                  The TCP Receive Window size. This may be scaled by bit-shifting left by a number 
#                              of bits specified in the "Window Scale" TCP option. If the host supports ECN, 
#                              then the TCP Receive Window size will also be controlled by that.
# RES=0x03                  Reserved bits. The ECN flags "CWR" and "ECNE" will show up in the two least 
#                              significant bits of this field.
# URG                          Urgent flag.   See URGP below.
# ACK                          Acknowledgement flag.
# PSH                          Push flag.
# RST                          RST (Reset) flag.
# SYN                          SYN flag, only exchanged at TCP connection establishment.
# FIN                          FIN flag, only exchanged at TCP disconnection.
# URGP=0                  The Urgent Pointer allows for urgent, "out of band" data transfer. Unfortunately 
#                              not all protocol implementations agree, so this facility is hardly ever used.
# OPT (020405...300)          enabled with: --log-tcp-options
#                              TCP options. This variable length field gets a lot of use. 
#                              Important options include: Window Scaling, 
#                              Selective Acknowledgement and Explicit Congestion Notification.

# Unfortunately the rule number in the chain which matched the packet is for architectural reasons 
# not available in netfilter logs. You will have to "cook your own" by using the user-prefix feature.

config.ini

[config]
log: /var/log/iptables.log
interval: 50

Ideja paprasta, skriptas kuris siuncia maila su informacija apie numestus prisijungimus. Radau alternatyva - file2ban, todel skriptas liko nebaigtas.

T
Techtronic
Mindaugas N.
  • 26 Kov '12

Oops, as tik dabar pastebejau, kad tema yra "pradedantiesiems". Gal kas is moderatoriu gali perkelti i "Programinės įrangos naudojimas"? Aciu!