Лабораторная № 3, Firewall ver. 2

May 08, 2010 20:00

Правила для файервола хранятся в виде чисел.


# -*- coding: cp1251 -*-

import re

ruleDict = {}
ruleList = []

class IPError:
    """
    Исключение возвращающее неправильное значение IP адреса или маски подсети.
    """
    def __init__(self,errValue):
        self.errIP = errValue

regxIP = re.compile(r'''\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
                          (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
                          (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
                          (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b''', re.VERBOSE)

def ip2int(IPAddress):
    """
    Функция возвращает числовое значение IP адреса типа int.
    """
    pow2 = [16777216, 65536, 256, 1]
    IPInt = 0
    for i in range(4):
        IPInt += pow2[i]*IPAddress[i]
    return IPInt

def int2ip(IPInt):
    """
    Функция возвращает IP адрес в виде списка, по его числовому значению.
    """
    pow2mask = [4278190080, 16711680, 65280, 255]
    pow2 = [16777216, 65536, 256, 1]
    IPDot = []
    for i in range(4):
        IPDot.append((IPInt & pow2mask[i])/pow2[i])
    return IPDot

def ip2list(strIP):
    """
    Функция преобразует строку IP адреса в список.
    """
    IPList = []
    if regxIP.search(strIP):
        for wordIP in strIP.strip().split('.'):
            IPList.append(int(wordIP))
    else:
        raise IPError('Неправильный IP адрес: ' + strIP)
    return IPList

def checkMask(Mask):
    """
    Проверяет правильность маски подсети, возвращает True | False.
    """
    maskSeq ={255:'',252:'',248:'',240:'',224:'',192:'',128:'',0:''}
    for i in Mask:
        if maskSeq.has_key(i):
            pass
        else:
            return False
    if Mask[0] != 255:
        if Mask[1] > 0 or Mask[2] > 0 or Mask[3] > 0:
            return False
    elif Mask[1] != 255:
        if Mask[2] > 0 or Mask[3] > 0:
            return False
    elif Mask[2] != 255 and Mask[3] > 0:
        return False
    else:
        return True

def netmask(addr, mask):
    """
    На основании введенного IP адреса и маски возвращает значения адреса подсети
    и широковещательного адреса.
    """
    inversMask = 4294967295
    subnet = addr & mask
    brdcst = addr | inversMask - mask
    return subnet, brdcst

def add(ruleStr):
    """
    Добавляет правило для файервола в словарь.
    """
    try:
        Rule, srcAddr, srcMask, dstAddr, dstMask = ruleStr.strip().split()
    except ValueError:
        raise IPError('Неправильное количество параметров.')

listSrcAddr, listSrcMask = ip2list(srcAddr), ip2list(srcMask)
    listDstAddr, listDstMask = ip2list(dstAddr), ip2list(dstMask)
    print listSrcMask
    if checkMask(listSrcMask) == False:
        raise IPError('Нерпавильная маска подсети источника: ' + srcMask)
    elif checkMask(listDstMask) == False:
        raise IPError('Нерпавильная маска подсети назначения: ' + dstMask)
    else:
        pass

IntSrcAddr, IntSrcMask = ip2int(listSrcAddr), ip2int(listSrcMask)
    IntDstAddr, IntDstMask = ip2int(listDstAddr), ip2int(listDstMask)

subNetSrc, brdCstSrc = netmask(IntSrcAddr, IntSrcMask)
    subNetDst, brdCstDst = netmask(IntDstAddr, IntDstMask)

if IntSrcAddr == subNetSrc or IntSrcAddr == brdCstSrc:
        raise IPError('Адрес источника является адресом подсети или широковещательным адресом.')
    elif IntDstAddr == subNetDst or IntDstAddr == brdCstDst:
        raise IPError('Адрес источника является адресом подсети или широковещательным адресом.')

if Rule.lower() == 'permit':
        ruleDict[IntSrcAddr + IntDstAddr] = True
        ruleList.append(ruleStr.strip())
    elif Rule.lower() == 'deny':
        ruleDict[IntSrcAddr + IntDstAddr] = False
        ruleList.append(ruleStr.strip())
    else:
        raise IPError('\nНеправильно задано ключевое слово: ' + Rule.lower())

def list():
    """
    Выводит на экран список правил для файервола.
    """
    ruleNum = 1
    print '\nПравила для файервола:'
    if len(ruleList) == 0:
        print '\nНи одного правила еще не задано.\n'
    else:
        for strRule in ruleList:
            print '%2i %s' % (ruleNum, strRule,)
            ruleNum += 1

def filter (src, dst):
    """
    Фильтрует пакет на основании адреса отправителя и адреса получателя.
    Возвращает значение True | False | Строку с ошибкой.
    """
    src, src = ip2list(src), ip2list(src)

filterKey = ip2int(src) + ip2int(dst)
    if filterKey in ruleDict.keys():
        return ruleDict[filterKey]
    else:
        return False

def delete(delRule):
    """
    По номеру удаляет правило из списка.
    """
    if delRule.isdigit() and 0 < int(delRule) <= len(ruleList):
        delKey = ruleList[int(delRule)-1].strip().split()
        ruleList.remove(ruleList[int(delRule)-1])
        delKey = ip2int(ip2list(delKey[1])) + ip2int(ip2list(delKey[3]))
        ruleDict.pop(delKey)
    else:
        pass

def backup(act):
    """
    Очищает файл с правилами для файервола.
    """
    if act == 'clear':
        try:
            DB = open('rules.db','w')
        except IOError:
            print 'Файл невозможно стереть.'
        finally:
            DB.close()

if act == 'save':
        try:
            rulesDB = open('rules.db','w')
            for i in ruleList:
                rulesDB.write(i+'\n')
        except IOError:
            print 'Правило не добавлено в файл для постоянного хранения.'
        finally:
            rulesDB.close()

def readDbFile():
    """
    Считывает правила из файла fileDB,
    должен находится в том же каталоге что и модуль.
    Возвращает словарь ruleDict.
    """
    global ruleDict
    global ruleList
    ruleDict = {}
    ruleList = []

for ruleLine in open('rules.db','r'):
        rule, srcaddr, srcmask, dstaddr, dstmask = ruleLine.strip().split()
        ruleList.append(ruleLine.strip())
        srcaddr, dstaddr = ip2int(ip2list(srcaddr)), ip2int(ip2list(dstaddr))
        if rule.lower() == 'permit':
            ruleDict[srcaddr + dstaddr] = True
        elif rule.lower() == 'deny':
            ruleDict[srcaddr + dstaddr] = False


python, lab #03

Previous post Next post
Up