jablonka.czprosek.czf

freenet-router

Subversion Repositories:
[/] [trunk/] [freenet-router/] [etc/] [firewall/] [macguard] - Rev 2

Compare with Previous - Blame - Download


#! /bin/bash
# Firewall nove generace pro Czela Debian 3.1
# Autor: Mirek Slugen
# Spoluatori: Michal Perlik, Michal Vondracek, Jan Chmelensky, Adam Pribyl
# Vytvoreno: 06.11.2006
# Naposledy zmeneno: 08.2014
# Tento skript muzete volne sirit a upravovat.

# globální proměnná pro RO file systém
RO="no"

# ukončení macguarda
macguard_stop() {
    # Standardně jakýkoliv průchozí provoz skrze router povolíme
    $IPTABLES -P FORWARD ACCEPT

    # Vymažeme obsah všech tříd vytvořených pro macguarda
    $IPTABLES -F eth_accept
    $IPTABLES -t nat -F valid_mac_pre
    $IPTABLES -F valid_mac_fwd

    # předtím, než vymažeme třídy macguarda, musíme zrušit všechny pravidla na ně odkazující
    for I in `iptables -L FORWARD -n -v --line-numbers | grep eth_accept | grep all | grep -v spt | grep -v dpt | awk '{print $1}' | sort -r -n`; do
        $IPTABLES -D FORWARD $I
    done
    for I in `iptables -t nat -L PREROUTING -n -v --line-numbers | grep valid_mac_pre | grep all | grep -v spt | grep -v dpt | awk '{print $1}' | sort -r -n`; do
        $IPTABLES -t nat -D PREROUTING $I
    done

    # vymažeme další pravidla vytvořená macguardem
    for I in `iptables -L FORWARD -n -v --line-numbers | grep ACCEPT | grep all | grep -v spt | grep -v dpt | awk '{print $1}' | sort -r -n`; do
        $IPTABLES -D FORWARD $I
    done
    for I in `iptables -t nat -L PREROUTING -n -v --line-numbers | grep ACCEPT | grep all | grep -v spt | grep -v dpt | awk '{print $1}' | sort -r -n`; do
        $IPTABLES -t nat -D PREROUTING $I
    done

    # Smažeme všechny třídy vytvořené pro macguarda
    $IPTABLES -X eth_accept
    $IPTABLES -t nat -X valid_mac_pre
    $IPTABLES -X valid_mac_fwd
}

# krátkodobě do další aktualizace povolíme mac adresu, první je IP, druhá MAC
macguard_allow_user() {
    ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0

    if [ "$1" == "0" ]; then
        while true; do
            $IPTABLES -D FORWARD -s "$2" -j valid_mac_fwd 2>/dev/null
            [ "$?" != "0" ] && break
        done
        while true; do
            $IPTABLES -t nat -D PREROUTING -s "$2" -j valid_mac_pre 2>/dev/null
            [ "$?" != "0" ] && break
        done
    else
        $IPTABLES -t nat -L valid_mac_pre -n 1>/dev/null 2>/dev/null
        [ "$?" != "0" ] && return 0

        $IPTABLES -L valid_mac_fwd -n 1>/dev/null 2>/dev/null
        [ "$?" != "0" ] && return 0

        LINE_PRE=$((`$IPTABLES -t nat -L valid_mac_pre -n -v --line-numbers | grep MAC | awk '{print $1}' | tail -n 1` + 1))

        $IPTABLES -t nat -I valid_mac_pre $LINE_PRE -s "$2" -m mac --mac-source "$1" -j ACCEPT 2>/dev/null

        LINE_FWD=$((`$IPTABLES -L valid_mac_fwd -n -v --line-numbers | grep MAC | awk '{print $1}' | tail -n 1` + 1))

        $IPTABLES -I valid_mac_fwd $LINE_FWD -s "$2" -m mac --mac-source "$1" -j ACCEPT 2>/dev/null
    fi
}

# krátkodobě do další aktualizace zakážeme mac adresu
macguard_deny_user() {
    ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0

    if [ "$1" == "0" ]; then
        $IPTABLES -A FORWARD -s "$2" -j valid_mac_fwd
        $IPTABLES -t nat -A PREROUTING -s "$2" -j valid_mac_pre
    else
        while true; do
            $IPTABLES -t nat -D valid_mac_pre -s "$2" -m mac --mac-source "$1" -j ACCEPT 2>/dev/null
            [ "$?" != "0" ] && break
        done
        while true; do
            $IPTABLES -D valid_mac_fwd -s "$2" -m mac --mac-source "$1" -j ACCEPT 2>/dev/null
            [ "$?" != "0" ] && break
        done
    fi
}

macguard_load_conf() {
    local TYPE=""
    local IP=""
    local MAC=""

    # Zpracujeme konfigurační soubor
    while read TYPE MAC IP; do
        if [ "$TYPE" == "ALLOW" ]; then
            echo -n "Allowing mac $MAC with ip $IP..."
            macguard_allow_user "$MAC" "$IP"
            echo "done."
        elif [ "$TYPE" == "DENY" ]; then
            echo -n "Denying mac $MAC with ip $IP..."
            macguard_deny_user "$MAC" "$IP"
            echo "done."
        fi
    done < "/etc/firewall/macguard.conf"
}

# Otestujeme jestli je soubor moĹžnĂŠ uloĹžit, pokud ne, tak povolĂ­me zĂĄpis
# a nastavĂ­me RO na yes.
ro_test() {
    local F_EXIST="no"

    ( [ "$1" == "" ] || [ "$1" == "/" ] ) && return 0

    [ -e "$1" ] && F_EXIST="yes"

    touch "$1" 2>/dev/null

    if [ "$?" != "0" ]; then
        /usr/local/sbin/rw 1>/dev/null
        RO="yes"
    fi

    [ "$F_EXIST" != "yes" ] && rm -f "$1" 2>/dev/null
}

# Ukončení RO módu, pokud jsme disk odemkli, tak ho také zkusíme zamknout
ro_exit() {
    [ "$RO" != "yes" ] && return 0
    /usr/local/sbin/ro 1>/dev/null
    RO="no"
}

# hlavnĂ­ implementace macguarda
macguard_start() {
    # detekce rozhranĂ­ pro macguarda
    I="0"
    MACGUARD_DEV_YES=""
    MACGUARD_DEV_NO=""
    MACGUARD_DEV_DHCP=""
    while [ "$I" -lt 15 ]; do
        DEV=DEV${I}_IFACE
        DEV=${!DEV}
        MACGUARD_DEV=DEV${I}_MACGUARD
        MACGUARD_DEV=${!MACGUARD_DEV}
        MACGUARD_DHCP=DEV${I}_MACGUARD_DHCP
        MACGUARD_DHCP=${!MACGUARD_DHCP}
        if [ "$MACGUARD_DEV" == "yes" ] && [ "$DEV" != "" ]; then
            if [ "$MACGUARD_DEV_YES" == "" ]; then
                MACGUARD_DEV_YES="$DEV"
            else
                MACGUARD_DEV_YES="$MACGUARD_DEV_YES $DEV"
            fi
        elif [ "$MACGUARD_DEV" != "yes" ] && [ "$DEV" != "" ]; then
            if [ "$MACGUARD_DEV_NO" == "" ]; then
                MACGUARD_DEV_NO="$DEV"
            else
                MACGUARD_DEV_NO="$MACGUARD_DEV_NO $DEV"
            fi
        fi
        if [ "$MACGUARD_DHCP" == "yes" ] && [ "$DEV" != "" ]; then
            if [ "$MACGUARD_DEV_DHCP" == "" ]; then
                MACGUARD_DEV_DHCP="$DEV"
            else
                MACGUARD_DEV_DHCP="$MACGUARD_DEV_DHCP $DEV"
            fi
        fi
        ((I++))
    done

    # Pro další práci potřebujeme dummy a jeho ip adresu!
    [ "$DUMMY_IFACE" == "" ] && DUMMY_IFACE="dummy0"
    [ "$DUMMY_IP" == "" ] && DUMMY_IP="`$IP addr show $DUMMY_IFACE | grep inet | grep -v inet6 | awk '{print \$2}' | cut -d \"/\" -f1`"

# zavedenĂ­ zĂĄkladnĂ­ch pravidel pro macguarda
# podmínky spuštění:
#       1. pokud máme nějaké rozhraní na kterém běží macguard
#       2. pokud neprovĂĄdĂ­me jen aktualizaci dat
if [ "$MACGUARD_DEV_YES" != "" ] && [ "$1" != "update" ]; then
    echo -n "Starting macguard on:"
    # Standardně jakýkoliv průchozí provoz skrze router zahazujeme
    $IPTABLES -P FORWARD DROP

    # Vytvoříme třídy pro macguarda
    $IPTABLES -N eth_accept
    $IPTABLES -t nat -N valid_mac_pre
    $IPTABLES -N valid_mac_fwd

    # pokud používáme ACCOUNT, tak ho znovu zavedeme i při zavedení základních pravidel pro macguarda
    [ "$ACCOUNT" == "yes" ] && account_start

    # vygenerujeme zĂĄkladnĂ­ pravidla pro danĂĄ rozhranĂ­
    for DEV in $MACGUARD_DEV_YES; do
        # základní ochrana před špatně zadaným, nebo neaktivním rozhraním
        $IP addr show $DEV 1>/dev/null 2>/dev/null
        [ "$?" != "0" ] && continue

        # oznĂĄmĂ­me Ĺže zpracovĂĄvĂĄme danĂŠ rozhranĂ­
        echo -n " $DEV"

        # zĂ­skĂĄme adresu IP a masku rozhranĂ­
        DEV_IP="`ip addr show $DEV | grep -v inet6 | grep inet | grep -v : | awk '{print \$2}' | cut -d \"/\" -f1`"
        DEV_IP1="`echo $DEV_IP | cut -d. -f1`"
        DEV_IP2="`echo $DEV_IP | cut -d. -f2`"
        DEV_IP3="`echo $DEV_IP | cut -d. -f3`"
        DEV_IP4="`echo $DEV_IP | cut -d. -f4`"

        # netmask
        NETMASK="`ip addr show $DEV | grep -v inet6 | grep inet | grep -v : | awk '{print \$2}' | cut -d \"/\" -f2`"

        # vygenerujeme masku na základě netmask
        if let $(((32-${NETMASK}) > 0)); then
            MASK_IP4=$(((255 << (32-${NETMASK})) & 255))
        else
            MASK_IP4=255
        fi
        if let $(((24-${NETMASK}) > 0)); then
            MASK_IP3=$(((255 << (24-${NETMASK})) & 255))
        else
            MASK_IP3=255
        fi
        if let $(((16-${NETMASK}) > 0)); then
            MASK_IP2=$(((255 << (16-${NETMASK})) & 255))
        else
            MASK_IP2=255
        fi
        if let $(((8-${NETMASK}) > 0)); then
            MASK_IP1=$(((255 << (8-${NETMASK})) & 255))
        else
            MASK_IP1=255
        fi
        MASK="$MASK_IP1.$MASK_IP2.$MASK_IP3.$MASK_IP4"

        # network
        NETWORK_IP1="$(($DEV_IP1 & $MASK_IP1))"
        NETWORK_IP2="$(($DEV_IP2 & $MASK_IP2))"
        NETWORK_IP3="$(($DEV_IP3 & $MASK_IP3))"
        NETWORK_IP4="$(($DEV_IP4 & $MASK_IP4))"
        NETWORK="$NETWORK_IP1.$NETWORK_IP2.$NETWORK_IP3.$NETWORK_IP4"

        # Nezakážeme průchod čehokoliv co nejde z rozsahu na daném rozhraní, abychom neblokovali
        # IP adresy připojené na daný router skrze další router.
        $IPTABLES -t nat -A PREROUTING -i $DEV ! -s "$NETWORK/$NETMASK" -j ACCEPT
        $IPTABLES -A FORWARD -i $DEV ! -s "$NETWORK/$NETMASK" -j ACCEPT

        # Vše ostatní jde do třídy valid_mac_pre kde bude ověřeno jestli je pro danou MAC adresu
        # a IP adresu povolen přístup na internet.
        $IPTABLES -t nat -A PREROUTING -i $DEV -j valid_mac_pre
        $IPTABLES -A FORWARD -i $DEV -j eth_accept
    done

    # povolíme příchozí provoz na rozhraních, kde není aktivní macguad
    for DEV in $MACGUARD_DEV_NO; do
        $IPTABLES -A FORWARD -i $DEV -j ACCEPT
    done

    # default politika pro eth_accept je ACCEPT
    $IPTABLES -A eth_accept -j valid_mac_fwd
    $IPTABLES -A eth_accept -j ACCEPT

    # odchozĂ­ provoz skrze rozhranĂ­ povolĂ­me
    for DEV in $MACGUARD_DEV_YES $MACGUARD_DEV_NO; do
        $IPTABLES -A FORWARD -o $DEV -j ACCEPT
    done

    echo ""
fi

# hlavní část macguarda
# podmínky spuštění:
#       1. pokud máme nějaké rozhraní na kterém běží macguard, nebo dhcp server
#       2. pokud nechceme dělat jen klasický update, nebo existuje semafor, nebo chceme dělat vynucený uprade, nebo neexistuje csv tabulka
if ( [ "$MACGUARD_DEV_YES" != "" ] || [ "$MACGUARD_DEV_DHCP" != "" ] ) && ( [ "$1" != "update" ] || [ -e "$MACGUARD_DIR/semafor" ] || [ "$2" == "force" ] || [ ! -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ] ); then
    # nahlĂĄsĂ­me do logu udĂĄlost
    logger "updating macguard settings"

    # semafor
    [ -e "$MACGUARD_DIR/semafor" ] && MACGUARD_SEMAFOR="on"
    rm -f "$MACGUARD_DIR/semafor"

    # pokud neexistuje csv tabulka, nebo děláme vynucený update, tak zkusíme stáhnout nová data
    if [ ! -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ] || [ "$2" == "force" ]; then
        # neexistují-li klíče pro ssh uživatele safe, tak je vygenerujeme
        if [ ! -e "/home/safe/.ssh/id_dsa" ] || [ ! -e "/home/safe/.ssh/id_dsa.pub" ]; then
            ro_test "/home/safe/.ssh/id_dsa"

            # soubory musíme raději odstranit
            rm -f "/home/safe/.ssh/id_dsa"* 2>/dev/null

            # generování klíčů
            echo -n "Generating ssh keys for user safe..."
            su safe -c "/usr/bin/ssh-keygen -q -P \"\" -t dsa -f /home/safe/.ssh/id_dsa"
            chown safe:safe "/home/safe/.ssh/id_dsa"
            chown safe:safe "/home/safe/.ssh/id_dsa.pub"
            echo "done."
            echo ""
            echo "Nyni musite nahrat verejny klic /home/safe/.ssh/id_dsa.pub na macguard server"
            echo "do souboru /home/safe/.ssh/authorized_keys, pokud nemate pristup kontaktujte"
            echo "spravce serveru. Bez tohoto kroku nebude mozne stahnout aktualni data pro"
            echo "macguarda ze serveru na tento router!!"
            echo ""
            sleep 2
            # zrušeno kvůli vyřazeni ssmtp a mail ze základní instalace
            #echo -n "Chcete zaslat verejny klic spravci macguard serveru [`tput setaf 2`ano`tput op`/ne] "
            #read x
            #if [ "$x" != "ne" ]; then
            # zatim si klic necham posilat jen sobe
            #cat "/home/safe/.ssh/id_dsa.pub" | mail -s "Verejny klic uzivatele safe z routeru `hostname`" thunder.m@czela.net
            #fi
        fi

        # pokusĂ­me se stĂĄhnout tabulku
        echo -n "Downloading new table for macguard..."
        su safe -c "mkdir -p $MACGUARD_DIR" 1>/dev/null 2>/tmp/firewall.err
        su safe -c "scp -B safe@${MACGUARD_SERVER}:/home/safe/macguard-centrala/table-${DUMMY_IP}.* $MACGUARD_DIR" 1>/dev/null 2>/tmp/firewall.err
        if [ "$?" == "0" ]; then
            echo "done."
            logger "downloading new macguard table: done"
            MACGUARD_STATUS="on"
        else
            echo "failed."
            # zobrazĂ­me chybovou hlĂĄĹĄku
            cat "/tmp/firewall.err"
            logger "downloading new macguard table: failed!"
            logger "`cat /tmp/firewall.err`"
            MACGUARD_STATUS="off"
            # pokud se nám nepodařilo získat data z macguard serveru, tak zkusíme použít
            # naposledy uloĹženou tabulku
            if [ -e "/usr/share/macguard/table-${DUMMY_IP}.csv" ] && [ ! -e "$MACGUARD_DIR/table-${DUMMY_IP}.csv" ]; then
                cp -ax "/usr/share/macguard/table-${DUMMY_IP}."* "$MACGUARD_DIR"
            fi
        fi

        # vymaĹžeme chybovou hlĂĄĹĄku
        rm -rf "/tmp/firewall.err"
    fi

    # Uděláme zálohu stažené tabulky, abychom při restartu měli okamžitě k dispozici
    # alespoň částečně aktuální data.
    MACGUARD_UPDATE_BACKUP="no"
    if ( [ "$MACGUARD_STATUS" == "on" ] || [ "$MACGUARD_SEMAFOR" == "on" ] ) && [ -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ]; then
        if [ -e "/usr/share/macguard/table-${DUMMY_IP}.csv" ]; then
            # soubory sice existují, ale liší se, takže je aktuální soubor nejspíš novější
            if [ "`diff \"$MACGUARD_DIR/table-${DUMMY_IP}.csv\" \"/usr/share/macguard/table-${DUMMY_IP}.csv\"`" != "" ]; then
                MACGUARD_UPDATE_BACKUP="yes"
            fi
        else
            MACGUARD_UPDATE_BACKUP="yes"
        fi
    fi

    # Aktualizujeme zálohu tabulky, aktualizace dat nesmíme provádět zase moc často,
    # jinak tím ničíme flash disky.
    if [ "$MACGUARD_UPDATE_BACKUP" == "yes" ]; then
        SKIP_RO="no"
        touch "/usr/share/macguard.testfile" 2>/dev/null
        if [ "$?" != "0" ]; then
            # stačí odemknout jednou týdně, pokud neodemkneme uzamčený FS, nezapíšou se nová data
            if [ -e "$MACGUARD_DIR/table-${DUMMY_IP}.csv" ] && [ ! -e "/usr/share/macguard/table-${DUMMY_IP}.csv" ]; then
                /usr/local/sbin/rw 1>/dev/null
                RO="yes"
            elif [ -e "$MACGUARD_DIR/table-${DUMMY_IP}.csv" ] && [ -e "/usr/share/macguard/table-${DUMMY_IP}.csv" ]; then
                if [ "`expr \`ls $MACGUARD_DIR/table-${DUMMY_IP}.csv -l --time-style=+%s | awk '{print \$6}'\` - \`ls /usr/share/macguard/table-${DUMMY_IP}.csv -l --time-style=+%s | awk '{print \$6}'\``" -gt "604800" ]; then
                    /usr/local/sbin/rw 1>/dev/null
                    RO="yes"
                fi
            else
                SKIP_RO="yes"
            fi
        fi

        rm -f "/usr/share/macguard.testfile" 2>/dev/null

        if [ "$SKIP_RO" != "yes" ]; then
            echo -n "Creating backup of macguard table..."
            mkdir -p "/usr/share/macguard"
            cp -ax "$MACGUARD_DIR/table-${DUMMY_IP}."* "/usr/share/macguard/"
            echo "done."
        fi
    fi

    # Pokud jsme nestahovali novĂĄ data a tudĂ­Ĺž nevĂ­me jestli je dostupnĂ˝ macguard server,
    # tak ověříme jeho dostupnost pingem, jestli je nedostupný, tak později povolíme všechny
    # IP.
    if [ "$MACGUARD_STATUS" == "" ]; then
        I_STATUS="0"
        J_STATUS="0"
        while true; do
            ping -q -c 1 $MACGUARD_SERVER >/dev/null 2>/dev/null
            if [ "$?" != "0" ]; then
                ((I_STATUS++))
            else
                ((J_STATUS++))
            fi
            # pokud je špatných více jak 1 a dobrých méně než 2, tak je server nedostupný
            if [ "$I_STATUS" -gt "1" ] && [ "$J_STATUS" -lt "2" ]; then
                MACGUARD_STATUS="off"
                break
            # pokud je dobrých více jak 1 a špatných méně než 2, tak je server dostupný
            elif [ "$J_STATUS" -gt "1" ] && [ "$I_STATUS" -lt "2" ]; then
                MACGUARD_STATUS="on"
                break
            fi
        done
    fi

# generování pravidel pro iptables na základě csv tabulky
# podmínky spuštění:
#       1. pokud máme nějaké rozhraní na kterém běží macguard
#       2. pokud existuje csv tabulka
#       3. pokud je dostupnĂ˝ macguard server, nebo byla nahrĂĄna novĂĄ tabulka
if [ "$MACGUARD_DEV_YES" != "" ] && [ -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ] && [ "$MACGUARD_STATUS" == "on" ]; then
    # Vymažeme všechna pravidla v dané třídě
    $IPTABLES -t nat -F valid_mac_pre 2>/dev/null
    $IPTABLES -F valid_mac_fwd 2>/dev/null

    # zpracujeme csv tabulku
    while read USER_IP B USER_MAC D USER_NAME F USER_VS H USER_ROUTER K USER_ROUTER_MAC L USER_SUBNET; do
        # podmínka pro netransparentní zařízení jako například ovislinky na wifi
        if [ "$USER_ROUTER" == "$DUMMY_IP" ]; then
            $IPTABLES -t nat -A valid_mac_pre -s "$USER_IP" -m mac --mac-source "$USER_MAC" -j ACCEPT
            $IPTABLES -A valid_mac_fwd -s "$USER_IP" -m mac --mac-source "$USER_MAC" -j ACCEPT
        else
            $IPTABLES -t nat -A valid_mac_pre -s "$USER_IP" -m mac --mac-source "$USER_ROUTER_MAC" -j ACCEPT
            $IPTABLES -A valid_mac_fwd -s "$USER_IP" -m mac --mac-source "$USER_ROUTER_MAC" -j ACCEPT
        fi
        # rozšíření o subnet, který uživatel může využívat
        if [ "`echo $USER_SUBNET | grep -F .`" != "" ]; then
            # otazka je jak tyto routy mazat po vypnuti macguarda, nebo firewallu?
            $IP route del "$USER_SUBNET" 2>/dev/null
            $IP route add "$USER_SUBNET" via "$USER_IP" 2>/dev/null
        fi
    done < "$MACGUARD_DIR/table-$DUMMY_IP.csv"

    # Nahrajeme speciální konfigurační soubor
    macguard_load_conf

    # povolíme ssh, web, mail a dns na vnitřní adresy i pro ostatní IP
    $IPTABLES -A valid_mac_fwd -p tcp -d $INTERNAL_IP --dport 22 -j ACCEPT
    $IPTABLES -A valid_mac_fwd -p tcp -d $INTERNAL_IP --dport 25 -j ACCEPT
    $IPTABLES -A valid_mac_fwd -p udp -d $INTERNAL_IP --dport 25 -j ACCEPT
    $IPTABLES -A valid_mac_fwd -p tcp -d $INTERNAL_IP --dport 53 -j ACCEPT
    $IPTABLES -A valid_mac_fwd -p udp -d $INTERNAL_IP --dport 53 -j ACCEPT
    $IPTABLES -A valid_mac_fwd -p tcp -d $INTERNAL_IP --dport 80:81 -j ACCEPT

    # Přesměrujeme jakýkoliv dotaz na http port nevnitřní IP na macguard server, port 81,
    # kde by měla být vysvětlující http stránka s informacemi proč je uživatel zablokován
    # případně jak vyřešit nefunkční připojení.
    $IPTABLES -t nat -A valid_mac_pre ! -d $INTERNAL_IP -p tcp --dport 80 -j DNAT --to ${MACGUARD_SERVER}:81

    # ostatnĂ­ MAC adresy zakĂĄĹžeme
    $IPTABLES -A valid_mac_fwd -j REJECT
else
    # Vymažeme všechna pravidla v dané třídě
    $IPTABLES -t nat -F valid_mac_pre 2>/dev/null
    $IPTABLES -F valid_mac_fwd 2>/dev/null
fi

# část pro generování a spouštění dhcp serveru, o dhcp server se stará macguard,
# proto není třeba speciálně upravovat soubor /etc/init.d/isc-dhcp-server
# podmínky spuštění:
#       1. pokud máme nějaké rozhraní, kde spouštíme dhcp server
#       2. neběží-li dhcp server, nebo existuje-li cvs tabulka
#       3. neběží-li dhcp server, nebo jsme dostali novou csv tabulku
if [ "$MACGUARD_DEV_DHCP" != "" ] && ( [ "`ps -e | grep dhcpd`" == "" ] || [ -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ] ) && ( [ "`ps -e | grep dhcpd`" == "" ] || [ "$MACGUARD_STATUS" == "on" ] ); then
    # dhcp server musíme zastavit aby nám při generování nepřepsal dhcpd.leases
    [ "`ps -e | grep dhcpd`" != "" ] && /etc/init.d/isc-dhcp-server stop
    # -------------------------- generovĂĄnĂ­ dhcpd.conf -----------------------------
    # načteme proměnnou INTERFACES
    [ -e "/etc/default/isc-dhcp-server" ] && . /etc/default/isc-dhcp-server
    # vynulujeme generovĂĄnĂ­ souboru /etc/default/isc-dhcp-server
    INTERFACES_NEW=""

    # vyčistíme dhcp soubory
    rm -f "$MACGUARD_DIR/dhcpd.conf"
    rm -f "/var/lib/dhcp/dhcpd.leases"*
    touch "/var/lib/dhcp/dhcpd.leases" # isc-dhcp-server vyzaduje existenci tohoto souboru

    # datum ve formĂĄtu pro dhcpd.leases
    DHCP_START_DATE="`date -u \"+%w %Y/%m/%d %H:%d:%M\"`"
    DHCP_END_DATE="`date -u \"+%w %Y/%m/%d %H:%d:%M\" -d \"+2 year\"`"

    # zĂĄklad dhcpd.conf
    echo "# Created by firewall script for macguard" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "authoritative;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "log-facility local7;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "default-lease-time 43200; # 12 hours" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "max-lease-time 2678400; # 31 days" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "option domain-name \"$DOMAIN\";" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "option domain-name-servers $DNS_PRIMARY, $DNS_SECONDARY;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "option netbios-name-servers $NETBIOS;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "option T150 code 150 = string;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "use-host-decl-names on;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "allow booting;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "allow bootp;" >> "$MACGUARD_DIR/dhcpd.conf"
    echo "" >> "$MACGUARD_DIR/dhcpd.conf"

    # generovĂĄnĂ­ ip adres pro jednotlivĂĄ rozhranĂ­
    for DEV in $MACGUARD_DEV_DHCP; do
        # základní ochrana před špatně zadaným, nebo neaktivním rozhraním
        $IP addr show $DEV 1>/dev/null 2>/dev/null
        [ "$?" != "0" ] && continue

        # Pokud schĂĄzĂ­ v /etc/default/isc-dhcp-server danĂŠ rozhranĂ­, tak musĂ­me vygenerovat
        # novĂ˝ soubor obsahujĂ­cĂ­ toto rozhranĂ­.
        [ "`echo $INTERFACES | tr \" \" \"\n\" | grep -x \"$DEV\"`" != "$DEV" ] && INTERFACES_NEW="yes"

        # spojení všech zařízení do formátu pro soubor /etc/default/isc-dhcp-server
        if [ "$INTERFACES_INTERNAL" != "" ]; then
            INTERFACES_INTERNAL="$INTERFACES_INTERNAL $DEV"
        else
            INTERFACES_INTERNAL="$DEV"
        fi

        # zĂ­skĂĄme adresu IP a masku rozhranĂ­
        DEV_IP="`ip addr show $DEV | grep -v inet6 | grep inet | grep -v : | awk '{print \$2}' | cut -d \"/\" -f1`"
        DEV_IP1="`echo $DEV_IP | cut -d. -f1`"
        DEV_IP2="`echo $DEV_IP | cut -d. -f2`"
        DEV_IP3="`echo $DEV_IP | cut -d. -f3`"
        DEV_IP4="`echo $DEV_IP | cut -d. -f4`"

        # netmask
        NETMASK="`ip addr show $DEV | grep -v inet6 | grep inet | grep -v : | awk '{print \$2}' | cut -d \"/\" -f2`"

        # vygenerujeme masku na základě netmask
        if let $(((32-${NETMASK}) > 0)); then
            MASK_IP4=$(((255 << (32-${NETMASK})) & 255))
        else
            MASK_IP4=255
        fi
        if let $(((24-${NETMASK}) > 0)); then
            MASK_IP3=$(((255 << (24-${NETMASK})) & 255))
        else
            MASK_IP3=255
        fi
        if let $(((16-${NETMASK}) > 0)); then
            MASK_IP2=$(((255 << (16-${NETMASK})) & 255))
        else
            MASK_IP2=255
        fi
        if let $(((8-${NETMASK}) > 0)); then
            MASK_IP1=$(((255 << (8-${NETMASK})) & 255))
        else
            MASK_IP1=255
        fi
        MASK="$MASK_IP1.$MASK_IP2.$MASK_IP3.$MASK_IP4"

        # network
        NETWORK_IP1="$(($DEV_IP1 & $MASK_IP1))"
        NETWORK_IP2="$(($DEV_IP2 & $MASK_IP2))"
        NETWORK_IP3="$(($DEV_IP3 & $MASK_IP3))"
        NETWORK_IP4="$(($DEV_IP4 & $MASK_IP4))"
        NETWORK="$NETWORK_IP1.$NETWORK_IP2.$NETWORK_IP3.$NETWORK_IP4"

        # broadcast
        BROADCAST_IP1="$((($DEV_IP1 & $MASK_IP1) + (255 - $MASK_IP1)))"
        BROADCAST_IP2="$((($DEV_IP2 & $MASK_IP2) + (255 - $MASK_IP2)))"
        BROADCAST_IP3="$((($DEV_IP3 & $MASK_IP3) + (255 - $MASK_IP3)))"
        BROADCAST_IP4="$((($DEV_IP4 & $MASK_IP4) + (255 - $MASK_IP4)))"
        BROADCAST="$BROADCAST_IP1.$BROADCAST_IP2.$BROADCAST_IP3.$BROADCAST_IP4"

        # zapĂ­ĹĄeme danĂ˝ subnet
        echo "subnet $NETWORK netmask $MASK {" >> "$MACGUARD_DIR/dhcpd.conf"

        # nejmensi subnet pro ktery umime udelat dynamic-bootp je s maskou 255.255.255.252
        if [ "$MASK_IP4" -le "252" ]; then
            # očekáváme že brána má první dostupnou adresu dané sítě!
            HIGHEST_IP4=0
            if [ -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ]; then
                HIGHEST_IP4=`grep $NETWORK_IP1\.$NETWORK_IP2\.$NETWORK_IP3\. "$MACGUARD_DIR/table-$DUMMY_IP.csv" | cut -d\; -f1 | cut -d\. -f4| sort -g | awk -v BIP4=$BROADCAST_IP4 '$1<BIP4' | awk -v NIP4=$NETWORK_IP4 '$1>NIP4' | tail -1`

                if [ -z "$HIGHEST_IP4" ]; then
                    HIGHEST_IP4=$(($NETWORK_IP4 + 2))
                else
                    HIGHEST_IP4=$(($HIGHEST_IP4 + 1))
                fi
            fi

            if [ $HIGHEST_IP4 -ge $(($BROADCAST_IP4 - 1)) ]; then
                echo "DHCP pro $DEV nema volny dynamicky rozsah" 
                HIGHEST_IP4=$(($NETWORK_IP4 + 2))
            fi

            echo "              range dynamic-bootp $NETWORK_IP1.$NETWORK_IP2.$NETWORK_IP3.$HIGHEST_IP4 $BROADCAST_IP1.$BROADCAST_IP2.$BROADCAST_IP3.$(($BROADCAST_IP4 - 1));" >> "$MACGUARD_DIR/dhcpd.conf" 
        fi

        # jako default gateway je ip adresa rozhranĂ­
        echo "              option routers $DEV_IP;" >> "$MACGUARD_DIR/dhcpd.conf"

        # příklad startu ze sítě pomocí pxelinuxu, pouze pro node nádraží a rozsah na ethernetu
        if [ "$DEV_IP" == "10.93.49.193" ]; then
            echo "              server-name \"10.93.49.250\";" >> "$MACGUARD_DIR/dhcpd.conf"
            echo "              next-server 10.93.49.250;" >> "$MACGUARD_DIR/dhcpd.conf"
            echo "              filename \"/tftpboot/pxelinux/pxelinux.0\";" >> "$MACGUARD_DIR/dhcpd.conf"
        fi

        echo "" >> "$MACGUARD_DIR/dhcpd.conf"

        # pokud existuje csv soubor, tak ho načteme
        if [ -e "$MACGUARD_DIR/table-$DUMMY_IP.csv" ]; then
            # Načítáme soubor tolikrát, kolik je k dispozici rozhraní, není moc efektivní.
            while read USER_IP A USER_MAC B USER_NAME C; do
                IFS=$';. \t\n'
                USER_IP_POM=( $USER_IP )
                IFS=$' \t\n'
                USER_IP1=${USER_IP_POM[0]}
                USER_IP2=${USER_IP_POM[1]}
                USER_IP3=${USER_IP_POM[2]}
                USER_IP4=${USER_IP_POM[3]}
                if ( [ $USER_IP1 == $DEV_IP1 ] || ( [ $USER_IP1 -gt $NETWORK_IP1 ] && [ $USER_IP1 -lt $BROADCAST_IP1 ] ) ) && \
                   ( [ $USER_IP2 == $DEV_IP2 ] || ( [ $USER_IP2 -gt $NETWORK_IP2 ] && [ $USER_IP2 -lt $BROADCAST_IP2 ] ) ) && \
                   ( [ $USER_IP3 == $DEV_IP3 ] || ( [ $USER_IP3 -gt $NETWORK_IP3 ] && [ $USER_IP3 -lt $BROADCAST_IP3 ] ) ) && \
                   ( [ $USER_IP4 == $DEV_IP4 ] || ( [ $USER_IP4 -gt $NETWORK_IP4 ] && [ $USER_IP4 -lt $BROADCAST_IP4 ] ) ) && \
                   ( [ "$DEV_IP" != "$USER_IP" ] ); then
                    # Nově jsou definice hostů v isc-dhcp-serveru od verze 3.1.1 globální, takže není nutné
                    # udávat je do rozsahu daného rozhraní, zároveň je třeba ošetřit více stejných mac adres
                    # o ty se dnes stará netadmin, který by neměl dovolit uživatelům zadat stejnou mac adresu,
                    # to se však v budoucnu může změnit!
                    echo "   host $USER_NAME { hardware ethernet $USER_MAC; fixed-address $USER_IP; }" >> "$MACGUARD_DIR/dhcpd.conf"
                    # isc-dhcp-server od verze 3.1.1 obsahuje takĂŠ jednu velkou mouchu, pokud jsou fixnĂ­ adresy
                    # definovaných hostů v rozsahu range, tak je klidně nabízí dále, existují 3 možná řešení:
                    # 1. sjednotit a seřadit ip adresy, tak aby nezasahovaly do rozsahu range
                    # 2. používat starší verzi isc-dhcp-serveru 3.0.4, která funguje správně
                    # 3. generovat ještě dhcpd.leases, kde nastavíme velmi dlouhé doby přidělení adres
                    echo "lease $USER_IP {" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "  starts $DHCP_START_DATE;" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "  ends $DHCP_END_DATE;" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "  tstp $DHCP_END_DATE;" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "  binding state active;" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "  hardware ethernet $USER_MAC;" >> "/var/lib/dhcp/dhcpd.leases"
                    echo "}" >> "/var/lib/dhcp/dhcpd.leases"
                fi
            done < "$MACGUARD_DIR/table-$DUMMY_IP.csv"
        fi
        echo "}" >> "$MACGUARD_DIR/dhcpd.conf"
        echo "" >> "$MACGUARD_DIR/dhcpd.conf"
    done
    # ----------------------- konec generovĂĄnĂ­ dhcpd.conf ---------------------------

    # došlo ke změně INTERFACES pro soubor /etc/default/isc-dhcp-server
    if [ "$INTERFACES_NEW" == "yes" ]; then
        ro_test "/etc/default/isc-dhcp-server"
        if [ ! -e "/etc/default/isc-dhcp-server.no_macguard" ] && [ -e "/etc/default/isc-dhcp-server" ]; then
            mv "/etc/default/isc-dhcp-server" "/etc/default/isc-dhcp-server.no_macguard"
        fi
        echo "# Created by firewall script for macguard" > /etc/default/isc-dhcp-server
        echo "INTERFACES=\"$INTERFACES_INTERNAL\"" >> /etc/default/isc-dhcp-server
    fi

    # symlink na dhcp soubor neodpovĂ­dĂĄ souboru kam macguard uklĂĄdĂĄ dhcp data
    if [ "`readlink /etc/dhcp/dhcpd.conf`" != "$MACGUARD_DIR/dhcpd.conf" ]; then
        ro_test "/etc/dhcp/dhcpd.conf.old"
        if [ -e "/etc/dhcp/dhcpd.conf" ]; then
            mv "/etc/dhcp/dhcpd.conf" "/etc/dhcp/dhcpd.conf.old"
        fi
        ln -s "$MACGUARD_DIR/dhcpd.conf" "/etc/dhcp/dhcpd.conf"
    fi

    # isc-dhcp-server není spouštěn po startu
    if [ "`find /etc/rc* -name \"*isc-dhcp-server\"`" == "" ]; then
        ro_test "/etc/rc.test"
        # v novĂŠ verzi Debiana uĹž nenĂ­ isc-dhcp-server v rc0.d a rc6.d!
        ln -s "../init.d/isc-dhcp-server" "/etc/rc1.d/K40isc-dhcp-server"
        ln -s "../init.d/isc-dhcp-server" "/etc/rc2.d/S40isc-dhcp-server"
        ln -s "../init.d/isc-dhcp-server" "/etc/rc3.d/S40isc-dhcp-server"
        ln -s "../init.d/isc-dhcp-server" "/etc/rc4.d/S40isc-dhcp-server"
        ln -s "../init.d/isc-dhcp-server" "/etc/rc5.d/S40isc-dhcp-server"
    fi

    # neexistuje konfigurace pro dhcp bez macguarda
    if [ ! -e "/etc/dhcp/dhcpd.conf.no_macguard" ] && [ -e "$MACGUARD_DIR/dhcpd.conf" ]; then
        ro_test "/etc/dhcp/dhcpd.conf.no_macguard"
        cp "$MACGUARD_DIR/dhcpd.conf" "/etc/dhcp/dhcpd.conf.no_macguard"
    fi

    # Opět spustíme dhcp server, neměli bychom ho spouštět v rc.S, pokud víme že
    # bude dhcp server spuštěn následně z rc.2, detekce runlevelu je však složitá.
    /etc/init.d/isc-dhcp-server start
fi

    # pokud neexistuej skript pro automatickou aktualizaci macguarda, tak ho vytvoříme
    if [ ! -e "/etc/cron.d/macguard" ]; then
        ro_test "/etc/cron.d/macguard"
        echo "# Created by firewall script for macguard" > /etc/cron.d/macguard
        echo "*/10    * * * * root    /etc/init.d/firewall macguard_update" >> /etc/cron.d/macguard
    fi
fi

    # pokud jsme odemkli disk pro zĂĄpis, tak ho musĂ­me takĂŠ uzamknout
    ro_exit
}

Powered by WebSVN 2.2.1