Роутер на FreeBSD. Два канала связи. Основной + резервный.

FreeBSD, Заметки на полях Добавить комментарий

Не так давно друг попросил помочь с настройкой на FreeBSD возможности переключения каналов связи с сетью Интернет с основного на резервный (при неполадках на основном), и обратно (при восстановлении связи на основном канале).

Естественно хотелось бы – чтобы это происходило автоматом ;)

В результате поисков – была обнаружена статейка «2 канала на ОС FreeBSD«. Но в процессе реализации там были обнаружены некоторые опечатки и недоработки :)
В результате все было доведено до логического завершения. Решение предлагается далее.

Реализовывалось все это на FreeBSD 7.1-RELEASE.

Далее требуется установленный perl. (Подсказочка – установите просто Midnight Commander если у Вас его еще нет ;) При его инсталляции perl установится по зависимостям).

Далее нам потребуется PF. Но устанавливать его дополнительно, или пересобирать ядро вовсе нет необходимости. PF был интегрирован в основную систему, начиная с FreeBSD 5.3 в ноябре 2004. Единственный минус, что без пересборки ядра Вам не будут доступны ALTQ в PF. ALTQ (Alternate Queuing) предоставляет управление пропускной способностью Quality of Service (QoS), позволяющее гарантировать пропускную способность для различных сервисов на основе фильтрующих правил.

Включаем PF в файле /etc/rc.conf (Вносим и сохраняем).

  1. gateway_enable="YES" # Включить поддержку работы в режиме шлюза
  2. pf_enable="YES" # Включить PF (загрузить модуль если необходимо)
  3. pf_rules="/etc/pf.conf" # определение правил для pf
  4. pf_flags="" # дополнительные флаги для запуска pfctl
  5. pflog_enable="YES" # запустить pflogd(8)
  6. pflog_logfile="/var/log/pflog" # где pflogd должен сохранять протокол
  7. pflog_flags="" # дополнительные флаги для запуска pflogd
  8.  

Далее создаем конфигурационный файл /etc/pf.conf для PF, где прописываем все правила и фильтры.

  1. # Main Setting
  2.  
  3. ext_if_1="vr0" # IPS_1 - интерфейс первого канала
  4. ext_if_2="vr1" # IPS_2 - интерфейс второго канал
  5. int_if="rl0" # lan - интерфейс внутренний сети
  6. lo="lo0" # loopback
  7.  
  8. int_net="192.168.254.0/25" # LAN NETWORK
  9. ext_addr_1="10.199.88.111" # IPS_1 wan
  10. ext_addr_2="10.233.3.46" # IPS_2 wan
  11. int_addr="192.168.254.2" # LAN IP
  12.  
  13. gw_1="10.199.88.110" # IPS_1 gw
  14. gw_2="10.233.3.45" # IPS_2 gw
  15.  
  16. # services
  17.  
  18. tcp_svc="ssh"
  19.  
  20. #log - логирование пакетов
  21.  
  22. set loginterface $ext_if_1
  23. set loginterface $ext_if_2
  24. set loginterface $int_if
  25.  
  26. # skip iface - не фильтровать loopback,
  27. # многие сервисы используют данный интерфейс под системные вещи.
  28.  
  29. set skip on lo0
  30.  
  31. # scrub
  32. scrub in all
  33.  
  34. # NAT
  35. # Натируем внешние интерфейсы
  36.  
  37. nat on $ext_if_1 inet from $int_net -> ($ext_if_1:0)
  38. nat on $ext_if_2 inet from $int_net -> ($ext_if_2:0)
  39. # INCOMING ROUTE
  40. # маршрутизирем весь входящий трафик, под условием, если пришел на тот то интерфейс,
  41. # то отправить необходимо ответ с того-то шлюза
  42. # плюс проставляем теги. Теги помогут нам корректно пробрасывать порты,
  43. # допустим у нас есть терминал сервер, пробросить можно следующим образом
  44. rdr on $ext_if_2 proto tcp from any to $ext_addr_2 port 3389 tag EXT_IF_B -> 192.168.254.17 port 3389
  45. rdr on $ext_if_1 proto tcp from any to $ext_addr_1 port 3389 tag EXT_IF_A -> 192.168.254.17 port 3389
  46. # BLOCK ALL
  47. # первоночально необходимо заблокировать весь входящий трафик
  48. block in
  49. # antispoof
  50. antispoof quick for $int_if
  51. # ICMP
  52. # разрешаем icmp на внешних интерфейсах и маршрутизирем их по свои шлюзам
  53. # чтобы не возникло ситуации пингуем один внешний адрес, а ответ идет по второму шлюзу.
  54. # IPS_1
  55. pass in on $ext_if_1 reply-to ($ext_if_1 $gw_1) inet proto icmp to ($ext_if_1) tag EXT_IF_A icmp-type echoreq code 0
  56. pass in on $ext_if_1 inet proto icmp from ($ext_if_1:network) to ($ext_if_1) icmp-type echoreq code 0
  57. # IPS_2
  58. pass in on $ext_if_2 reply-to ($ext_if_2 $gw_2) inet proto icmp to ($ext_if_2) tag EXT_IF_B icmp-type echoreq code 0
  59. pass in on $ext_if_2 inet proto icmp from ($ext_if_2:network) to ($ext_if_2) icmp-type echoreq code 0
  60. # allow tcp ports
  61. # разрешаем на внешних интерфейсах сервисы и маршрутизирем их, выше у нас разрешен только ssh
  62. # для udp аналогичная запись за изменением только proto tcp на proto udp
  63. # IPS_1
  64. pass in on $ext_if_1 reply-to ($ext_if_1 $gw_1) inet proto tcp to ($ext_if_1) port { $tcp_svc }
  65. pass in on $ext_if_1 inet proto tcp from ($ext_if_1:network) to ($ext_if_1) port { $tcp_svc }
  66. # IPS_2
  67. pass in on $ext_if_2 reply-to ($ext_if_2 $gw_2) inet proto tcp to ($ext_if_2) port { $tcp_svc }
  68. pass in on $ext_if_2 inet proto tcp from ($ext_if_2:network) to ($ext_if_2) port { $tcp_svc }
  69. # IPS_1
  70. pass in quick from ($ext_if_1:network) tagged EXT_IF_A keep state
  71. pass in quick reply-to ($ext_if_1 $gw_1) tagged EXT_IF_A keep state
  72. # IPS_2
  73. pass in quick from ($ext_if_2:network) tagged EXT_IF_B keep state
  74. pass in quick reply-to ($ext_if_2 $gw_2) tagged EXT_IF_B keep state
  75. # FIREWALL
  76. # разрешаем все во внутреннем пространстве шлюза
  77. pass out inet from (self:network)
  78. pass in inet proto icmp to (self:network)
  79. # LOCAL NETWORK
  80. # Разрешаем весь трафик на выход из локальной сети
  81. pass quick on $int_if
  82. # OUTGOING ROUTE
  83. # Маршрутизирем исходящий трафик
  84. pass out route-to ($ext_if_1 $gw_1) inet from ($ext_if_1) keep state
  85. pass out route-to ($ext_if_2 $gw_2) inet from ($ext_if_2) keep state
  86. pass out inet from { $ext_if_1 $ext_if_2 } to (self:network)
  87.  

Этого файла с правилами будет достаточно чтобы обеспечить «хождение трафика» по двум каналам, с правильной маршрутизацией.
В подробности впадать не буду, если захотите посмотреть, что означает каждое правило, то почитайте документацию к PF.

Далее, необходимо в /etc/rc.conf добавить основной шлюз:

  1. defaultrouter="10.199.88.110"
  2.  

Тот же самый IP, который прописывали как gw_1 в файле /etc/pf.conf

Cохраняем.

Далее нужно поставить пакетик для перла NET_PING:

  1. cd /usr/ports/net/p5-Net-Ping
  2. make install clean
  3.  

Далее напишем собственно скрипт для переключения каналов в случае падение основного, и обратно в случае поднятия.

  1.  
  2. #!/usr/bin/perl -w
  3. use strict;
  4. use warnings;
  5.  
  6. use Net::Ping;
  7. my $p = Net::Ping->new("icmp");
  8. my $gw1 = "10.199.88.111"; # шлюз по умолчанию
  9. my $gw2 = "10.233.3.46"; # резервный шлюз
  10. my $now = localtime time;
  11. my $log_file = "/var/log/change_route.log"; # путь и имя файла лог
  12.  
  13. my $command = `netstat -rn | grep default`;
  14. my @b = split('\s+',$command,3);
  15.  
  16. if ($p->ping($gw1,0.05)){
  17. print "host $gw1 is ok\n";
  18. if($b[1] ne $gw1){
  19. if($b[1] eq ""){
  20. `route add default $gw1`;
  21. }else{
  22. `route change default $gw1`;
  23. open(LOG,">>$log_file");
  24. print LOG "$now Route change to $gw1\n";
  25. close(LOG);
  26. }
  27. }
  28. }else{
  29. print "host $gw1 not responding .\n";
  30. if($b[1] ne $gw2){
  31. `route change default $gw2`;
  32. open(LOG,">>$log_file");
  33. print LOG "$now Route change to $gw2\n";
  34. close(LOG);
  35. }
  36. }
  37. $p->close();#
  38.  

Сохраняем скрипт, делаем его исполняемым

  1. chmod +x имя_файла_вашего_скрипта.pl
  2.  

И закидываем в крон на исполнение раз в минуту. Т.е. добавляем в файл /etc/crontab строку

  1. * * * * * root perl /путь_к_файлу/имя_вашего_скрипта.pl
  2.  

Все. Перегружаем сервер! И если сделали все верно и правильно, то у Вас все уже должно работать ;)

5 ответов to “Роутер на FreeBSD. Два канала связи. Основной + резервный.”

  1. Ivanov Says:

    Видел уже где то…

  2. SuperMan Says:

    Спс

  3. Kostya Says:

    Хм..

  4. Elena Says:

    ……

    Кино фильмы онлайн

  5. Сергей Says:

    СПС.

    Я тут

Ответить

Вы должны войти на сайт чтобы просмотреть это сообщение.

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Войти