Аутсорсинг ИТ, Web-разработка

FreeBSD + natd x 2: трансляция адресов для интернет и локальной сети.

FreeBSD + natd x 2


Содержание

1. Постановка задачи.
2. Конфигурация ipfw.
3. Создание\модификация rc скриптов.
4. Правка rc.conf.
5. Проверка связи, проверка функционирования скриптов.

1. Постановка задачи.

Задача формулируется просто: необходимо транслировать сетевые адреса на двух разных интерфейсах, один из которых виртуальный. Цели две:

В нашем распоряжении машина с FreeBSD 5.4-STABLE, на которой установлены следующие интерфейсы: Ниже изображена схема сети:

2. Конфигурация ipfw.

Приведенная ниже конфигурация ipfw минимальна, так что следует при необходимости добавить дополнительные ограничения. Основная задача данной конфигурации ipfw - позволить mpd создать туннель к VPN-серверу и распределить пакеты для Интернет и пакеты для сети провайдера по разным divert-сокетам (8669 и 8668 соответственно), при этом не позволяя ничего лишнего (особенно соединений "снаружи"). Предполагается, что комментариев к тексту будет достаточно для понимания конфигурации. Итак, /etc/elantech.firewall:

#!/bin/sh
### Полезные переменные ;)

	fwcmd="/sbin/ipfw -q"
	skip="skipto 30000"

### Внешний интерфейс, смотрит в сеть провайдера (ext_if)
	ext_if="sk0"
	ext_net="192.168.0.0/16"	
	ext_ip="192.168.94.26"

### Внутренний интерфейс, смотрит в "маленькую" локалку (elantech_if)
	elantech_if="rl0"
	elantech_net="10.0.0.0/24"
	elantech_mask="255.255.255.0"
	elantech_ip="10.0.0.1"

### Internet интерфейс (VPN туннель)
	inet_if="ng0"
	inet_ip="62.231.11.104"

### VPN-сервер
	vpn_ip="192.168.2.1"	
	vpn_port="1723"
	
###-------------------------------------------------------------------------------------

### Сбрасываем старые правила
	${fwcmd} -f flush

### Таблица доступа в интернет/к большой локалке для машин из "маленькой" сети
	${fwcmd} table 13 flush
	${fwcmd} table 13 add 10.0.0.13
	${fwcmd} table 13 add 10.0.0.10
	${fwcmd} table 13 add 10.0.0.1

### Только локальный траффик через loopback
	${fwcmd} add 100 pass all from any to any via lo0
	${fwcmd} add 200 deny all from any to 127.0.0.0/8
	${fwcmd} add 300 deny ip from 127.0.0.0/8 to any	

### Разрешаем GRE пакеты до и от VPN сервера, чтобы mpd мог поднять туннель
	${fwcmd} add 501 allow gre from ${ext_ip} to ${vpn_ip} via ${ext_if}
	${fwcmd} add 502 allow gre from ${vpn_ip} to ${ext_ip} via ${ext_if}
### Разрешаем PPTP к VPN серверу, опять же для создания туннеля
	${fwcmd} add 503 allow tcp from ${ext_ip} to ${vpn_ip} dst-port ${vpn-port} via ${ext_if} setup keep-state

###-------------------------------------------------------------------------------------
### NAT-им входящие из сети провайдера пакеты
${fwcmd} add 10000 divert natd all from ${ext_net} to any in via ${ext_if}
### NAT-им входящие пакеты из Internet
${fwcmd} add 10001 divert 8669 all from any to any in via ${inet_if}
###-------------------------------------------------------------------------------------	
### Требуем от ipfw обработки динамических правил
${fwcmd} add 11000 check-state

### Доступ из локалки в сеть провайдера
${fwcmd} add 12100 ${skip} tcp from table\(13\) to ${ext_net} out via ${ext_if} setup keep-state
${fwcmd} add 12105 ${skip} udp from table\(13\) to ${ext_net} out via ${ext_if} keep-state
${fwcmd} add 12110 ${skip} icmp from table\(13\) to ${ext_net} out via ${ext_if} keep-state

### Доступ из локалки в Internet
${fwcmd} add 12115 ${skip} tcp from table\(13\) to not ${ext_net} out via ${inet_if} setup keep-state
${fwcmd} add 12120 ${skip} udp from table\(13\) to not ${ext_net} out via ${inet_if} keep-state
${fwcmd} add 12125 ${skip} icmp from table\(13\) to not ${ext_net} out via ${inet_if} keep-state

### Доступ в Internet для себя
${fwcmd} add 12115 ${skip} tcp from ${inet_ip} to not ${ext_net} out via ng0 setup keep-state
${fwcmd} add 12120 ${skip} udp from ${inet_ip} to not ${ext_net} out via ng0 keep-state
${fwcmd} add 12125 ${skip} icmp from ${inet_ip} to not ${ext_net} out via ng0 keep-state

### Доступ в сеть провайдера для себя
${fwcmd} add 12130 ${skip} tcp from ${ext_ip} to ${ext_net} out via ${ext_if} setup keep-state
${fwcmd} add 12135 ${skip} udp from ${ext_ip} to ${ext_net} out via ${ext_if} keep-state
${fwcmd} add 12140 ${skip} icmp from ${ext_ip} to ${ext_net} out via ${ext_if} keep-state

### Доступ из локалки к внутреннему интерфейсу
${fwcmd} add 12145 ${skip} tcp from table\(13\) to ${elantech_ip} in via ${elantech_if} setup keep-state
${fwcmd} add 12150 ${skip} udp from table\(13\) to ${elantech_ip} in via  ${elantech_if} keep-state
${fwcmd} add 12155 ${skip} icmp from table\(13\) to  ${elantech_ip} in via  ${elantech_if} keep-state

### Ексклюзив для root-а
${fwcmd} add 12200 ${skip} all from me to any out via ${elantech_if} setup keep-state


###-------------------------------------------------------------------------------------
### Режем остальные пакеты
${fwcmd} add 14600 deny all from any to any via ${ext_if}
${fwcmd} add 14601 deny all from any to any via ${inet_if}
${fwcmd} add 14602 deny all from any to me via ${elantech_if}
${fwcmd} add 14603 deny all from me to any via ${elantech_if}

###-------------------------------------------------------------------------------------
### NAT-им пакеты в сеть провайдера
${fwcmd} add 50000 divert natd all from any to ${ext_net} out via ${ext_if}
### NAT-им пакеты в интернет
${fwcmd} add 51000 divert 8669 all from any to any out via ${inet_if}
### Сюда долетели честные пакеты - пропускаем!
${fwcmd} add 55000 allow ip from any to any
###-------------------------------------------------------------------------------------

3. Создание\модификация rc скриптов.

Итак, настало время подумать о запуске второго экземпляра natd. Запускать его будем аналогично основному нату, поэтому делаем...

#cp /etc/rc.d/natd /etc/rc.d/natd2
... читаем man rc, man rc.subr, HANDBOOK и правим /etc/rc.d/natd2. Вот результат (изменения выделены красным):
#!/bin/sh
#
# $FreeBSD: src/etc/rc.d/natd,v 1.1.2.1 2004/10/10 09:50:53 mtm Exp $
#

# PROVIDE: natd2
# KEYWORD: nostart nojail

. /etc/rc.subr
. /etc/network.subr

name="natd2"
rcvar=`set_rcvar`
command="/sbin/natd"
start_cmd="natd2_start"
pidfile="/var/run/${name}.pid"

natd2_start()
{
	dhcp_list="`list_net_interfaces dhcp`"
	for ifn in ${dhcp_list}; do
		case ${natd2_interface} in
		${ifn})
			natd_flags="$natd2_flags -dynamic"
			;;
		*)
			;;
		esac
	done
	if [ -n "${natd2_interface}" ]; then
		if echo ${natd2_interface} | \
		grep -q -E '^[0-9]+(\.[0-9]+){0,3}$'; then
			natd2_flags="$natd2_flags -a ${natd2_interface}"
		else
			natd2_flags="$natd2_flags -n ${natd2_interface}"
		fi
	fi
	echo -n ' natd2'
	${natd2_program:-/sbin/natd} ${natd2_flags} ${natd2_ifarg} -P ${pidfile}
}

load_rc_config $name
run_rc_command "$1"
Хорошо видно, что мы подставили цифру "2" ко многим переменным, добавили переменную pidfile, чтобы система скриптов могла корректно останавливать и запускать natd2, а также добавили опцию -P с именем pidfile к строке запуска natd2. Файл /etc/rc.d/natd тоже следует немного модифицировать:
#!/bin/sh
#
# $FreeBSD: src/etc/rc.d/natd,v 1.1.2.1 2004/10/10 09:50:53 mtm Exp $
#

# PROVIDE: natd
# KEYWORD: nostart nojail

. /etc/rc.subr
. /etc/network.subr

name="natd"
rcvar=`set_rcvar`
command="/sbin/${name}"
start_cmd="natd_start"
pidfile="/var/run/${name}.pid"

natd_start()
{
	dhcp_list="`list_net_interfaces dhcp`"
	for ifn in ${dhcp_list}; do
		case ${natd_interface} in
		${ifn})
			natd_flags="$natd_flags -dynamic"
			;;
		*)
			;;
		esac
	done
	if [ -n "${natd_interface}" ]; then
		if echo ${natd_interface} | \
		grep -q -E '^[0-9]+(\.[0-9]+){0,3}$'; then
			natd_flags="$natd_flags -a ${natd_interface}"
		else
			natd_flags="$natd_flags -n ${natd_interface}"
		fi
	fi
	echo -n ' natd'
	${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} -P ${pidfile}
}

load_rc_config $name
run_rc_command "$1"
Чтобы при старте/перезапуске/остановке ipfw аналогичным действиям подвергался не только natd, но и natd2, правим /etc/rc.d/ipfw:
#!/bin/sh
#
# $FreeBSD: src/etc/rc.d/ipfw,v 1.8.2.1 2004/10/10 09:50:53 mtm Exp $
#

# PROVIDE: ipfw
# REQUIRE: ppp-user
# BEFORE: NETWORKING
# KEYWORD: nojail

. /etc/rc.subr
. /etc/network.subr

name="ipfw"
rcvar="firewall_enable"
start_cmd="ipfw_start"
start_precmd="ipfw_precmd"
stop_cmd="ipfw_stop"

ipfw_precmd()
{
	if ! ${SYSCTL} net.inet.ip.fw.enable > /dev/null 2>&1; then
		if ! kldload ipfw; then
			warn unable to load firewall module.
			return 1
		fi
	fi

	return 0
}

ipfw_start()
{
	# set the firewall rules script if none was specified
	[ -z "${firewall_script}" ] && firewall_script=/etc/rc.firewall

	if [ -r "${firewall_script}" ]; then
		. "${firewall_script}"
		echo -n 'Firewall rules loaded, starting divert daemons:'
		if [ -f /etc/rc.d/natd ] ; then
			/etc/rc.d/natd start
		fi
		if [ -f /etc/rc.d/natd2 ] ; then
			/etc/rc.d/natd2 start
		fi		
	elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then
		echo 'Warning: kernel has firewall functionality, but' \
		    ' firewall rules are not enabled.'
		echo '           All ip services are disabled.'
	fi
	echo '.'

	# Firewall logging
	#
	if checkyesno firewall_logging; then
		echo 'Firewall logging enabled'
		sysctl net.inet.ip.fw.verbose=1 >/dev/null
	fi

	# Enable the firewall
	#
	${SYSCTL_W} net.inet.ip.fw.enable=1
}

ipfw_stop()
{
	# Disable the firewall
	#
	${SYSCTL_W} net.inet.ip.fw.enable=0
	if [ -f /etc/rc.d/natd ] ; then
		/etc/rc.d/natd stop
	fi
	if [ -f /etc/rc.d/natd2 ] ; then
		/etc/rc.d/natd2 stop
	fi	
}

load_rc_config $name
run_rc_command "$1"

4. Правка rc.conf.

Теперь допишем в /etc/rc.conf нужные для функционирования нашей системы параметры:

hostname="oppa.ricohprinters.ru"
### Интерфейс, который смотрит в сеть провайдера
ifconfig_sk0="192.168.94.26/24"
### Интерфейс, который смотрит в нашу локалку
ifconfig_rl0="10.0.0.1/24"

### Маршрутизация и файрволл
gateway_enable="YES"
firewall_enable="YES"
### Наш файрволльный скрипт
firewall_script="/etc/firewall.elantech"

### natd
natd_enable="YES"
natd_interface="sk0"
natd_flags=""
### natd2 (для него указываем внешний IP-адрес, а не интерфейс, 
### т.к. на момент запуска natd2 интерфейс ng0 еще не создан)
natd2_enable="YES"
natd2_interface="62.231.11.104"
natd2_flags="-p 8669"

### Статические маршруты
route_fnet="192.168/16 192.168.94.1"
static_routes="fnet"

### DNS
named_enable="YES"

### PPTP клиент
mpd_enable="YES"

5. Проверка связи, проверка функционирования скриптов.

На практике убеждаемся, что ipfw, natd, natd2 и mpd корректно останавливаются, запускаются, перезапускаются, VPN туннель создается, доступ в интернет есть там, где он нужен.

oppa# /etc/rc.d/ipfw stop
net.inet.ip.fw.enable: 1 -> 0
Stopping natd.
Waiting for PIDS: 285, 285, 285, 285, 285.
Stopping natd2.
Waiting for PIDS: 295, 295, 295, 295, 295.
oppa# /etc/rc.d/ipfw start
Firewall rules loaded, starting divert daemons: natd natd2.
net.inet.ip.fw.enable: 0 -> 1
oppa# ifconfig
sk0: flags=8843 mtu 1500
        inet 192.168.94.26 netmask 0xffffff00 broadcast 192.168.94.255
        inet6 fe80::211:d8ff:fe98:9d1a%sk0 prefixlen 64 scopeid 0x2
        ether 00:11:d8:98:9d:1a
        media: Ethernet autoselect (100baseTX )
        status: active
rl0: flags=8843 mtu 1500
        options=8
        inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255
        inet6 fe80::280:48ff:fe33:9d77%rl0 prefixlen 64 scopeid 0x3
        ether 00:48:33:9d:77
        media: Ethernet autoselect (100baseTX )
        status: active
plip0: flags=108810 mtu 1500
lo0: flags=8049 mtu 16384
        inet 127.0.0.1 netmask 0xff000000
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x6
ng0: flags=88d1 mtu 1500
        inet 62.231.11.104 --> 172.16.0.1 netmask 0xffffffff
        inet6 fe80::211:d8ff:fe98:9d1a%ng0 prefixlen 64 scopeid 0x7
oppa#  
Все работает! А у Вас? Шлите письма с отзывами и пожеланиями.




© 2004-2006 ООО «ЭЛАНТЕК».
Адрес: Московская область, г. Фрязино, ул. Полевая, д.6, этаж 4, офис 20.
Телефон: +7 (000) 000-00-00, E-mail: support@ricohprinters.ru