Freebsd настройка шлюза. FreeBSD как router или как заставить FreeBSD маршрутизировать пакеты из одной сети в другую

В данной статье мы расскажем о настройке роутера на базе FreeBSD выполняющего роль шлюза в инернет с установкой firewall-a, и поддерживающем статическую arp таблицу mac адресов в локальной сети. Речь пойдет о IPFW который в FreeBSD служит верой и правдой уже много лет, тем более что в последней версии в составе c FreeBSD 4.0 исправленны ошибки и добавленна корректная возможность ограничивать полосу пропускания по интерфейсу (использование pipe с опцией bw). Предположим что мы имеет роутер с тремя сетевыми платами одна из которых (назовем ее vx0, IP 200.200.200.1) смотрит в сторону Internet-a а вторая (назовем ее vx1, IP 200.200.200.2) смотрит в сторону локальной сети с реальными 18 IP адресами (subnet 200.200.200.0/28 netmask 255.255.255.240). К третьей сетевой карточке (vx2 IP 192.168.1.1 и сеть 192.168.1.0/28) подключена 10Mb сеть соседнего офисса. Задачи перед нами поставленны следующие: 1. Закрыть доступ во внутренюю сеть извне по портам 135,137,139 2. Дать возможность пользователям локальной сети работать с почтой и работать с в броузере с WWW,FTP серверами других компаний. 3. Закрыть на роутере возможность атаки типа SYN Flood, ICMP Flood. 4. Закрыть доступ к корпоративному WWW,FTP серверу (200.200.200.5) используемый для работы с отчетами выставленными на этот WWW server только в пределах локальной сети и доступа из филиала который имеет IP 190.190.190.5 5. Открыть доступ для конфигурирования этого роутера с определеного хоста системного администратора. 6. Обеспечить подсчет трафика по IP адресам в локальной сети чтобы впоследствии доказать что Вася весь месяц только и занимался скачиванием c www.playboy.com картинок сомнительного содержания. 7. Ограничить трафик 64Kb на третьей сетевой карточке для дружественного клиента компании находящемуся в том же здании и подключенному по 10Mb к нашему роутеру и закрыть доступ с их стороны в локальную сеть нашей компании. Итак приступим. 1. Конфигурирование ядра и опций запукаемых скриптов. В ядро необходимо занести следующие опции: options IPFIREWALL (включает в ядро код для фильтрации пакетов) options IPFIREWALL_VERBOSE (включает возможность вести логи по правилам фильтрации и проходящих пакетов) options IPFIREEWALL_VERBOSE_LIMIT=10 (ограничение списка числа пакетов записываемых в лог для того чтобы не зафлудили syslog) options TCP_DROP_SYNFIN (отбрасывает TCP пакеты с SYN и FIN) В итоге при перезагрузке системы мы получим firewall который по умолчанию закрывает прохождение любого IP трафика по всем интерфейсам. Далее мы определим правила которые откроют только те порты TCP или UDP которые нужны для работы пользователей. Если Вы придерживаетесь другого подхода - "сначала все откроем а потом будем закрывать" то вам необходимо указать следующую опцию в ядре: options IPFIREWALL_DEFAULT_TO_ACCEPT В /etc/defaults/rc.conf указываем следующее: tcp_extensions="NO" (отключаем "опасные" из RFC1323 расширения TCP) tcp_drop_synfin="YES" (отбрасывем SYN + FIN) icmp_drop_redirect="YES" (игнорируем перенаправленные ICMP пакеты) icmp_log_redirect="YES" (включаем логинг ICMP REDIRECT) firewall_enable="YES" (включаем использование firewall) firewall_type="Company" (указываем что наши настройки firewalla находятся в rc.firewall в разделе "Company") defaultrouter="199.199.199.1" (шлюз до нашего ISP) 2. Конфигурирование IPFW. Теперь приступаем к написанию правил IPFW. Более побдробное описание синтактиса можно прочитать в handbook или man ipfw. Поскольку мы создаем свою конфигурацию ("Company") то делаем ее описание в rc.firewall: # Описываем сеть и интерфейсы fw="200.200.200.1" local="200.200.200.2" client="192.168.1.1" net="200.200.200.0/28" mask="255.255.255.255.240" # Разрешаем трафик по local интерфейсу ${fwcmd} add pass all from any to any via lo0 # Разрешаем трафик только в пределах локальной сети ${fwcmd} add pass all from any to any via vx1 # Запрещаем прохождение фрагментированных пакетов ${fwcmd} add deny icmp from any to any frag # Разрешаем прохождение ICMP пакетов ${fwcmd} add pass ICMP from any to any # Разрешаем работу с SMTP протоколом ${fwcmd} add pass tcp from any to any 25 out ${fwcmd} add pass tcp from any 25 to any out # Разрешаем работу с HTTPS протоколом ${fwcmd} add pass tcp from any to any 443 out ${fwcmd} add pass tcp from any 443 to any out # Запрещаем работу снаружи с внутреним сервером компании ${fwcmd} add pass tcp from 199.199.199.10 to 200.200.200.5 80 via vx0 ${fwcmd} add pass tcp from 200.200.200.5 80 to 199.199.199.10 via vx0 # Запрещаем работу снаружи с внутреним сервером компании ${fwcmd} add deny tcp from any to 200.200.200.5 80 in via vx0 # Разрешаем работу с HTTP протоколом ${fwcmd} add pass tcp from any to any 80 out via vx1 ${fwcmd} add pass tcp from any 80 to any out via vx1 # Разрешаем работу по всем протоколам в пределах # только локальной сети нашей компании ${fwcmd} add allow all from any to any via vx1 # Разрешаем работу с DNS серверами ${fwcmd} add pass udp from any to any 53 ${fwcmd} add pass udp from any 53 to any # Разрешаем работу с NEWS Серверами ${fwcmd} add pass udp from any to any 119 out via vx1 ${fwcmd} add pass udp from any 119 to any out via vx1 # Разрешаем забор почты по POP3 протоколу ${fwcmd} add pass udp from any to any 110 ${fwcmd} add pass udp from any 110 to any # Разрешаем работу с FTP серверами # Обратите внимание что 20 порт протокола TCP используется для # передачи данных, помимо 21 порта. ${fwcmd} add pass tcp form any 21 to any ${fwcmd} add pass tcp from any to any 21 ${fwcmd} add pass tcp from any 20 to any ${fwcmd} add pass tcp from any to any 20 # Разрешаем доступ по ssh с домашней машины # администратора имеющей IP 200.200.200.15 ${fwcmd} add pass tcp from 200.200.200.15 22 to {isp} ${fwcmd} add pass tcp from {isp} to 200.200.200.15 22 # Ограничиваем трафик с сетевой карточки vx2 в локальную сеть # нашей компании ${fwcmd} add deny all from 192.168.1.0/24 to ${net}:${mask} via vx1 ${fwcmd} add deny all from ${net}:${mask} to 192.168.1.0/24 via vx1 # Разрешаем работу по базовым портам TCP на интерфейсе vx2 ${fwcmd} add pass tcp from 192.168.1.0/24 to any 25 via vx2 ${fwcmd} add pass tcp from any 25 to 192.168.1.0/24 via vx2 ${fwcmd} add pass tcp from 192.168.1.0/24 to any 110 via vx2 ${fwcmd} add pass tcp from any 110 to 192.168.1.0/24 via vx2 ${fwcmd} add pass udp from 192.168.1.0/24 to any 53 via vx2 ${fwcmd} add pass udp from any 53 to 192.168.1.0/24 via vx2 ${fwcmd} add pass tcp from 192.168.1.0/24 to any 80 via vx2 ${fwcmd} add pass tcp from any 80 to 192.168.1.0/24 via vx2 # Ограничиваем полосу пропускания на интерфейсе vx2 в 64 Kb. # для входящего трафика ${fwcmd} add pipe 1 ip from any to any in via vx0 ${fwcmd} add pipe 1 config bw 64Kbit/s # Ограничиваем полосу пропускания на интерфейсе vx2 в 64 Kb. # для исходящего трафика ${fwcmd} add pipe 2 ip from any to any out via vx0 ${fwcmd} add pipe 2 config bw 64Kbit/s Для проверки работы правил вы можете воспользоваться популярным сканером TCP/IP NMAP (входит в состав FreeBSD) дав например команду: nmap 200.200.200.1 или nmap 200.200.200.2 находясь за пределами диапазона адресов вашей сети, или попросив об этом вашего ISP. 3. Предотвращение подделки MAC адреса Нам необходимо обезопасить наш роутер от возможности принятия пакетов с IP адресами которые могут попасть в локальную сеть извне под видом легальных пакетов TCP/IP входящие в диапазон сети 200.200.200.0/28. Даже если это произойдет то на этот случай у нас есть жестко привязанная таблица IP адресов к MAC адресам сетевых карт и роутера нашего ISP. Иногда это бывает необходимо как мера от нечистоплотных сотрудников которые меняют IP адресс своего хоста на адрес другого ПК, владелец которого например находится в отпуске и шишки соотв. посыплятся на него;) Для начала вам нужно построить MAC таблицу адресов, где формат ее будет примерно таким: petya 00:20:af:4a:3e:e3 vasya 00:20:fg:3a:3e:21 sasha 00:20:fg:3a:3e:21 marina 00:20:fg:3a:3e:21 и сохранить ее в файле например /etc/ethers. Для того чтобы узнать Ethernet адрес хоста достаточно на нем набрать arp -a. При запуске на роутере arp -f /etc/ethers вся информация о соответствии IP адреса и MAC адреса сетевой карточки при работе протокола ARP будет браться из файла /etc/ether и замораживаться. Это процесс можно автоматизировать запустив на роутере arpwatch (он есть в портах FreeBSD) и сделав на каждом хосте файл /etc/hosts с описанием пары name_hosts IP_adress и /etc/ethers с вышеприведенным форматом. Когда появляется факт подмены IP адресса то arpwatch посылает письмо с описанием проишедшего и таблица arp замораживается. 4. Настраиваем статистику. Для создания стратистики мы будем использовать ipfm входящий в состав пакетов FreeBSD. При инсталяции в /usr/local/etc/rc.d создается файл ipfm.sh а в /usr/local/etc файл ipfm.conf. Его то как раз нам и нужно отредактировать. Итак приступим: ##### FIRST LOGGING CONFIGURATION ##### # Описывем внутреннюю сеть с которой снимаем статистику LOG 200.200.200.0/255.255.255.240 NOT WITH 200.200.0.0/255.255.0.0 # Присваиваем название файлу для сбора статистики FILENAME /var/log/ipfm/local_net-%d.%m-%H.%M.%S # Устанавливаем период записи в лог в нашем случае лог будет обновляться # еженедально TIME 7 day SORT IN RESOLVE ##### SECOND LOGGING CONFIGURATION ##### NEWLOG # Описывем внутреннюю сеть нашего клиента 192.168.1.0/24 subnet 192.168.1.0/255.255.255.0 NOT WITH 192.168.0.0/255.255.0.0 # Задаем период записи в лог в данном случае 1 день FILENAME /var/log/ipfm/ipfm-%d.%m-%H.%M.%S # Log on a period of one week TIME 1 day SORT IN RESOLVE Если же требуется более детальная информация по протоколам и количеству передаваемых пакетов то можно воспользоваться опцией count в ipfw: # Подсчитываем входящий и исходящий трафик по HTTP протоколу ipfw add count tcp from any to any 80 in via vx0 ipfw add count tcp from any to any 80 out via vx0 # Подсчитываем входящий и исходящий трафик по HTTP протоколу для клиентов ipfw add count tcp from any to any 80 in via vx2 ipfw add count tcp from any to any 80 out via vx2 ipfw add count tcp from any to any 21 in via vx2 ipfw add count tcp from any to any 21 out via vx2 Еcли же вас интересует статистика с конкретного IP адреса то вы просто указываете так: ipfw add count tcp from any to 200.200.200.3 in via vx1 где 200.200.200.3 это IP адрес пользователя например Васи который ежемесячно скачивает с www.playboy.com графические файлы. Вы можете также закрыть доступ к этому сайту например таким способом: ipfw add log deny all from any to www.playboy.com с записью в лог попыток обращения к нему. Графическая статистика строится с применением пакеты MRTG (Multi Router Transfeer Grapheer) при использовании агента snmp запущенного на роутере. Также необходимо установить на роутере средства обнаружения атак, но это уже тема для другой статьи.

Многие новички в сетях и FreeBSD сталкиваются с вопросом:

«Как соединить две сети если сервер на FreeBSD имеет физическое подключение к обеим сетям?»

Иными словами сервер FreeBSD должен выступать в роли router (маршрутизатор).

Итак, что мы имеем:

  • Ethernet сеть
  • Две подсети класса «С» (/24 — маска 255.255.255.0)
  • Сервер FreeBSD с двумя сетевыми картами
  • Клиенты в обеих подсетях

Наша задача, чтобы клиенты из подсети 192.168.1.0/24 могли обмениваться трафиком с клиентами из подсети 192.168.0.0/24.

Сначала настроим сервер FreeBSD и заставим его передавать (маршрутизировать) пакеты из одной подсети в другую.

За это отвечает параметр net.inet.ip.forwarding , посмотрим в какое значение он имеет:

# sysctl net.inet.ip.forwarding
net.inet.ip.forwarding: 0

На данный момент его значение «0», а это значит, что сервер FreeBSD не будет выполнять маршрутизации.

Включим эту функцию:

# sysctl net.inet.ip.forwarding=1
net.inet.ip.forwarding: 0 -> 1

Так мы изменили значение с «0» на «1». Теперь нужно сделать, так чтобы после ребута это значение всегда было 1-цой. Это можно сделать 2-мя способами:

  1. в файл /etc/rc.conf добавить строчку: gateway_enable=»YES»
  2. в файл /etc/sysctl.conf добавить строчку: net.inet.ip.forwarding=1

На сервере у нас есть две сетевые карты и соответственно два интерфейса: em0 и em1.

Пусть em0 «смотрит» в сеть слева, а em1 в сеть справа. Назначим IP-адреса для интерфейсов FreeBSD сервера:

# ifconfig em0 add 192.168.1.1/24
# ifconfig em1 add 192.168.0.1/24

Примечание :

Если на команду ifconfig вы получаете ответ:
command not found
воспользуйтесь командой
# whereis ifconfig
ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz /usr/src/sbin/ifconfig
которая укажет где именно располагается утилита ifconfig
как видно из результата выполнения команды whereis утилита ifconfig находится /sbin/ifconfig
вводите полный путь до утилиты ifconfig, тогда надпись command not found появляться не будет и команда будет выполняться

Посмотрим что получилось:

# ifconfig -a

em0 : flags=8843 metric 0 mtu 1500 ether 00:02:a5:4e:92:48 inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255 media : Ethernet autoselect (100baseTX ) status : active em1 : flags=8802 metric 0 mtu 1500 ether 00:02:a5:4e:92:49 inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255 media : Ethernet autoselect (100baseTX ) status : active

Рассмотрим что все это значит:

em0 и em1 — имена сетевых интерфейсов
флаг UP — означает что сетевая карта включена, если этого флага не будет, то пакеты не будут приниматься на этом интерфейсе (для включения воспользуйтесь командой: ifconfig ИМЯ_ИНТЕРФЕЙСА up)
ether — это mac-адрес этой сетевой карты
inet — назначенный IP-адрес для этого интерфейса и broadcast адрес для этой подсети
media — информация о скорости и дуплексе интерфейса
status — текущий статус интерфейса. Если status: no carrier, то это означает, что на сетевой карте нет линка.

Сохраним настройки, чтобы IP-адреса назначались интерфейсам после ребута сервера, для этого необходимо добавить в файл /etc/rc.conf следующие строчки:

ifconfig_em0=»inet 192.168.1.1 netmask 255.255.255.0″
ifconfig_em1=»inet 192.168.0.1 netmask 255.255.255.0″

Если на сервере вы используете firewall, например ipfw, то добавим правила разрешающие проход пакетов из одной сети в другую:

ipfw add 100 allow ip from 192.168.1.1/24 to 192.168.0.1/24
ipfw add 110 allow ip from 192.168.1.0/24 to 192.168.1.1/24

Теперь настройте клиентские компьютеры:

  • Выставить IP-адрес из нужной подсети: 192.168.1.ХХХ или 192.168.0.ХХХ
  • Выставить маску подсети 255.255.255.0
  • Выставить шлюз по умолчанию: для подсети 192.168.1.ХХХ это 192.168.1.1, а для подсети 192.168.0.ХХХ это 192.168.0.1 (именно эти IP-адреса на интерфейсах нашего FreeBSD сервера)

Наступило время проверить есть ли связь сервера и клиентов. Для этого возьмем заведомо рабочий клиентский компьютер из 2-х сетей, например это будут компьютеры с IP-адресами:

  • 192.168.1.11
  • 192.168.0.15

Воспользуемся утилитой ping на сервере:

# ping 192.168.1.11

Если результат будет таким:

PING 192.168.1.11 (192.168.1.11): 56 data bytes
64 bytes from 192.168.1.11: icmp_seq=0 ttl=64 time=0.466 ms
64 bytes from 192.168.1.11: icmp_seq=1 ttl=64 time=0.238 ms
64 bytes from 192.168.1.11: icmp_seq=2 ttl=64 time=0.272 ms
^C
— 192.168.1.11 ping statistics —
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.238/0.325/0.466/0.100 ms

Значит все хорошо и связь между сервером и клиентом есть. Проделайте тоже самое с 192.168.0.15.

Если результат ping отрицательный, то убедитесь что на клиентском компьютере правильно выставлен IP-адрес и маска подсети, а так же наличие линка на сетевой карте.

Теперь можно попробовать проверить связь между клиентскими компьютерами из разных подсетей.

Так же воспользуемся утилитой ping, но уже на компьютере с IP-адресом 192.168.1.11:

ping 192.168.0.15

Если ответ есть, то и свзяь между компьютерами из разных подсетей есть.

Если ответа нет, то воспользуемся утилитой tracert (для Windows) или traceroute (для FreeBSD):

tracert 192.168.0.15

Если сразу «идут звездочки»:

1 * * *

То проверьте правильность выставление шлюза по умолчанию.

Если трасса выглядит так:

1 192.168.1.1 (192.168.1.1) 0.421 ms 0.447 ms 0.485 ms
2 * * *

То пакет доходит до сервера, убедитесь что firewall сервера не блокирует пакеты и что клиентский компьютер с IP-адресом 192.168.0.15 правильно настроен и «видит» сервер (проверьте IP-адрес, маску подсети, шлюз по умолчанию и наличие ping до сервера)

Вы все проверили, но по прежнему ничего не работает? Воспользуемся утилитой tcpdump на сервере, которая покажет пакеты проходящие через интерфейсы сервера:


и

Запустите пинг с одного клиентского компьютера из одной подсети на другой клиентский компьютер в другой подсети (как мы делали в примерах выше) и смотрите в вывод команды tcpdump на сервере, который будет примерно таким:

# tcpdump -ni em0

12:17:23.398376 IP 192.168.1.11 > 192.168.0.15: ICMP echo request, id 49222, seq 0, length 64
12:17:24.399906 IP 192.168.1.11 > 192.168.0.15: ICMP echo request, id 49222, seq 1, length 64

Т.е. компьютер 192.168.1.11 посылает пакет ICMP echo request до компьютера 192.168.0.15, но ответов мы не видим. Посмотри передает ли сервер эти пакеты на другую сетевую карту:

# tcpdump -ni em1

12:21:18.167017 IP 192.168.1.11 >
12:21:19.168022 IP 192.168.1.11 > 192.168.0.15: ICMP echo request, id 50246, seq 5, length 64

Видим, что запросы передаются на другой интерфейс сервера, но ответов по прежнему нет. Проверьте настройки компьютера 192.168.0.15 и отсутствие у него проблем с физическим подключением к сети.

Когда все работает вывод будет таким:

12:21:17.165998 IP 192.168.1.11 > 192.168.0.15: ICMP echo request, id 50246, seq 3, length 64
12:21:17.171199 IP 192.168.0.15 > 192.168.1.11: ICMP echo reply, id 50246, seq 3, length 64
12:21:18.167017 IP 192.168.1.11 > 192.168.0.15: ICMP echo request, id 50246, seq 4, length 64
12:21:18.171353 IP 192.168.0.15 > 192.168.1.11: ICMP echo reply, id 50246, seq 4, length 64

Мы видим стандартый вывод «запрос-ответ», когда на пакет ICMP echo request приходит ответ в виде пакета ICMP echo reply

Введение == Кратенько хотелось бы накидать план, которому стоит следовать, чтобы курс на Интернет для офиса был правильным и в сторону никого не вильнуло. Сразу отмечу, что шлюз в юниксе - это не одна программа, а целый десяток программ, каждая из которых выполняет свое действие и имеет свои собственные настройки. Мы используем: * FreeBSD 7 * natd * named, routed * ipfw * squid * squidGuard * apache * dhcpd Мой тестовый сервер уже находится в рамках локальной сети, поэтому я считаю, что внешняя сеть у меня это 192.168.0.0/24, а внутреняя - 172.16.0.0/16. Числа, в конце концов, не имеют значения - главное, смысл. Я поставил FreeBSD в минимальной комплектации и мой rc.conf содержит только: hostname="vm=freepro.local" ifconfig_em0="DHCP" linux_enable="YES" sshd_enable="YES" == Настройка NAT == Мой внешний интерфейс - em0 - по умолчанию получает свой IP-адрес по DHCP от обычного роутера с адресом 192.168.1.1. Очевидно, что этот же роутер выполняет роль DNS-сервера. На первом этапе я делаю NAT (всегда на внешнем интерфейсе!) и модифицирую файл /etc/rc.conf таким образом: hostname="vm=freepro.local" defaultrouter="192.168.1.1" ifconfig_em0="inet 192.168.1.10 netmask 255.255.255.0" linux_enable="YES" sshd_enable="YES" # Интернет-шлюз ifconfig_em1="inet 172.16.0.1 netmask 255.255.0.0" gateway_enable="YES" natd_enable="YES" natd_interface="em0" #natd_flags="-f /etc/redirect.conf" firewall_enable="YES" firewall_type="open" #firewall_script="/etc/firewall.conf" router_enable="YES" router="/sbin/routed" router_flags="-q" Я зафиксировал внешний адрес и задал внутренний. Теперь поправим DNS в файле /etc/resolv.conf: nameserver 192.168.1.1 Это всё! Стартуем службы: # /etc/rc.d/ipfw start # /etc/rc.d/natd start # /etc/rc.d/routed start # /etc/rc.d/named start И интернет работает! Клиенту, разумеется, руками прописываем: IP: 172.16.0.2 MASK: 255.255.0.0 GATE: 172.16.0.1 DNS1: 192.168.1.1 Конечно, это очень плохой шлюз. Во-первых, он вообще не защищен, во-вторых, он совсем не кешируется, в-третьих, все DNS-запросы он перенаправляет "наверх", ну и в нем напрочь отсутствует возможность получать какую-либо статистику и чем-либо управлять. Но зато это очень легкий и быстрый шлюз и от дальнейших настроек его производительность будет только увеличиваться, а не уменьшаться. Кстати, обратите внимание, что в новом rc.conf уже закомментированы две строки. Первый комментарий - поможет мне в будущем "пробросить" некоторые порты снаружи - внутрь сети. Т.е. к примеру, если я хочу получить доступ по ssh к клиентскому компьютеру 172.16.0.2 - то я должен буду сделать такой файл: # Файл /etc/redirect.conf redirect_port tcp 172.16.0.2:22 2222 Это означает, что соединяясь с сервером снаружи по порту 2222 я попаду на машину в локальной сети как раз по 22 порту (ssh). Второй комментарий - это моя персональная конфигурация фаервола, заточенная и проверенная. == Настройка ipfw == Моя конфигурация для ipfw на данном этапе она выглядит так: #!/bin/sh # Конфигурация IPFW для простого NAT-сервера /etc/firewall.conf cmd="/sbin/ipfw -q" IfOut="em0" IpOut="192.168.1.10" NetOut="192.168.1.0/24" IfIn="em1" IpIn="172.16.0.1" NetIn="172.16.0.0/16" ################################################## # Clear ################################################## ${cmd} -f flush ${cmd} table 0 flush ${cmd} table 1 flush ################################################## # Whitelist / Blacklist ################################################## ${cmd} table 0 add 172.16.0.12 ${cmd} table 1 add 172.16.0.13 ################################################## # Loopback ################################################## ${cmd} add allow ip from any to any via lo0 ################################################## # Block world to private ################################################## ${cmd} add deny ip from any to 127.0.0.0/8 ${cmd} add deny ip from 127.0.0.0/8 to any #${cmd} add deny ip from 172.16.0.0/16 to any via ${IfOut} #${cmd} add deny ip from 192.168.1.0/24 to any via ${IfOut} ${cmd} add deny ip from any to 10.0.0.0/8 via ${IfOut} #${cmd} add deny ip from any to 172.16.0.0/12 via ${IfOut} #${cmd} add deny ip from any to 192.168.0.0/16 via ${IfOut} ${cmd} add deny ip from any to 0.0.0.0/8 via ${IfOut} ${cmd} add deny ip from any to 169.254.0.0/16 via ${IfOut} ${cmd} add deny ip from any to 192.0.2.0/24 via ${IfOut} ${cmd} add deny ip from any to 224.0.0.0/4 via ${IfOut} ${cmd} add deny ip from any to 240.0.0.0/4 via ${IfOut} ################################################## # ICMP ################################################## ${cmd} add deny icmp from any to any frag ${cmd} add deny log icmp from any to 255.255.255.255 in via ${IfOut} ${cmd} add deny log icmp from any to 255.255.255.255 out via ${IfOut} ################################################## # NAT ################################################## ${cmd} add divert 8668 ip from ${NetIn} to any via ${IfOut} ${cmd} add divert 8668 ip from any to ${IpOut} via ${IfOut} #${cmd} add divert 8668 ip from any to any via ${IfOut} ################################################## # Block private to world ################################################## ${cmd} add deny ip from 10.0.0.0/8 to any via ${IfOut} #${cmd} add deny ip from 172.16.0.0/12 to any via ${IfOut} #${cmd} add deny ip from 192.168.0.0/16 to any via ${IfOut} ${cmd} add deny ip from 0.0.0.0/8 to any via ${IfOut} ${cmd} add deny ip from 169.254.0.0/16 to any via ${IfOut} ${cmd} add deny ip from 192.0.2.0/24 to any via ${IfOut} ${cmd} add deny ip from 224.0.0.0/4 to any via ${IfOut} ${cmd} add deny ip from 240.0.0.0/4 to any via ${IfOut} ################################################## # Whitelist ################################################## ${cmd} add allow all from "table(0)" to any ${cmd} add allow all from any to "table(0)" ################################################## # Blacklist ################################################## ${cmd} add deny all from "table(1)" to any ################################################## # Keep established ################################################## ${cmd} add allow tcp from any to me established ################################################## # Main ################################################## ${cmd} add allow ip from any to any frag ${cmd} add allow icmp from any to ${IpOut} icmptypes 0,8,11 # dns ${cmd} add allow tcp from any to ${IpOut} dst-port 53 setup ${cmd} add allow udp from any to ${IpOut} dst-port 53 ${cmd} add allow udp from ${IpOut} 53 to any ${cmd} add allow udp from ${IpOut} to any dst-port 53 keep-state # dns-client ${cmd} add allow tcp from any to ${NetIn} dst-port 53 setup ${cmd} add allow udp from any to ${NetIn} dst-port 53 ${cmd} add allow udp from ${NetIn} 53 to any ${cmd} add allow udp from ${NetIn} to any dst-port 53 keep-state # time ${cmd} add allow udp from ${IpOut} to any dst-port 123 keep-state # time-client ${cmd} add allow udp from ${NetIn} to any dst-port 123 keep-state # ssh-in ${cmd} add allow tcp from any to ${IpOut} 22 ${cmd} add allow tcp from ${IpOut} 22 to any # ssh-out ${cmd} add allow tcp from ${IpOut} to any 22 ${cmd} add allow tcp from any 22 to ${IpOut} # http ${cmd} add allow tcp from ${IpOut} to any dst-port 80 # http-client ${cmd} add allow tcp from ${NetIn} to any dst-port 80 ${cmd} add allow tcp from any 80 to ${NetIn} # smtp ${cmd} add allow tcp from any to ${IpOut} dst-port 25 setup # forward 8080 to 81 ${cmd} add allow tcp from any to ${IpOut} dst-port 8080 ${cmd} add allow tcp from ${IpOut} 8080 to any ${cmd} add allow tcp from any to ${NetIn} dst-port 81 ${cmd} add allow tcp from ${NetIn} 81 to any # out ${cmd} add deny log tcp from any to any in via ${IfOut} setup #${cmd} add allow tcp from any to any setup ################################################## # Local network ################################################## ${cmd} add allow all from any to any via ${IfIn} ################################################## # Deny All ################################################## ${cmd} add deny all from any to any Я специально закомментировал некоторые строки, которые прибивают пакеты из локальных сетей 192, 172 на внешнем интерфейсе, поскольку мой внешний интерфейс и есть локальный. В реальности эти строки нужны. Едем дальше. == Настройка squid == Теперь мне нужен squid - кеширующий прокси-сервер, способный грамотно раздавать интернет всем пользователям по правилам, которые задает системный администратор. pkg_add -r squid Примечание: конечно, более правильный вариант - собирать ПО из свежих и обновленных портов, но мы экономим на времени, поэтому ставим пакетами. Когда-нибудь потом обновимся с помощью portupgrade. Для squid делаем самую простую настройку - правим файл /usr/local/etc/squid/squid.conf # Минимальная конфигурация SQUID acl all src 0.0.0.0/0.0.0.0 acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 acl to_localhost dst 127.0.0.0/8 acl localnet src 172.16.0.0/255.255.0.0 acl SSL_ports port 443 acl CONNECT method CONNECT http_access allow manager localhost http_access allow localnet http_access deny manager http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access deny all icp_access allow all http_port 3128 transparent hierarchy_stoplist cgi-bin ? acl QUERY urlpath_regex cgi-bin \? cache deny QUERY cache_dir ufs /usr/local/squid/cache 100 16 256 access_log /usr/local/squid/logs/access.log squid cache_log /usr/local/squid/logs/cache.log cache_store_log /usr/local/squid/logs/store.log refresh_pattern ^ftp: 1440 20% 10080 refresh_pattern ^gopher: 1440 0% 1440 refresh_pattern . 0 20% 4320 acl apache rep_header Server ^Apache broken_vary_encoding allow apache cache_effective_user squid cache_effective_group squid visible_hostname vm-freepro.local icp_port 0 error_directory /usr/local/etc/squid/errors/English coredump_dir /usr/local/squid/cache Комментарии из файла конфигурации я намеренно убрал, потому что там их не много, а очень много. Не забываем поправить /etc/rc.conf, добавив строку: squid_enable="YES" Далее - перестраиваем кэш и стартуем сквид: # squid -z # /usr/local/etc/rc.d/squid start Первое, что мы делаем после установки squid - запрещаем локальным пользователям ходить в интернет через 80 порт. Порт 80 перебрасываем на 3128 - т.е. заставляем всех пользователей ходить только через squid. Здесь есть большая маленькая загвоздка. Такую операцию можно сделать, только внедрив поддержку IPFW в ядро, иначе форвардинг не работает. Да, это означает, что сейчас нам придется собрать своё ядро! Дело непростое, но полезное - после сборки своего ядра скорость его работы должна возрасти, а объем - заметно уменьшиться. Сначала с помощью sysinstall ставим исходники ядра: # sysinstall Переходим в /Configure/Distributions Отмечаем внутри раздела src [X] base [X] sys Теперь в папке /usr/src у нас есть исходники ядра. Далее копируем конфигурацию GENERIC в "свою" MYKERNEL, и правим MYKERNEL: # cd /usr/src/sys/i386/conf # cp GENERIC MYKERNEL # mcedit MYKERNEL При правке конфига обязательно нужно указать следующие опции: # Включение фаервола в ядро options IPFIREWALL # Включение механизма логирования "log" options IPFIREWALL_VERBOSE # Ограничение логов - защита от переполнения options IPFIREWALL_VERBOSE_LIMIT=50 # Включение механизма перенаправления пакетов options IPFIREWALL_FORWARD # Включение механизма трансляции адресов NAT options IPDIVERT # Включение механизма ограничения скорости канала options DUMMYNET А также убрать все лишнее "железо", которого в реальности у вас нет. Теперь выполняем сборку ядра. Данная операция может немного затянуться, и может оборваться с ошибкой, потребовав установки дополнительных исходников из sysinstall в зависимости от того, что вы написали в конфигурации. Надеемся, что там нет ничего лишнего. # cd /usr/src # make buildkernel KERNCONF=MYKERNEL # make installkernel KERNCONF=MYKERNEL Теперь нужно перегрузиться, но перед перезагрузкой обязательно прочитайте мануал на тот случай, если перезагрузиться не получится. Хотелось бы, чтобы этого, конечно, не произошло. Итак, перегружаемся и снова правим /etc/firewall.conf. #!/bin/sh # Конфигурация IPFW для NAT-сервера и SQUID-прокси cmd="/sbin/ipfw -q" IfOut="em0" IpOut="192.168.1.10" NetOut="192.168.1.0/24" IfIn="em1" IpIn="172.16.0.1" NetIn="172.16.0.0/16" ################################################## # Clear ################################################## ${cmd} -f flush ${cmd} table 0 flush ${cmd} table 1 flush ################################################## # Whitelist / Blacklist ################################################## ${cmd} table 0 add 172.16.0.2 ${cmd} table 1 add 172.16.0.13 ################################################## # Loopback ################################################## ${cmd} add allow ip from any to any via lo0 ################################################## # Block world to private ################################################## ${cmd} add deny ip from any to 127.0.0.0/8 ${cmd} add deny ip from 127.0.0.0/8 to any #${cmd} add deny ip from 172.16.0.0/16 to any via ${IfOut} #${cmd} add deny ip from 192.168.1.0/24 to any via ${IfOut} ${cmd} add deny ip from any to 10.0.0.0/8 via ${IfOut} #${cmd} add deny ip from any to 172.16.0.0/12 via ${IfOut} #${cmd} add deny ip from any to 192.168.0.0/16 via ${IfOut} ${cmd} add deny ip from any to 0.0.0.0/8 via ${IfOut} ${cmd} add deny ip from any to 169.254.0.0/16 via ${IfOut} ${cmd} add deny ip from any to 192.0.2.0/24 via ${IfOut} ${cmd} add deny ip from any to 224.0.0.0/4 via ${IfOut} ${cmd} add deny ip from any to 240.0.0.0/4 via ${IfOut} ################################################## # ICMP ################################################## ${cmd} add deny icmp from any to any frag ${cmd} add deny log icmp from any to 255.255.255.255 in via ${IfOut} ${cmd} add deny log icmp from any to 255.255.255.255 out via ${IfOut} ################################################## # NAT ################################################## ${cmd} add divert 8668 ip from ${NetIn} to any via ${IfOut} ${cmd} add divert 8668 ip from any to ${IpOut} via ${IfOut} #${cmd} add divert 8668 ip from any to any via ${IfOut} ################################################## # Block private to world ################################################## ${cmd} add deny ip from 10.0.0.0/8 to any via ${IfOut} #${cmd} add deny ip from 172.16.0.0/12 to any via ${IfOut} #${cmd} add deny ip from 192.168.0.0/16 to any via ${IfOut} ${cmd} add deny ip from 0.0.0.0/8 to any via ${IfOut} ${cmd} add deny ip from 169.254.0.0/16 to any via ${IfOut} ${cmd} add deny ip from 192.0.2.0/24 to any via ${IfOut} ${cmd} add deny ip from 224.0.0.0/4 to any via ${IfOut} ${cmd} add deny ip from 240.0.0.0/4 to any via ${IfOut} ################################################## # Whitelist ################################################## ${cmd} add allow all from "table(0)" to any ${cmd} add allow all from any to "table(0)" ################################################## # Blacklist ################################################## ${cmd} add deny all from "table(1)" to any ################################################## # Keep established ################################################## ${cmd} add allow tcp from any to me established ################################################## # Main ################################################## ${cmd} add allow ip from any to any frag ${cmd} add allow icmp from any to ${IpOut} icmptypes 0,8,11 # dns ${cmd} add allow tcp from any to ${IpOut} dst-port 53 setup ${cmd} add allow udp from any to ${IpOut} dst-port 53 ${cmd} add allow udp from ${IpOut} 53 to any ${cmd} add allow udp from ${IpOut} to any dst-port 53 keep-state # dns-client ${cmd} add allow tcp from any to ${NetIn} dst-port 53 setup ${cmd} add allow udp from any to ${NetIn} dst-port 53 ${cmd} add allow udp from ${NetIn} 53 to any ${cmd} add allow udp from ${NetIn} to any dst-port 53 keep-state # time ${cmd} add allow udp from ${IpOut} to any dst-port 123 keep-state # time-client ${cmd} add allow udp from ${NetIn} to any dst-port 123 keep-state # ssh-in ${cmd} add allow tcp from any to ${IpOut} 22 ${cmd} add allow tcp from ${IpOut} 22 to any # ssh-out ${cmd} add allow tcp from ${IpOut} to any 22 ${cmd} add allow tcp from any 22 to ${IpOut} # http ${cmd} add allow tcp from ${IpOut} to any dst-port 80 # http-client #${cmd} add allow tcp from ${NetIn} to any dst-port 80 #${cmd} add allow tcp from any 80 to ${NetIn} # squid ${cmd} add allow all from ${NetIn} to ${IpIn} 3128 via ${IfIn} ${cmd} add fwd ${IpIn},3128 tcp from ${NetIn} to any 80 # smtp ${cmd} add allow tcp from any to ${IpOut} dst-port 25 setup # out ${cmd} add deny log tcp from any to any in via ${IfOut} setup #${cmd} add allow tcp from any to any setup ################################################## # Local network ################################################## ${cmd} add allow all from any to any via ${IfIn} ################################################## # Deny All ################################################## ${cmd} add deny all from any to any Перезапускаем сервисы и проверяем - всё работает, и клиенты незаметно для самих себя проходят через систему контроля. Настройку контроля доступа пока отложим, и решим еще один важный вопрос: получение DNS. == Настройка DNS == Сейчас в наших клиентах прописан DNS адрес 192.168.1.1 - внешний по отношению к внутренней сети 172.16.0.0/16. Можно сказать, что клиенты тысячи раз за день лезут выше сервера в поисках адресов. Сделаем систему лучше - настроим кеширующий DNS-сервер, который бы позволял избежать сквозных коннектов наружу, экономил нам трафик и ускорял работу. Не забываем перед этим запретить доступ по порту 53 наружу для всех клиентов. В файле /etc/namedb/named.conf правим параметры listen-on, forwarders: options { directory "/etc/namedb"; pid-file "/var/run/named/pid"; dump-file "/var/dump/named_dump.db"; statistics-file "/var/stats/named.stats"; listen-on { 127.0.0.1; 172.16.0.1; }; disable-empty-zone "255.255.255.255.IN-ADDR.ARPA"; disable-empty-zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA"; disable-empty-zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA"; forwarders { 192.168.1.1; }; // query-source address * port 53; }; В файле /etc/resolv.conf делаем первым локальный DNS: nameserver 127.0.0.1 nameserver 192.168.1.1 В /etc/firewall.conf запрещаем клиентам использовать внешние DNS (правим секции с комментарием dns-client) # dns-client # Запрещаем внешние DNS #${cmd} add allow tcp from any to ${NetIn} dst-port 53 setup #${cmd} add allow udp from any to ${NetIn} dst-port 53 #${cmd} add allow udp from ${NetIn} 53 to any #${cmd} add allow udp from ${NetIn} to any dst-port 53 keep-state # Разрешаем только локальные DNS ${cmd} add allow tcp from ${NetIn} to ${IpIn} dst-port 53 setup ${cmd} add allow udp from ${NetIn} to ${IpIn} dst-port 53 Рестартуем: # /etc/rc.d/named restart # /etc/rc.d/ipfw restart Теперь вернемся к вопросу контроля доступа в интернет. Решений - сразу два. Во-первых - настроить acl-политики в squid. Во-вторых - установить и настроить squidGuard - специальное приложение для контроля доступа. Начнем по порядку. == Настройка squid acl == acl - это правила в конфигурации squid, которые достаточно эффективно позволяют ограничивать информационный поток, проходящий через прокси-сервер. Если кратко - с acl в два счета можно убить всякую левоту, которая мешает работать. Все acl- настройки по умолчанию пишутся в файле squid.conf, но также могут быть вынесены во внешние файлы. Для примера приведу часть конфига: # Запрещаем всем файлопомойки acl shares dstdomain .rapidshare.com .webfile.ru http_access deny shares # Запрещаем всем запрашивать сайты по IP acl ip_urls url_regex http://+\.+\.+\.+[:/] http_access deny ip_urls # Ограничения по группам src group_strict { ip 172.16.0.20-172.16.0.25 } src group_allow { ip 172.16.0.26-172.16.0.30 } acl { group_allow { pass any } group_strict { pass local none } } Получается замечательно. Но очевидно, что в хорошем прокси таких правил должно быть много - по правилу на каждую "дыру". Выяснять "дыры" и прописывать их поштучно - утомительно, но, как всегда, есть готовое решение - squidGuard - приложение-фильтр с огромным набором правил, пополнять которые, в принципе, можно даже по расписанию cron. Изучаем вопрос. == Настройка squidGuard == Теперь попробуем поставить и настроить squidGuard. Делается это не сложно, но нужно быть внимательным. Итак: # pkg_add -r squidGuard # cp /usr/local/etc/squid/squidGuard.conf.sample /usr/local/etc/squid/squidGuard.conf В файле squidGuard.conf хранятся все настройки, некоторые из которых придется поправить сразу же, а именно: # Файл squidGuard.conf ... source sample-clients { ip 172.16.0.0/16 } ... Сделаем привязку squidGuard к squid - добавим 3 строки в файл squid.conf: redirector_bypass on redirect_program /usr/local/bin/squidGuard -c /usr/local/etc/squid/squidGuard.conf redirect_children 10 squidGuard хранит свою конфигурационную базу в /var/db/squidGuard. Перед первым запуском или после внесения изменений ее необходимо перестроить: # rehash # squidGuard -C all # chown -R squid:squid /var/db/squidGuard # /usr/local/etc/rc.d/squid restart Все хорошо, вот только при попытке клиента зайти на запрещенный сайт, к примеру, http://3warez.com/, мы наблюдаем тормоза. А хотелось бы получать какое-то вразумительное сообщение. Для этого нам потребуется apache. == Настройка apache == Как уже говорилось, apache нужен нам для отображения информации о заблокированных адресах и причинах блокировок. Делаем как обычно: # pkg_add -r apache22 # echo "apache22_enable="YES"" >> /etc/rc.conf Настройки apache лежат в файле /usr/local/etc/apache22/httpd.conf. Перед запуском необходимо проверить директивы DocumentRoot, ServerName - подробности опущу, т.к. в интернете масса статей по настройке этого сервера. Делается за 1 сек. Запускаем: # echo "Access denied" > /usr/local/www/apache22/data/index.html # /usr/local/etc/rc.d/apache22 start Поправим немного конфиг squidGuard.conf: # В самом конце файла acl { ..... default { redirect http://172.16.0.1/index.html } } == Настройка dhcpd == И вот мы близимся к завершению. Сеть настроена и работает чудесно. Все под контролем, все строго ограничено. Но после кнута клиентам пора предложить и пряник - в виде раздачи автоматической DHCP-адресов. Хороший администратор, конечно, и тут смухлюет - будет раздавать адреса только по MAC, но мы просто наведём изюм. # pkg_add -r isc-dhcp3-server # cp /usr/local/etc/dhcpd.conf.sample /usr/local/etc/dhcpd.conf В файл /etc/rc.conf добавляем строки: dhcpd_enable="YES" dhcpd_flags="-q" dhcpd_ifaces="em1" Еще нужно поправить самый главный конфиг /usr/local/etc/dhcpd.conf: option domain-name "example.com"; option domain-name-servers 172.16.0.1; option subnet-mask 255.255.255.0; default-lease-time 3600; max-lease-time 86400; ddns-update-style none; subnet 172.16.0.0 netmask 255.255.0.0 { range 192.16.0.11 172.16.0.15; option routers 172.16.0.1; } Включаем электричество: # /usr/local/etc/rc.d/isc-dhcpd start Вот, пожалуй, и всё, самое главное. Данная статья не претендует на абсолютную полноту и содержательность, но вкратце описывает этапы, которые необходимо пройти, чтобы довести сервер до рабочего состояния. Дальше - только тюнинг и еще раз тюнинг. Не забывайте также, что это не единственный путь настройки сервера - в unix всегда есть альтернатива и вы можете использовать совсем другие приложения.

Использование FreeBSD на небольших роутерах для связи с внешним миром уже давно перестало быть чем-то выдающимся. Эта простая в использовании, нетребовательная к ресурсам и обслуживанию операционная система почти идеально подходит для решения подобных задач.

Нам понадобится

Аппаратное обеспечение . Чтобы вывести внутреннюю сеть в Интернет, достаточно компьютера Pentium III 600 МГц, 256 Мб RAM, 10 Гб HDD, 2 сетевые карты. Конфигурация взята с запасом, для полноценной работы сети малого офиса (около 50 пользователей) вполне хватило бы Pentium II 400 МГц, c 128 Мб RAM. Но в дальнейшем может возникнуть желание установить на этот же шлюз, к примеру, прокси-сервер, лучше выбрать конфигурацию более высокого уровня.

Операционная система : FreeBSD 5.5 или 6.1.

Дополнительно: из-за того, что данный компьютер подлежит непрерывному использованию, рекомендую доставить внутрь корпуса дополнительные вентиляторы чтобы обеспечить принудительное нагнетание/отток воздуха для охлаждения. Практически все современные корпусы ATX позволяют сделать это.

Поскольку все необходимые модули включены в состав операционной системы, больше нам ничего не потребуется.

Настройка сетевых интерфейсов

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

Должно появиться что-то подобное:

rl0: flags=8843 mtu 1500
options=8
ether 00:xx:xx:xx:xx:xx

status: active
xl0: flags=8843 mtu 1500
options=9
ether 00:zz:zz:zz:zz:zz
media: Ethernet autoselect (100baseTX)
status: active
plip0: flags=108810 mtu 1500
lo0: flags=8049 mtu 16384
inet6::1 prefixlen 128


В компьютере установлены две сетевые карты c именами интерфейсов rl0 и xl0.

В нашем случае интерфейс rl0 будет «смотреть» во внешний мир, а xl0 – во внутреннюю сеть. IP- адрес внутреннего интерфейса: 192.168.9.2 , маска подсети 255.255.255.0, имя интерфейса xl0; IP-адрес внешнего интерфейса 83.xxx.xxx.xxx, маска подсети 255.255.255.224, имя интерфейса rl0.

Уточнить, сетевым картам каких производителей соответствуют те или иные сетевые адреса, можно, заглянув в файл GENERIC в каталоге /usr/src/sys/i386/conf:

# more /usr/src/sys/i386/conf/ GENERIC

В нем находим соответствующие строчки:

device rl # RealTek 8129/8139

device xl # 3Com 3c90x (“Boomerang”, “Cyclone”)

Таким образом, интерфейс rl0 соответствует сетевой карте RealTek 8129/8139 и ее аналогам. Сетевой интерфейс xl0 соответствует сетевой карте 3Com.

Отдельно стоит упомянуть о файле GENERIC. Это файл конфигурации ядра, устанавливаемого по умолчанию при инсталляции FreeBSD. Он организован так, чтобы система могла поддерживать большинство наиболее используемых устройств, в том числе и указанные сетевые карты. Очень часто дальнейшие модификации ядра строятся на модифицированной копии этого файла. В данном случае, мы именно так и поступим:

Шлюз провайдера – по умолчанию 83.xxx.xxx.1.
В сети присутствуют компьютеры пользователей – 192.168.9.31, 192.168.9.32.
Наш домен (условно) – ourdomain.ru.
Имя хоста (компьютера) – ourhost.ourdomain.ru.

Выполняем настройку сетевых карт. Можно использовать утилиту sysinstall (/stand/sysinstall для FreeBSD 5.5 и /usr/sbin/sysinstall для FreeBSD 6.1) Но поскольку нам известны все необходимые параметры, то для упрощения процесса и экономии времени мы будем задавать параметры путем редактирования соответствующих конфигурационных файлов.

Для редактирования будем использовать текстовый редактор vi, присутствующий практически в любой системе UNIX. Для администраторов, пока незнакомых с редактором, могу порекомендовать замечательную статью Максима Мошкова http://www.lib.ru/unixhelp/vi.txt и http://www.lib.ru/unixhelp/vibegin.txt.

Настройки сетевых интерфейсов во FreeBSD хранятся в файле /etc/rc.conf. Открываем его на редактирование:

# vi /etc/rc.conf

И добавляем следующие строки:

# Задаем внутренний интерфейс
ifconfig_xl0="inet 192.168.9.2 netmask 255.255.255.0"
# Задаем внешний интерфейс
ifconfig_rl0="inet 83.xxx.xxx.xxx netmask 255.255.255.224"
# Задаем шлюз провайдера по умолчанию
defaultrouter="83.xxx.xxx.1"
# Имя хоста
hostname="ourhost.ourdomain.ru"
# Указываем, что сервер будет работать как маршрутизатор
gateway_enable="YES"

После чего перезагружаем компьютер:

В данный момент компьютер можно было и не перезагружать. Но мы хотим достоверно убедиться, что наши интерфейсы установлены корректно и работают, поэтому я все же рекомендую перезагрузиться.

После загрузки проверяем:

Вывод команды ifconfig:

rl0: flags=8843 mtu 1500
options=8
inet6 fe80::215:58ff:fe3e:8fb1%rl0 prefixlen 64 scopeid 0x1
inet 83.xxx.xxx.xxx netmask 0xffffffe0 broadcast 83.xxx.xxx.yyy
ether 00:xx:xx:xx:xx:xx
media: Ethernet autoselect (100baseTX)
status: active
xl0: flags=8843 mtu 1500
options=9
inet6 fe80::20a:5eff:fe62:ade2%xl0 prefixlen 64 scopeid 0x2
inet 192.168.9.2 netmask 0xffffff00 broadcast 192.168.9.255
ether 00:zz:zz:zz:zz:zz
media: Ethernet autoselect (100baseTX)
status: active
plip0: flags=108810 mtu 1500
lo0: flags=8049 mtu 16384
inet6::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4
inet 127.0.0.1 netmask 0xff000000

Файл rc.conf, на мой взгляд, можно назвать ключевым файлом конфигурации. Очень большое число параметров, используемых системой, задается в виде соответствующих переменных в этом файле. В том числе настройки сетевых интерфейсов, файервола и NAT, используемых нами.

Настройка шлюза

Мы будем использовать «родной» для FreeBSD файервол IPFW. Для этого мы должны внести некоторые изменения в ядро системы. Если возникли дополнительные вопросы по перекомпиляции ядра, советую прочитать дополнительный материал: http://freebsd.org.ru/how-to/kernelconfig.html.

Заметьте, что нужно использовать исходные тексты ядра для соответствующей архитектуры. Поскольку архитектура нашего компьютера базируется на платформе i386, то и ядро должно быть скомпилировано в соответствии с платформой. Для владельцев компьютеров других платформ я рекомендую обратиться к соответствующей литературе.

Исходники ядра по умолчанию лежат в каталоге /usr/src/sys/i386/conf. Соответственно переходим в данный каталог:

# cd /usr/src/sys/i386/conf

Как правило, изменяют файл GENERIC, содержащий опции ядра, устанавливаемого по умолчанию. Для этого делаем копию данного файла:

# cp GENERIC ourkernel

Открываем на редактирование новый файл ourkernel:

и добавляем следующие опции:

#
options IPFIREWALL #firewall
options IPFIREWALL_VERBOSE ?
#enable logging to syslogd(8)
options IPFIREWALL_FORWARD ?
#enable transparent proxy support
options IPFIREWALL_VERBOSE_LIMIT=100 #limit verbosity
options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default
#
options DUMMYNET
#
options IPDIVERT #divert sockets

После сделанных изменений можно приступать к перекомпиляции ядра.

Выполняем команды:

# config ourkernel
# cd /usr/src/sys/i386/compile/ourkernel
# make depend
# make
# make install

Перегружаемся:

Если после перезагрузки сервер работает нормально, приступаем к настройке файервола.

Для организации работы файервола используются следующие переменные, добавляемые при необходимости в файл rc.conf.

Разрешает или запрещает использование файервола:

# Set to YES to enable firewall functionality
firewall_enable="NO"

Имя и местоположение файла, отвечающего за инициализацию файервола.

# Which script to run to set up the firewall
firewall_script="/etc/rc.firewall"

При установке данного правила в «YES» подавляется вывод на дисплей:

firewall_quiet="NO"

Разрешить/запретить ведение лога событий:

firewall_logging="NO"

Тип настройки файервола:

firewall_type="UNKNOWN"

по умолчанию FreeBSD использует правила из файла /etc/rc.firewall.

В нем есть несколько готовых шаблонов:

open – файервол разрешает прохождение всех пакетов.

client – рекомендуется для защиты только этого компьютера. То есть файервол настроен как стандартный клиентский компьютер. Он разрешает все исходящие соединения и запрещает все входящие соединения, кроме соединений по 25 порту.

simple – предполагается для настроек простых шлюзов и т. д. То есть в качестве простейшего файервола, защищающего внутреннюю сеть от проникновения извне. Мы будем настраивать более гибкую систему правил, поэтому данный шаблон нами не используется не будет.

closed – Разрешается трафик через локальный интерфейс lo0. Прохождение остального трафика определяется правилом по умолчанию. Как правило, это запрет любого доступа, исключая внутренний интерфейс lo0 (попросту говоря, разрешен только доступ «к самому себе»)

UNKNOWN – запретить загрузку файервольных правил из конфигурационного скрипта по умолчанию. Файервол никак не настраивается. Будет он пропускать трафик или нет, зависит от конфигурации ядра системы. Используется по умолчанию.

Эту же переменную в значении «filename» – «имя_файла» – можно использовать для задания собственного конфигурационного файла для файервола.

Например:

firewall_type="/etc/rc.firewall.newconfig"

будет загружать настройки из созданного файла /etc/rc.firewall.newconfig.

«firewall_flags=””» – служит для передачи дополнительных аргументов при использовании firewall_type со значением filename.

Наша задача состоит в том, чтобы создать систему, отвечающую следующим критериям:

Простота администрирования.

Возможность модификации «на лету», незаметно для пользователей. Поэтому такие операции, как разрыв соединений и тем более перезагрузка для нас нежелательны.

Гарантия того, что наша система будет работать на большинстве машин.

В нашем примере скрипта все компьютеры локальной сети делятся на две условные группы: одна группа привилегированная – это те, кому разрешен доступ в Интернет, используя наиболее употребительные сервисы, такие как:

HTTP – порт 80;
HTTPS – порт 443;
FTP – порты 20, 21 и от 1025 до 65535;
SMTP-протокол для пересылки почты – порт 25;
POP3-протокол для приема сообщений – порт 110.

Есть и другая группа, компьютерам из которой разрешен доступ только к внешнему корпоративному серверу c IP-адресом 83.xxx.xxx.2 (только протоколы SMTP и POP3).

Мы должны добиться, чтобы можно было изменять привилегированную группу, что называется, «на лету», по возможности не разрывая установленных соединений. Для этого мы из нашего скрипта вызываем дополнительный скрипт rc.firewall.local.inet. Достаточно отредактировать и перезапустить этот дополнительный скрипт, не затрагивая всех остальных настроек файервола.

Дополнительно мы должны предусмотреть ситуацию, когда меняются параметры сети, такие как IP-адрес шлюза провайдера. Для этого мы будем использовать в скрипте локальные переменные. Например, при изменении шлюза по умолчанию достаточно изменить значение переменной intgateway и перезапустить скрипт rc.firewall.run.

Вот наш пример скрипта:

# vi rc.firewall.run
#!/bin/sh
extip="83.xxx.xxx.xxx"
intip="192.168.9.2"
intnet="192.168.9.0/24"
mailserver="83.xxx.xxx.2"
intgateway="83.xxx.xxx.1"
#
/sbin/ipfw -f flush &
#
/sbin/ipfw add 180 divert natd ip from ${intnet} to any out xmit fxp0
/sbin/ipfw add 190 divert natd ip from any to ${extip}
# ICMP
/sbin/ipfw add 500 allow icmp from any to any
# SSH
/sbin/ipfw add 10000 allow tcp from any to any 22
/sbin/ipfw add 10010 allow tcp from any 22 to any
# DNS
/sbin/ipfw add 11000 allow tcp from any to any 53
/sbin/ipfw add 11010 allow tcp from any 53 to any
/sbin/ipfw add 11020 allow udp from any to any 53
/sbin/ipfw add 11030 allow udp from any 53 to any
# Web FTP
/sbin/ipfw add 12000 allow tcp from me to any 20,21,80,443
/sbin/ipfw add 12010 allow tcp from any 20,21,80,443 to me
/sbin/ipfw add 12020 allow udp from me to any 20,21
/sbin/ipfw add 12030 allow udp from any 20,21 to me
#
# Script for the privilege group
/bin/sh /etc/rc.firewall.local.inet
# Deny other computer of LAN
/sbin/ipfw add 12960 deny tcp from ${intnet} to any 20,21,80,443
/sbin/ipfw add 12970 deny tcp from any 20,21,80,443 to ${intnet}
/sbin/ipfw add 12980 deny udp from ${intnet} to any 20,21
/sbin/ipfw add 12990 deny udp from any 20,21 to ${intnet}
#
#
/sbin/ipfw add 13000 allow tcp from ${intnet} to ${mailserver} 25,110
/sbin/ipfw add 13010 allow tcp from ${mailserver} 25,110 to ${intnet}
#
/sbin/ipfw add 55010 allow tcp from any to any 1024-65534
/sbin/ipfw add 55020 allow tcp from any 1024-65534 to any
/sbin/ipfw add 55030 allow tcp from any 1024-65534 to any
/sbin/ipfw add 55040 allow tcp from any to any 1024-65534
/sbin/ipfw add 55050 allow udp from any to any 1024-65534
/sbin/ipfw add 55060 allow udp from any 1024-65534 to any
/sbin/ipfw add 55070 allow udp from any 1024-65534 to any
/sbin/ipfw add 55080 allow udp from any to any 1024-65534
# Deny all
/sbin/ipfw add 65534 deny ip from any to any

Создаем и редактируем скрипт rc.firewall.local.inet для работы с привилегированной группой адресов:

# vi /etc/ rc.firewall.local.inet
#!/bin/sh
intnet="192.168.9.0/24"
privgroup={31,32}
#
/sbin/ipfw delete 12310
/sbin/ipfw delete 12320
/sbin/ipfw delete 12330
/sbin/ipfw delete 12340
#
/sbin/ipfw add 12310 allow tcp from ${intnet}${privgroup} to any 20,21,80,443,1025-65535
/sbin/ipfw add 12320 allow tcp from any 20,21,80,443,1025-65535 to ${intnet}${privgroup}
/sbin/ipfw add 12330 allow udp from ${intnet}${privgroup} to any 20,21,1025-65535
/sbin/ipfw add 12340 allow udp from any 20,21,1025-65535 to ${intnet}${privgroup}

В скрипте для изменения состава привилегированной группы необходимо отредактировать переменную privgroup, добавив/удалив в ней номер хоста в локальной подсети.
Например, чтобы добавить два компьютера с IP-адресами 192.168.9.33 и 192.168.9.45, нужно записать «privgroup={31-33,45}».

Использовать правила типа «/sbin/ipfw delete NNNNN» при старте системы, когда такого правила не было – немножко некрасиво. При попытке удалить несуществующее правило система выдает на консоль сообщение следующего вида:

ipfw: rule 13031: setsockopt(IP_FW_DEL): Invalid argument

При этом система продолжает нормально работать.

Если все делать строго, то нужно создавать два скрипта: один запускать при старте, второй – при изменениях на ходу. Но тогда нужно будет вносить соответствующие изменения в оба скрипта.Поскольку основная цель – создать простую в администрировании систему, то данной проблемой в нашем случае можно пренебречь.

Зато теперь мы можем после внесения соответствующих изменений просто перезапустить скрипт для привилегированной группы.

# /bin/sh rc.firewall.local.inet

Также мы можем вносить изменения и перезапускать скрипт rc.firewall.run, хотя, по замыслу, это нам придется делать гораздо реже, чем в случае со скриптом привелигированной группы.

# /bin/sh rc.firewall.run

Поскольку мы написали свой собственный скрипт, обнуляющий существующие правила и запускающий альтернативную конфигурацию файервола, нужно подумать, как его запустить.

Во FreeBSD есть замечательный механизм запуска пользовательских программ: файл rc.local. По умолчанию он отсутствует в системе.

Раз мы уже создаем данный файл, добавим в него команду запуска демона natd, который отвечает за поддержку NAT.

Демон natd запускается из файла rc.conf. (Опять этот файл, поистине он играет ключевую роль для всей системы FreeBSD в целом!)

Механизм запуска этого файла из rc.conf выполняется посредством следующих переменных:

# -- путь к самому файлу natd
natd_program="/sbin/natd"
# Разрешить NAT (если firewall_enable == YES)
natd_enable="YES"
# Внешний интерфейс или IPaddress для использования
natd_interface=""
# Дополнительный флаги запуска natd
natd_flags=""

Но в этом случае мы будем использовать вызов демона natd посредством rc.local. Команда:

# vi /etc/rc.local

автоматически создает файл /etc/rc.local и открывает его на редактирование.

Добавляем в него следующие строки:

# Команда запуска natd
/sbin/natd -n rl0
# где «-n rl0» - имя интерфейса, на котором запускается NAT
#
# И запускаем наш скрипт для установки правил для файервола:
/bin/sh /etc/rc.firewall.run

Перезагружаемся и проверяем доступ к нужным ресурсам Интернета с компьютера из локальной сети.

1. Эви Немет, Гарт Снайдер, Скотт Сибасс, Трент Р.Хейн. UNIX. Руководство системного администратора. «BHV», «Питер», 2004 г.
2. Алексей Федорчук, Алексей Торн. FreeBSD. Установка, настройка, использование. BHV, 2003 г.
3. Филипп Торчинский. Практическое пособие администратора UNIX. «Символ», 2003 г.

Не так давно нужно было поставить гейт в Интернет для одного интернет-кафе. Кафе имело доступ к Интернету через ADSL-модем с Ethernet интерфейсом и локалку на 50 компьютеров со статическими адресами. Решено было поставить именно шлюз, а не купить обычной роутер с NAT, так как в роутерах все равно крутится урезанный линукс, а шлюз на базе ПК имел гораздо больше возможностей. К тому с таким количеством компьютеров использование прокси-сервера для кеширования веб-страниц давало определенную экономию траффика. Машинка имела параметры уровня Pentium2-600 с 256 Mb оперативной памяти. Вариант установки оффтописка отпадал из-за слабых мощностей и ненадежности и отсутствия гибкости. К тому же FreeBSD идеально подходит для гейтов в силу малой требовательности ресурсов и надежности работы. Насколько мне известно по хоум-провайдингу, гейты на FreeBSD могут спокойно натить полосу до 500-600 mbit/sec

Итак, дано - установить FreeBSD на компьютер, настроить NAT, настроить прозрачный прокси.

Не буду утомлять читателей описанием установки, благо это подробно описано и иллюстрировано в .
После установки я , включив в него дополнительные опции, а именно

options IPFIREWALL #добавил поддержку файрволла
options IPFIREWALL_VERBOSE #логгирование
options IPFIREWALL_VERBOSE_LIMIT=100 #органичение количества записей в лог
options IPFIREWALL_DEFAULT_TO_ACCEPT #файерволл "открыт" по умолчанию
options IPFIREWALL_FORWARD
options IPDIVERT #включение поддержки перенаправления пакетов
options DUMMYNET #может понадобится для ограничения скорости

После пересборки ядра настала очередь правки /etc/rc.conf для включения NAT. NAT будет использовать в виде отдельного демона. У меня на шлюзе стояло 2 сетевые карточки, одна смотрела в интернет через модем (настроенный в режиме моста), вторая в локальную сеть.
Соотвественно, первая была re0 и имела адрес вида 213.230.x.x, вторая rl0 - адрес 192.168.0.1

Правим /etc/rc.conf

defaultrouter=213.230.x.x #указываем основной шлюз
ifconfig_re0="inet 213.230.x.x netmask 255.255.255.252" #задаем внешний интернетовский адрес
ifconfig_rl0="inet 192.168.0.1 netmask 255.255.255.0" #задаем внутренний адрес
gateway_enable="YES" #зайдествуем режим шлюза
natd_enable="YES" #включем NAT
nat_interface="re0" #указываем натируемый интерфейс
nat_flags="-f /etc/natd.conf" #файл настройки демона NAT
firewall_enable="YES"

nameserver 195.158.0.1
nameserver 195.158.0.3

После сохранения и перезагрузки (это не обязательно, можно поднять интерфейсы и демон не перезагружая, но проверить как что поднимается все же нужно), проверяем доступность в обоих сетках, пропинговав локальные машины и хосты в интернете.
Уже на данном этапе интернет доступен локальным компьютерам, единственное что нужно дополнительно настроить на них, так это указать на них шлюз по умолчанию 192.168.0.1 и в строке DNS-сервера также прописать 192.168.0.1

Пришла очередь поставить squid. Для начала обновляем .
После успешного обновления переходим собственно к установке.

#cd /usr/ports/www/squid31/
#make install clean

После окончания установки идем править файл настройки squid, находящегося по адресу /usr/local/etc/squid/squid.conf


# Adapt to list your (internal) IP networks from where browsing
# should be allowed
#Здесь указываются подсетки, которые имеют доступ к нашей проксе, у нас подсетка 192.168.0.0, потому оставляем только ее
#acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
#acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/24 # Указываем сеть 192.168.0.1-254
#IPv6 Not Available:acl localnet src fc00::/7 # RFC 4193 local private network range
#IPv6 Not Available:acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80 # https
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # httpss
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # https-mgmt
acl Safe_ports port 488 # gss-https
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling https
acl CONNECT method CONNECT

#
# Recommended minimum Access Permission configuration:
#
# Only allow cachemgr access from localhost
https_access allow manager localhost
https_access deny manager

# Deny requests to certain unsafe ports
https_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
https_access deny CONNECT !SSL_ports

# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on "localhost" is a local user
#https_access deny to_localhost

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
https_access allow localnet
https_access allow localhost

# And finally deny all other access to this proxy
https_access deny all

# Squid normally listens to port 3128 - Порт, на котором будет висеть прокси
https_port 127.0.0.1:3128 intercept #transparent для версий ниже 3.1

# We recommend you to use at least the following line.
hierarchy_stoplist cgi-bin ?

# Uncomment and adjust the following to add a disk cache directory.
cache_dir ufs /var/squid/cache 500 16 256
cache_mem 256 MB
# Leave coredumps in the first cache dir
coredump_dir /var/squid/cache

# Add any of your own refresh_pattern entries above these.
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|?) 0 0% 0
refresh_pattern . 0 20% 4320

#/usr/local/sbin/squid -z

Стартуем его

#/usr/local/etc/rc.d/squid -start

Если Squid успешно запустился - открываем любой бразуер, указываем нашу проксю вида 192.168.0.1:3128 и пробуем открыть например тот же google.com.
Открылся? Замечательно, вписываем в /etc/rc.conf

squid_enable="YES"

И делаем его прозрачным, добавив правило в файрволл.

ipfw add fwd 192.168.0.1,3128 tcp from 192.168.0.0/24 to any 80

После этого, на клиентском компьютере убираем прокси с браузера и пробуем открыть другую страницу. Паралелльно можно смотреть файл /var/log/squid/access.log, в котором фиксируются обращения к прокси. Если все работает, в логи появляются записи - поздравляю. Теперь все веб-запросы от клиентских компьютеров будут прозрачно кешироваться, экономя вам траффик.
На этом первоначальная настройка гейта завершена.

UPD. Иногда нужно раздавать интернет не всем в локальной сети, а некоторым пользователям. Тогда можно прикрутить к сквиду авторизацию. Это делается путем добавления в конфиг

auth_param basic program /usr/local/libexec/squid/ncsa_auth /usr/local/etc/squid/internet_users
auth_param basic children 5
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
auth_param basic casesensitive off

acl squidusers proxy_auth REQUIRED

# htpasswd -c /etc/squid/internet_users synergix
New password: *******
Re-type new password: *******
Adding password for user synergix

Ключ -с необходимо указывать только один раз, при создании файла с паролями. В последующем добавлять пользователей нужно без этого ключа. Итак, мы получили файл с примерно таким содержимым.


synergix:89XzEEI/P0e56

Где synergix - имя пользователя, а 89XzEEI/P0e56 - хеш его пароля. Для добавления нового пользователя в существующий файл необходимо выполнить следующую команду

# htpasswd -b /etc/squid/internet_users second_user 1234567
Adding password for user second_user

Посмотрим -

# cat /etc/squid/internet_users
syenrgix:89XzEEI/P0e56
second_user:EAJezc5eLXrV2

Выставим права для файла

# chmod 440 /usr/local/etc/squid/internet_users
# chown squid:squid /usr/local/etc/squid/internet_users

#/usr/local/etc/rc.d/squid reload