Продолжим нашу тему домашнего роутера на Freebsd.
В этом посте я опишу как сделать bridge из wi-fi и lan, hostapd, который позволит управлять wi-fi точкой доступа (например мы сможем поставить шифрование WPA2-PSK), а так же настроим DHCP для FreeBSD. Для тех кому нужен только wi-fi (или lan) могут настроить так же, как и здесь опустив настройку бриджа.
Итак – мы собрали ядро в необходимыми параметрами и устройством if_bridge.
По команде ifconfig -a мы увидим все сконфигурированные и не сконфигурированные интерфейсы в системе:
# ifconfig -a rl0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=8<VLAN_MTU> ether 00:1e:8c:0f:ff:ff inet 172.16.56.63 netmask 0xffffffc0 broadcast 172.16.56.255 media: Ethernet autoselect (100baseTX <full-duplex>) status: active ath0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 2290 ether 00:24:01:03:01:2a media: IEEE 802.11 Wireless Ethernet autoselect mode 11g <hostap> status: no carrier rl1: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=8<VLAN_MTU> ether 00:0f:ea:4d:25:24 media: Ethernet autoselect (100baseTX <full-duplex>) status: no carrier plip0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> metric 0 mtu 1500 lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 options=3<RXCSUM,TXCSUM> inet6 fe80::1%lo0 prefixlen 64 scopeid 0x5 inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 nd6 options=3<PERFORMNUD,ACCEPT_RTADV>
Отлично. Мы будем работать с интерфейсами rl1 и ath0, которые являются LAN и WI-FI соответственно. rl0 – это интерфейс, который смотрит во внутреннею локалку провайдера. К нему мы вернемся только тогда, когда будем настраивать маршрутизацию с помощью IPFW.
Итак, добавим в /etc/rc.conf конфигурацию нашей локальной сети:
cat /etc/rc.conf hostname="megarouter.local" gateway_enable="YES" #обязательный параметр inetd_enable="YES" #не обязательный параметр, но лучше оставить на всякий пожарный. Потом может пригодиться sshd_enable="YES" #хотим же мы уметь удаленно управлять нашим "роутером"? ifconfig_rlinet #настройка интерфейса на внешку. firewall="/sbin/ipfw" #путь до ipfw. firewall_enable="YES" firewall_script="/etc/firewall.sh" firewall_logging="YES" hostapd_enable="YES" #запускаем hosapd для wifi (тем кто wi-fi не использует - можно отключить) Собираем их портов. defaultrouter="172.16.56.1" #путь до "основного шлюза" для внешнего интерфейса. dhcpd_enable="YES" dhcpd_conf="/usr/local/etc/dhcpd.conf" dhcpd_ifaces="bridge0" #интерфейс, по которому dhcpd будет работать if_ath_load="YES" ifconfig_ath0="up" wlans_athwlan0" cloned_interfaces="bridge0" ifconfig_bridge0="inet 192.168.1.1 netmask 255.255.255.0 addm wlan0 addm rl1 up" create_args_wlan0="wlanmode hostap" ifconfig_wlan0="up ssid freebsdap mode 11g channel 10" ifconfig_rl1="up" natd_enable="YES" #запускаем natd natd_interface="rl0" natd_flags="-m -u -f /etc/natd.conf"
Вроде бы с основами все.
Теперь конфиг dhcp сервера, который будет выдавать ip:
option domain-name "router.local"; option domain-name-servers 8.8.8.8, 8.8.4.4; default-lease-time 720000; max-lease-time 720000; min-lease-time 720000; ddns-update-style none; authoritative; log-facility local7; subnet 192.168.1.0 netmask 255.255.255.0 { range 192.168.1.2 192.168.1.250; option routers 192.168.1.1; option subnet-mask 255.255.255.0; option netbios-name-servers 192.168.1.1; option netbios-dd-server 192.168.1.1; option netbios-node-type 8; option broadcast-address 192.168.1.255; }
Все. Теперь запускаем dhcpd и после перезагрузки мы уже раздаем ипшники направо и налево по указанному в rc.conf интерфейсу.
Осталось только настроить hostapd, который отвечает за безопасность нашего wi-fi:
interface=wlan0 driver=bsd logger_syslog=-1 logger_syslog_level=2 logger_stdout=-1 logger_stdout_level=2 debug=4 dump_file=/tmp/hostapd.dump ctrl_interface=/var/run/hostapd ctrl_interface_group=wheel ssid=freebsdap wpa=1 wpa_passphrase=p@ssw0rd wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP CCMP
Здесь тоже все предельно понятно по-моему.
Итак, осталась самая малость. Это файл конфигурации ipfw. У меня он находится в /etc/firewall.sh:
#!/bin/sh # для начала вводим переменные - для нашего же удобства, чтобы не # вводить по сотне раз одно и то же, а потом искать почему не работает, # и в итоге выяснять, что ошибся IP адресом в одном из правил FwCMD="/sbin/ipfw" # собственно где лежит бинарник ipfw LanOut="xl0" # внешний интерфейс LanIn="sis0" # внутренний интерфейс IpOut="222.222.222.222" # внешний IP адрес машины IpIn="192.168.20.254" # внутренний IP машины NetMask="24" # маска сети (если она разная для внешней # и внутренней сети - придётся вводить ещё # одну переменную, но самое забавное, что # можно и забить - оставить 24 - всё будет # работать, по крайней мере я пробовал - # работаало на 4-х машинах, в разных сетях, # с разными масками - настоящими разными! но - # это неправильно.) NetIn="192.168.20.0" # Внутренняя сеть # Сбрасываем все правила: ${FwCMD} -f flush # Проверяем - соответствует ли пакет динамическим правилам: ${FwCMD} add check-state # Разрешаем весь траффик по внутреннему интерфейсу (петле) # Вообще я во многих местах читал что без него может ничё не заработать вообще # и прочие страшилки. Работает - почта, апач, .... А вот squid - не работает :) # так что без него и правда - никуда. ${FwCMD} add allow ip from any to any via lo0 # рубим попытки lo0 куда-то лезть и откуда-то лезть на lo0 (вот честно - ни # одного пакета по этим правилам не зарубилось за всё время... Может в этом # моё счастье? :)) ${FwCMD} add deny ip from any to 127.0.0.0/8 ${FwCMD} add deny ip from 127.0.0.0/8 to any # Вводим запреты: # режем частные сети на внешнем интерфейсе - по легенде он у нас # смотрит в интернет, а значит пакетам этим браться неоткуда на нём. # рубим частные сeти ${FwCMD} add deny ip from any to 10.0.0.0/8 in via ${LanOut} ${FwCMD} add deny ip from any to 172.16.0.0/12 in via ${LanOut} ${FwCMD} add deny ip from any to 192.168.0.0/16 in via ${LanOut} ${FwCMD} add deny ip from any to 0.0.0.0/8 in via ${LanOut} # рубим автоконфигуреную частную сеть ${FwCMD} add deny ip from any to 169.254.0.0/16 in via ${LanOut} # рубаем мультикастовые рассылки ${FwCMD} add deny ip from any to 240.0.0.0/4 in via ${LanOut} # рубим фрагментированные icmp ${FwCMD} add deny icmp from any to any frag # рубим широковещательные icmp на внешнем интерфейсе ${FwCMD} add deny log icmp from any to 255.255.255.255 in via ${LanOut} ${FwCMD} add deny log icmp from any to 255.255.255.255 out via ${LanOut} # а тут собственно файрволл и начался: # отправляем всех на frox ${FwCMD} add fwd ${IpIn},2121 tcp from ${NetIn}/${NetMask} to any 21 via ${LanOut} # отправляем всех на squid (в данном случае - прокси прозрачный) ${FwCMD} add fwd 127.0.0.1,3128 tcp from ${NetIn}/${NetMask} to any 80 via ${LanOut} # пропускаем траффик через трансляцию сетевых адресов (NAT) ${FwCMD} add divert natd ip from ${NetIn}/${NetMask} to any out via ${LanOut} ${FwCMD} add divert natd ip from any to ${IpOut} in via ${LanOut} # рубим траффик к частным сетям через внешний интерфейс # заметтьте - эти правила отличаются от тех что были выше! ${FwCMD} add deny ip from 10.0.0.0/8 to any out via ${LanOut} ${FwCMD} add deny ip from 172.16.0.0/12 to any out via ${LanOut} ${FwCMD} add deny ip from 192.168.0.0/16 to any out via ${LanOut} ${FwCMD} add deny ip from 0.0.0.0/8 to any out via ${LanOut} # рубим автоконфигуреную частную сеть ${FwCMD} add deny ip from 169.254.0.0/16 to any out via ${LanOut} # рубаем мультикастовые рассылки ${FwCMD} add deny ip from 224.0.0.0/4 to any out via ${LanOut} # рубаем мультикастовые рассылки ${FwCMD} add deny ip from 240.0.0.0/4 to any out via ${LanOut} # разрешаем все установленные соединения (если они установились - # значит по каким-то правилам они проходили.) ${FwCMD} add allow tcp from any to any established # разрешаем весь исходящий траффик (серверу-то в инет можно? :)) ${FwCMD} add allow ip from ${IpOut} to any out xmit ${LanOut} # разрешаем DNS снаружи (нам же надо узнавать IP по именам машин?) ${FwCMD} add allow udp from any 53 to any via ${LanOut} # разрешаем DNS входящий снаружи - если на этой машине работает named # и держит какую-то зону. В остальных случаях - не нужно ${FwCMD} add allow udp from any to any 53 via ${LanOut} # разрешаем UDP (для синхронизации времени - 123 порт) ${FwCMD} add allow udp from any to any 123 via ${LanOut} # разрешаем ftp снаружи (оба правила - для пасивного режима) # для узнавания портранджа по которому будет работать, лезем в #/usr/home/lissyara/>sysctl net.inet.ip.portrange.first # net.inet.ip.portrange.first: 49152 # /usr/home/lissyara/>sysctl net.inet.ip.portrange.last # net.inet.ip.portrange.last: 65535 ${FwCMD} add allow tcp from any to ${IpOut} 21 via ${LanOut} #Можно изгалиться примерно так, если есть желание, но я предпочитаю руками #${FwCMD} add allow tcp from any to ${IpOut} \ #`sysctl net.inet.ip.portrange.first | awk '{print $2}'`-\ #`sysctl net.inet.ip.portrange.last | awk '{print $2}'` via ${LanOut} ${FwCMD} add allow tcp from any to ${IpOut} 49152-65535 via ${LanOut} # разрешаем некоторые типы ICMP траффика - эхо-запрос, # эхо-ответ и время жизни пакета истекло ${FwCMD} add allow icmp from any to any icmptypes 0,8,11 # открываем снаружи 80 порт - если у нас есть WWW сервер на машине ${FwCMD} add allow tcp from any to ${IpOut} 80 via ${LanOut} # открываем снаружи 25 порт (SMTP) если на машине крутится почта #${FwCMD} add allow tcp from any to ${IpOut} 25 via ${LanOut} # открываем снаружи 22 порт - если надо будет ходить на машину по ssh ${FwCMD} add allow tcp from any to ${IpOut} 22 via ${LanOut} # открываем снаружи 143 порт(если надо смотреть почту снаружи по IMAP) ${FwCMD} add allow tcp from any to ${IpOut} 143 via ${LanOut} # открываем снаружи 110 порт(если надо смотреть почту снаружи по POP) ${FwCMD} add allow tcp from any to ${IpOut} 110 via ${LanOut} # по поводу следующих трёх правил, для tcp, udp и icmp - их можно # заменить одним правилом: #${FwCMD} add allow ip from any to any via ${LanIn} # но для удобства наладки и контроля происходящего я предпочитаю три отдельных # правила, хотя могут быть грабли - например протокол gre не пройдёт - # придётся стругать отдельное правило для него, типа #${FwCMD} add allow gre from any to any via ${LanIn} # итак: # разрешаем весь tcp траффик внутри локалки (на внутреннем интерфейсе) ${FwCMD} add allow tcp from any to any via ${LanIn} # разрешаем весь udp траффик внутри локалки (на внутреннем интерфейсе) ${FwCMD} add allow udp from any to any via ${LanIn} # разрешаем весь icmp траффик внутри локалки (на внутреннем интерфейсе) ${FwCMD} add allow icmp from any to any via ${LanIn} # запрещаем всё и всем. Если тип файрволла не open то это правило добавится # автоматически, но всё-же ну его. Лучше сам. Надёжней. ${FwCMD} add deny ip from any to any
Конфиги для ipfw я брал отсюда, за что lissyar’е отдельное огромное спасибо.
Итак, после перезагрузки мы получаем полноценный, работоспособный роутер, который готов служить нам верой и правдой достаточно долго. Я же ещё добавил на него nginx, proftpd, который отвечает у меня за файлопомойку и samba, которая так же файлопомолит в сети :)