The OpenNET Project
 
Поиск (ключи):    ПРОГРАММЫ СТАТЬИ СОВЕТЫ ФОРУМ
  WIKI НОВОСТИ (+) MAN'ы ДОКУМЕНТАЦИЯ

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


<< Предыдущая ИНДЕКС Правка src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: nat, ipfw, freebsd,  (найти похожие документы)
From: Taras Savchuk <taras@elantech.ru.> Newsgroups: email Date: Mon, 03 Oct 2005 14:31:37 +0000 (UTC) Subject: Построение шлюза с трансляцией адресов на двух интерфейсах во FreeBSD FreeBSD + natd x 2 Содержание 1. Постановка задачи. 2. Конфигурация ipfw. 3. Создание\модификация rc скриптов. 4. Правка rc.conf. 5. Проверка связи, проверка функционирования скриптов. Благодарности ELANTECH - ИТ аутсорсинг, комплексная системная интеграция, абонентское обслуживание, поддержка UNIX/Linux/FreeBSD серверов, WEB дизайн, WEB разработка, разработка ПО, автоматизация. 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). Ниже изображена схема сети: 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# Все работает! А у Вас? Шлите письма на taras@elantech.ru с отзывами и пожеланиями.

<< Предыдущая ИНДЕКС Правка src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ Линейный режим | Показать все | RSS ]
 
  • 1.1, universite, 23:35, 04/10/2005 [ответить] [смотреть все]
  • +/
    Ниосилил!

    Непонятно через какой интерфейс поднят VPN?
    Нафига делать такие огромные стартовые скрипты?
    когда можно обойтись тремя конфигами (двух натов и firewall) и запускать с rc.conf и rc.local.


     
     
  • 2.11, lexx, 17:55, 29/12/2005 [^] [ответить] [смотреть все] [показать ветку]
  • +/
    interface virtualniy on sozdaetsya progoy pod nazvaniem mpd ... весь текст скрыт [показать] [показать ветку]
     
  • 1.2, Saenara, 05:50, 05/10/2005 [ответить] [смотреть все]  
  • +/
    Непонятно, зачем делать через natd+ipfw, когда теперь есть pf?
     
     
  • 2.8, Vdim, 11:55, 26/10/2005 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Извиняюсь за глупый вопрос, но что такое pf И если можно узнать токак построит... весь текст скрыт [показать] [показать ветку]
     
  • 1.3, SomeThingWrong, 09:48, 05/10/2005 [ответить] [смотреть все]  
  • +/
    согласен с Saenara, накой хрен юзать старые оглобли natd + ipfw, если существует pf?
     
     
  • 2.4, Envoy, 12:12, 05/10/2005 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Еще есть ipfilter, который не только под BSD РАБОТАЕТ ... весь текст скрыт [показать] [показать ветку]
     
  • 1.5, _Ale_, 13:24, 05/10/2005 [ответить] [смотреть все]  
  • +/
    в который раз убеждаюсь PF - весчь! А тут такое наворочено, что не дай бог!
     
  • 1.6, Taras_, 00:42, 06/10/2005 [ответить] [смотреть все]  
  • +/
    pf есть, но в 6-ой ветке natd уже в ядре, а это большая перспектива.
     
  • 1.7, Feb, 11:55, 06/10/2005 [ответить] [смотреть все]  
  • +/
    Отличная статья!
     
  • 1.9, Stalker AKA Zver, 14:59, 23/12/2005 [ответить] [смотреть все]  
  • +/
    А как быть в такой ситуации?

    http://www.bsdportal.ru/viewtopic.php?t=7662

     
  • 1.12, gerash, 21:31, 31/01/2006 [ответить] [смотреть все]  
  • +/
    А про IPNAT все дружно забыли?
    в отличие от монстра, описанного в статье, он спокойно НАТит на два интерфейса, и не требует, в отличие от NATD, двух переключений контекста на каждый пакет. Кстати, он не требует, чтобы с ним вместе запускался ipf, и спокойно сосуществует с ipfw. А правила НАТа можно менять по ходу дела.
    Т.е. вся мазута в статье свелать бы к отработке правила

    map <extNIC> from <intranet> to any -> <extNIC-address>/32

    и добавлению при поднятии ng0 из mpd правила
    map ng0 from <intranet> to <куда там через VPN ходим> -> <ng0-address>/32

    что спокойно добавляется (и убирается при падении VPN) из скрипта в /usr/local/etc/mpd/, ну, например, ng0-up и ng0-down

     
  • 1.13, jhn, 15:45, 22/02/2006 [ответить] [смотреть все]  
  • +/
    А как быть если ext_ip inet_ip задаются dhcp сервером???
     
     
  • 2.16, gerash, 12:58, 24/09/2006 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Скрипты ng*-up и ng*-down вызываются из mpd с параметрами - например

    exec: /usr/local/etc/mpd/ng1-up ng1 inet 192.168.2.2 192.168.2.1 MyConnection
    exec: /usr/local/etc/mpd/ng1-down ng1 inet MyConnection

    так что наличие или отсутствие DHCP не влияет.

     
  • 1.18, MetallisT, 14:37, 28/09/2007 [ответить] [смотреть все]  
  • +/
    всё отлично работает )
     
  • 1.20, daggerok, 17:33, 30/07/2009 [ответить] [смотреть все]  
  • +/
    далее поскипано зачем вы это делаете есть более простой способ и правильный чит... весь текст скрыт [показать]
     
  • 1.21, Pirate, 14:30, 07/07/2010 [ответить] [смотреть все]  
  • +/
    Настроил данный конфиг, перестали открываются сайты. Просто белый экран и лоадер "0%" и может висеть так до бесконечности. Может у кого была такая проблема, подскажите решение пожалуйста!
     

    Ваш комментарий
    Имя:         
    E-Mail:      
    Заголовок:
    Текст:



    ПОДПИШИСЬ НА ЖУРНАЛ Linux Format 2012!

    Журнал "Linux Format" (Линукс Формат)- Единственный в России и странах СНГ журнал на русском языке, посвящённый Linux и свободному ПО. Журнал для IT-директоров, IT-менеджеров, программистов, системных администраторов, учителей школ и преподавателей ВУЗов и всех пользователей ПК. В каждом выпуске: Новости индустрии OpenSource, обзоры новинок свободного ПО, обучающие и методические статьи.

    Каждый, кто оформит подписку, получает бонусы и подарки- объёмные наклейки на системный блок, диск с архивом номеров за 2005-2011 г.г. и ежемесячно электронную версию журнала в pdf-формате.

    Оформить подписку на год


      Закладки на сайте
      Проследить за страницей
    Created 1996-2012 by Maxim Chirkov  
    ДобавитьРекламаВебмастеруГИД  
    RUNNet TopList