Σ публикаций: 133
#лучшедома
Любые ответы на любые вопросы!

*NIX. Построение шлюза с трансляцией адресов на двух интерфейсах во FreeBSD

Построение шлюза с трансляцией адресов на двух интерфейсах во FreeBSD 

Содержание

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

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

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

     * Обеспечить для локальной сети доступ к ресурсам сети провайдера.
     * Предоставить  для  пользователей  локальной сети доступ к ресурсам
       Интернет.

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

     * sk0: 192.168.94.26/24 - смотрит в сеть провайдера (192.168.xxx.0/24).
     * rl0: 10.0.0.1/24 - смотрит во внутреннюю сеть (10.0.0.0/24).
     * ng0:  62.231.11.104 - туннель к VPN-серверу 192.168.2.1 
       (VPN-сервер находится в сети провайдера, туннель создается демоном mpd).

   Ниже изображена схема сети:

Схема помтроения шлюза на FreeBSD



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.elantech.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:80: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#

Все работает!

Настройка vsftpd
Настройка vsftpd. FTP-сервер под управлением linux своими руками.
Настройка NAT
Настройка NAT (natd) на примере предоставления доступа к ресурсам внешней сети (интернет) из внутренней локальной сети
Настройка роутера на базе FreeBSD
Настройка роутера на базе FreeBSD
Настройка шлюза на FreeBSD
Пошаговое руководство по настройка интернет-шлюза на операционной системе FreeBSD
FreeBSD в качестве сервера доступа. Часть 3. Настройка FireWall
FreeBSD в качестве сервера доступа. Часть 3. Настройка FireWall
FreeBSD в качестве сервера доступа. Часть 2. Немного о безопасности
FreeBSD в качестве сервера доступа. Часть 2. Немного о безопасности
FreeBSD в качестве сервера доступа. Часть 1. Простой сервер доступа с NAT
FreeBSD в качестве сервера доступа. Часть 1. Простой сервер доступа с NAT
Страница сгенерирована за 0,0477 s
Наверх