Генерация правил для iptables

Потребовалось как-то помочь знакомому с настройкой iptables, в процессе написал простой скрипт на питоне, с помощью которого можно без особого курения манов настроить простую маршруторизацию.

На вывод дает список команд для iptables, который затем можно засунуть в .sh и скопировать/слинковать в нужный ранлевел.
Умеет делать 'проброс' портов.
Собственно сам скрипт(штука максимально простая и примитивная):
# coding: utf8
import settings

def initiptables():
	# Делаем базовые настройки, тут впринципе нет ничего сложного. 
	s = settings.path_to_iptables
	print s + ' -F'
	print s + ' -X'
	print s + ' -P INPUT ' + settings.policy_IN
	print s + ' -P OUTPUT ' + settings.policy_OUT
	print s + ' -P FORWARD ' + settings.policy_FRW
	print s + ' -A INPUT -p TCP --syn -j ACCEPT'
	print s + ' -A INPUT -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT'
	print s + ' -A INPUT -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT'
	print s + ' -A INPUT -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT'
	print s + ' -A INPUT -p ALL -i lo -s 127.0.0.0/8 -j ACCEPT' 
	print s + ' -A INPUT -p ALL -i lo -s ' + settings.inet_ip + ' -j ACCEPT'
	print s + ' -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT'
	print s + ' -A OUTPUT -p ALL -s 127.0.0.0/8 -j ACCEPT'
	print s + ' -A OUTPUT -p ALL -s ' + settings.inet_ip + ' -j ACCEPT'
	print s + ' -t nat -A POSTROUTING -o ' + settings.inet_eth + ' -j SNAT --to-source ' + settings.inet_ip #TODO
	if settings.enableRouting: 
		print 'echo "1" > /proc/sys/net/ipv4/ip_forward'
	for e in settings.local_interfaces.keys():
		ip, net = settings.local_interfaces[e]
		initinterface(e, ip, net)

def initinterface(eth, ip, net):
	s = '  ' + settings.path_to_iptables
	print '# Настраиваем интерфейс {0}, ip {1}, подсеть {2}'.format(eth, ip, net)
	print s + ' -A INPUT -p ALL -i ' + eth + ' -s ' + net + ' -j ACCEPT'
	print s + ' -A INPUT -p ALL -i lo -s ' + ip + ' -j ACCEPT' 
	print s + ' -A OUTPUT -p ALL -s ' + ip + ' -j ACCEPT' 
	if settings.hasDHCP: 
		print s + ' -A INPUT -p UDP -i ' + eth + ' --dport 67 --sport 68 -j ACCEPT'


def set_ip_port_to_inet_all():
	for e in settings.local_interfaces.keys():
		ip, net = settings.local_interfaces[e]
		print '# Настраиваем интерфейс {0}, ip {1}, подсеть {2}'.format(e, ip, net)
		# Порты общего назначения
		cmd1 = '  ' + settings.path_to_iptables + ' -A FORWARD -p '
		cmd2 = ' -s ' + net + ' -m multiport --dports ' 
		if settings.ip_port_to_inet_all.__class__ == (0,1).__class__:
			# к своему стыду, я так и не сообразил, как узнать класс объекта :( 
			# потому и пользуюсь таким индуским методом, а мне всего-то нужно было 
			# проверить является ли объект тайплом
			for i in settings.ip_port_to_inet_all:
				cmd2 = cmd2 + str(i) + ','
		else: 
			cmd2 = cmd2 + settings.ip_port_to_inet_all
		print cmd1 + 'tcp' + cmd2[:-1] + ' -j ACCEPT'
		print cmd1 + 'udp' + cmd2[:-1] + ' -j ACCEPT'

def set_ip_port_to_inet():
	# Создаем список особых правил по IPадрессам
	for ip, ports in settings.ip_port_to_inet.items():
		print '# ...правила для ' + ip
		tmp_ports = ''
		if ports.__class__ == (0,1).__class__:
			for t in ports: 
				tmp_ports = tmp_ports + str(t) + ','
			tmp_ports = tmp_ports[:-1]
		else: tmp_ports = ports
		cmd1 = '  ' + settings.path_to_iptables + ' -A FORWARD -p '
		cmd2 = ' -s ' + ip + ' -m multiport --dports ' + str(tmp_ports) + ' -j ACCEPT'
		print cmd1 + 'TCP' + cmd2
		print cmd1 + 'UDP' + cmd2

def set_ports_from_inet():
	# Создаем список портов доступных с внешней сети
	cmd1 = settings.path_to_iptables + ' -A INPUT -p '
	cmd2 = ' -d ' + settings.inet_ip + ' -m multiport --dports ' + settings.ports_from_inet + ' -j ACCEPT'
	print cmd1 + 'TCP' + cmd2
	print cmd1 + 'UDP' + cmd2

def set_ip_route_from_inet():
	# настраиваем проброс портов
	for ip, ports in settings.ip_route_from_inet.items():
		print '# ...правила для ' + ip
		tmp_ports = ''
		if ports.__class__ == (0,1).__class__:
			for t in ports: 
				tmp_ports = tmp_ports + str(t) + ','
			tmp_ports = tmp_ports[:-1]
		else: tmp_ports = ports
		cmd1 = '  ' + settings.path_to_iptables + ' -A FORWARD -i ' + settings.inet_eth
		cmd2 = ' -m multiport --dports ' + str(tmp_ports) + ' -j ACCEPT'
		print cmd1 + ' -p TCP' + cmd2
		print cmd1 + ' -p UDP' + cmd2
		cmd1 = '  ' + settings.path_to_iptables + ' -t nat -A PREROUTING -i ' + settings.inet_eth
		cmd2 = ' -m multiport --dports ' + str(tmp_ports) + ' -j DNAT --to-destination ' + ip 
		print cmd1 + '-p TCP' + cmd2
		print cmd1 + '-p UDP' + cmd2

if settings.dobaseconf:
	print '# Инициализация, очистка старых правил, создание базовых правил'
	initiptables()

if settings.justgivmeinet:
	print '# Тупо все разрешаем'
	for e, ip, net in settings.local_interfaces:
		print settings.path_to_iptables + ' -A FORWARD -s ' + net + ' -j ACCEPT'

if settings.doport2inetall and not settings.justgivmeinet:
	print '# Настраиваем общедоступные порты для локальных пользователей'
	set_ip_port_to_inet_all()

if settings.doport2inetip and not settings.justgivmeinet:
	print '# Настраиваем особых пользователей' 
	set_ip_port_to_inet()

if settings.doportsfrominet:
	print '# Создаем список доступных извне портов (подключение только к фаирволу)'
	set_ports_from_inet()

if settings.doroutefrominet:
	print '# Создаем правила для проброса портов'
	set_ip_route_from_inet()


Пример файла конфигурации к нему должен лежать там-же где и сам скрипт и называться 'settings.py':
# coding: utf8
path_to_iptables	= '/sbin/iptables' # Путь к программе iptables
allow_forward		= '1' # Разрешать форвард траффика

inet_eth			= 'ppp0' # Внешний интерфейс
inet_ip				= '11.22.33.44' # Внешний IP

# Описание локальных сетей в форме {'интерфейс':('ип-интерфейса','подсеть')}
# к примеру: {'eth0':('10.12.0.1','10.12.0.0/24'),'eth2':('192.168.10.10','192.168.10.0/24')}
local_interfaces	= { \
'eth0':('192.168.10.254','192.168.10.0/24'), \
'eth1':('192.168.1.1','192.168.1.0/24') \
}

# Какие порты могут использовать все пользователи локальной сети
ip_port_to_inet_all	= \
(25,110,80,443,5222,5223)

# Какие порты разрешать указанным ip
# формат: {'ip1':(port1, port2, .., port15),'ip2':(port1,port2, .., port15)}
ip_port_to_inet		= { \
'192.168.10.104':(22,666), \
'192.168.10.5':(111), \
'192.168.1.3':(23,56) \
}

# Какие порты и куда пробрасывать
# формат аналогичен ip_port_to_inet
ip_route_from_inet	= { \
'192.168.10.104':(80,8008,8000,6600,6601,8001), \
'192.168.1.10':(25,110,443) \
}

# Порты, на которые, принимает сам фаирвол из инета
# формат: 'port1,port2,..,port15'
ports_from_inet		= '666,22'

policy_IN			= 'DROP'
policy_OUT			= 'DROP'
policy_FRW			= 'DROP'

hasDHCP				= True # На нашем фаирволе стоит DHCP-сервер?
enableRouting		= True # Мы роутер?

dobaseconf			= True # Делать базовые настройки?
doport2inetall		= True # Создавать правила для портов доступных для всех?
doport2inetip		= True # Создавать правила для портов доступных для избранных?
doroutefrominet		= True # Делать проброс портов?
doportsfrominet		= True # К каким портам на фаирволе можно подключаться из инета?
justgivmeinet		= False # Просто разрешить всем в локальной сети использовать инет.
# justgivmeinet исключает doport2inetall и doport2inetip
  • iptables python
  • 0
  • 1 октября 2010, 10:55
  • kir2yar      


Комментарии (2)

RSS свернуть / развернуть
+
0
Хорошо написано, в закладку!)
avatar

melinux

  • 31 октября 2010, 16:43
+
0
Cut!
avatar

Lex

  • 3 ноября 2010, 20:49

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.