Правила для файервола хранятся в виде чисел.
# -*- 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