Выпускаем локальную сеть в Интернет используя сервер на FreeBSD и ng_nat [2009]
Для работы этого примера необходимо иметь подгруженный ng_ipfw.ko
Убедиться в его наличии можно командой:
/sbin/kldstat
Id Refs Address Size Name 1 11 0xc0400000 4eddc0 kernel .......................... 7 1 0xc9e22000 2000 ng_ipfw.ko
Если у вас ng_ipfw.ko не загружен, то подгрузите его:
/sbin/kldload /boot/kernel/ng_ipfw.ko
После того как ng_ipfw.ko подгружен, в выводе команды:
/usr/sbin/ngctl list
появится строчка вида:
Name: ipfw Type: ipfw ID: 00000023 Num hooks: 2
Без загруженного ng_ipfw.ko при попытке выполнить команды ngctl`а вы будете получать сообщение:
ngctl: send msg: No such file or directory
а при попытке добавить правило в ipfw получите:
ipfw: getsockopt(IP_FW_ADD): Invalid argument
Настройка ng_nat проста и сводится к простенькому скрипту:
Для примера будем NAT`ить подсеть 172.16.5.96/27 через IP-адрес 192.168.20.8 на внешнем интерфейсе fxp0.
#!/usr/bin/perl
$ip='192.168.20.8'; $iface='fxp0'; $net='172.16.5.96/27'; $cmd=sprintf("/usr/sbin/ngctl -f - << -EOF mkpeer ipfw: nat 60 out name ipfw:60 nat connect ipfw: nat: 61 in msg nat: setaliasaddr %s ",$ip); system($cmd);
###добавляем необходимые правила в firewall $cmd=sprintf("/sbin/ipfw add 1000 netgraph 61 all from any to %s via %s in",$ip,$iface); system($cmd); $cmd=sprintf("/sbin/ipfw add 1010 netgraph 60 all from %s to any via %s out",$net,$iface); system($cmd);
где: $ip - IP адрес, через который будет работать нат (который смотрит в интернет) $iface - ваш внешний интерфейс $net - IP подсеть, которую мы собираемся NAT`ить netgraph - правило в firewall, аналогично divert, только перенаправляет трафик не в socket, а в ноду netgraph, 60, 61 - адреса исходящего и входящего хуков.
Если делать руками в консоле, то команды выглядят следующим образом:
###создаем ноду nat и подключаем к ipfw /usr/sbin/ngctl mkpeer ipfw: nat 60 out ###даем ноде имя "natA" /usr/sbin/ngctl name ipfw:60 natA ###соединяем входящие и исходящие хуки для "natA" /usr/sbin/ngctl connect ipfw: natA: 61 in ###посылаем управляющее сообщение в виде IP адреса, через который будет работать нат. /usr/sbin/ngctl msg natA: setaliasaddr 192.168.20.8
Если все работает, то мы можем посмотреть вывод следующей команды:
#test:~:ngctl show natA: Name: nat Type: nat ID: 00000029 Num hooks: 2 Local hook Peer name Peer type Peer ID Peer hook ---------- --------- --------- ------- --------- in ipfw ipfw 00000001 61 out ipfw ipfw 00000001 60
Также можно посмотреть все целиком:
#test:~:ngctl list
Как выключить этот NAT ?
Просто выполнить команду:
#test:~:ngctl shutdown natA:
Заметка:
Если вы хотите запустить NAT на нескольких внешних IP-адресах, но не забывайте изменять имена нод (в примере natA) и номера хуков (в примере 60,61) т.к. они должны быть уникальны для каждого из процессов.
Не путайте in и out в создаваемой ноде и правилах ipfw.