packet filter: борьба с якорями

Настройка сетевых служб, маршрутизации, фаерволлов. Проблемы с сетевым оборудованием.
Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
GHopper
мл. сержант
Сообщения: 83
Зарегистрирован: 2008-12-11 15:52:22

packet filter: борьба с якорями

Непрочитанное сообщение GHopper » 2008-12-11 15:58:01

Здравствуйте!

Код: Выделить всё

[root@gh_gate /etc]# uname -a
FreeBSD gh_gate.home 7.0-RELEASE FreeBSD 7.0-RELEASE #4: Mon Dec  1 23:15:46 UTC 2008     ghopper@gh_gate.home:/usr/src/sys/i386/compile/gh_kernel  i386
Имелся пакетный фильтр ipfw. Не справляется с нагрузкой! Решил уйти на PF

Код: Выделить всё

[root@gh_gate /etc]# cat /usr/src/sys/i386/conf/gh_kernel
...
# PF
device          pf
device          pflog
device          pfsync

options         ALTQ
options         ALTQ_CBQ                # Class Bases Queuing (CBQ)
options         ALTQ_RED                # Random Early Detection (RED)
options         ALTQ_RIO                # RED In/Out
options         ALTQ_HFSC               # Hierarchical Packet Scheduler (HFSC)
options         ALTQ_PRIQ               # Priority Queuing (PRIQ)
options         ALTQ_NOPCC              # Required for SMP build
##

options         NETGRAPH
options         NETGRAPH_BPF
options         NETGRAPH_BRIDGE
options         NETGRAPH_DEVICE
options         NETGRAPH_ECHO
options         NETGRAPH_EIFACE
options         NETGRAPH_ETHER
options         NETGRAPH_IFACE
options         NETGRAPH_KSOCKET
options         NETGRAPH_L2TP
options         NETGRAPH_MPPC_ENCRYPTION
options         NETGRAPH_NETFLOW
options         NETGRAPH_ONE2MANY
options         NETGRAPH_PPP
options         NETGRAPH_PPPOE
options         NETGRAPH_PPTPGRE
options         NETGRAPH_SOCKET
options         NETGRAPH_TCPMSS
options         NETGRAPH_TEE
options         NETGRAPH_TTY
options         NETGRAPH_VJC
#options         NETGRAPH_IPFW
#options         NETGRAPH_NAT

## ipfw options
#options IPFIREWALL
#options IPFIREWALL_VERBOSE
#options IPFIREWALL_VERBOSE_LIMIT=1000
#options IPDIVERT
#options DUMMYNET
Очень хороший фаервол - удобно администрируется, быстрый нат и огромный возможности. Но одна проблема - никак не могу освоиться с динамическим добавлением правил.

Код: Выделить всё

[root@gh_gate /etc]# cat /etc/pf.conf1
icmp_types="{echoreq, unreach}"

block on rl0 all
pass out on rl0 keep state
pass in on rl0 inet proto icmp all icmp-type $icmp_types
#pass in on rl0 inet proto tcp from any to any port 22
anchor goodguys
[root@gh_gate /etc]# pfctl -n -f /etc/pf.conf
[root@gh_gate /etc]# pfctl -f /etc/pf.conf
[root@gh_gate /etc]# pfctl -sr
block drop on rl0 all
pass out on rl0 all flags S/SA keep state
pass in quick on rl0 inet proto icmp all icmp-type echoreq keep state
pass in quick on rl0 inet proto icmp all icmp-type unreach keep state
anchor "goodguys" all
[root@gh_gate /etc]# pfctl -a goodguys:ssh -sr
pfctl: DIOCGETRULES: Invalid argument
После этого с клиента проверяю:

Код: Выделить всё

ghopper@main ~ $ ping 192.168.0.1
ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.302 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.212 ms

--- 192.168.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.212/0.257/0.302/0.045 ms

ghopper@main ~ $ ssh ghopper@192.168.0.1
ssh: connect to host 192.168.0.1 port 22: Connection timed out
Все ок! Теперь хочу динамически дать доступ до ssh. Без перезагрузки основных правил!

Код: Выделить всё

[root@gh_gate /etc]# echo "pass in on rl0  proto tcp from any to any port 22" | pfctl -a goodguys:ssh -f -
[root@gh_gate /etc]# pfctl -a goodguys:ssh -sr
pass in on rl0 proto tcp from any to any port = ssh flags S/SA keep state
Пробую подключиться с клиента:

Код: Выделить всё

ghopper@main ~ $ ssh ghopper@192.168.0.1
ssh: connect to host 192.168.0.1 port 22: Connection timed out
Думаю: "может я что-то где-то глючу?!" Переписываю файлик pf.conf:

Код: Выделить всё

[root@gh_gate /etc]# cat pf.conf
icmp_types="{echoreq, unreach}"

block on rl0 all
pass out on rl0 keep state
pass in on rl0 inet proto icmp all icmp-type $icmp_types
pass in on rl0 inet proto tcp from any to any port 22
anchor goodguys
[root@gh_gate /etc]# pfctl -f /etc/pf.conf
С клиента пробую подключиться к ssh-порту - все получается! Т.е. проблема кроется именно в том, что pf не хочет залазить в якорные правила. Как победить проблему?

P.S. Изучаю PF с http://www.opennet.ru/base/net/pf_faq.txt.html
P.P.S. На самом деле у меня ситуация намного запутаннее - два провайдера (PPPOE,PPTP) и сеть с клиентами (PPTP). Нужно для каждого поднятого тоннеля динамически добавлять новые правила.

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
zingel
beastie
Сообщения: 6204
Зарегистрирован: 2007-10-30 3:56:49
Откуда: Moscow
Контактная информация:

Re: packet filter: борьба с якорями

Непрочитанное сообщение zingel » 2008-12-12 15:01:35

то, что ты задублировал тему на другом форуме - не решит твою проблему быстрее, тем более на линуховом форуме.

Код: Выделить всё

pfctl -a 'goodguys:ssh' -sr
Z301171463546 - можно пожертвовать мне денег

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35228
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: packet filter: борьба с якорями

Непрочитанное сообщение Alex Keda » 2008-12-12 15:13:52

zingel писал(а):то, что ты задублировал тему на другом форуме - не решит твою проблему быстрее, тем более на линуховом форуме
это опеннет-то линуксовый?
при том тчо сама машины на 6.x фре? =))
Убей их всех! Бог потом рассортирует...

Аватара пользователя
zingel
beastie
Сообщения: 6204
Зарегистрирован: 2007-10-30 3:56:49
Откуда: Moscow
Контактная информация:

Re: packet filter: борьба с якорями

Непрочитанное сообщение zingel » 2008-12-12 15:17:56

не, он на линухфоруме создал тему
Z301171463546 - можно пожертвовать мне денег

GHopper
мл. сержант
Сообщения: 83
Зарегистрирован: 2008-12-11 15:52:22

Re: packet filter: борьба с якорями

Непрочитанное сообщение GHopper » 2008-12-12 15:56:16

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

По поводу linux и FreeBSD. Я думаю в данном вопросе это непринципиально.

По сути вопроса - может еще какие данные предоставить?

Аватара пользователя
zingel
beastie
Сообщения: 6204
Зарегистрирован: 2007-10-30 3:56:49
Откуда: Moscow
Контактная информация:

Re: packet filter: борьба с якорями

Непрочитанное сообщение zingel » 2008-12-12 16:02:24

там проблема в обработке аргумента для параметра, нужно одинарные ковычки писать:

Код: Выделить всё

int
pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
    char *anchorname, int depth)
{
        struct pfioc_rule pr;
        u_int32_t nr, mnr, header = 0;
        int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
        int len = strlen(path);
        int brace;
        char *p;

        if (path[0])
                snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
        else
                snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);

        memset(&pr, 0, sizeof(pr));
        memcpy(pr.anchor, path, sizeof(pr.anchor));
        if (opts & PF_OPT_SHOWALL) {
                pr.rule.action = PF_PASS;
                if (ioctl(dev, DIOCGETRULES, &pr)) {
                        warn("DIOCGETRULES");
                        goto error;
                }
                header++;
        }
        pr.rule.action = PF_SCRUB;
        if (ioctl(dev, DIOCGETRULES, &pr)) {
                warn("DIOCGETRULES");
                goto error;
        }
Z301171463546 - можно пожертвовать мне денег

GHopper
мл. сержант
Сообщения: 83
Зарегистрирован: 2008-12-11 15:52:22

Re: packet filter: борьба с якорями

Непрочитанное сообщение GHopper » 2008-12-31 16:58:26

Удалось выяснить, что если писать

Код: Выделить всё

echo "pass in proto tcp from 192.168.0.2 to any port 22" | pfctl -a goodguys -f -
вместо

Код: Выделить всё

echo "pass in on rl0  proto tcp from any to any port 22" | pfctl -a goodguys:ssh -f -
то правила в якоре goodguys обрабатываются!

В документации http://www.opennet.ru/base/net/pf_faq.txt.html написано, что можно использовать создавать именованные правила в якорях (anchor:subname), тогда почему у меня этот трюк не проканал? И как на якорь goodguys повесить правила отдельно для ng3 и ng4 интерфейса? Ведь это разные клиенты, поэтому при подключении/отключении каждого из них нужно соответственно добавлять/удалять правила? Кол-во клиентов заранее неизвестно.

GHopper
мл. сержант
Сообщения: 83
Зарегистрирован: 2008-12-11 15:52:22

Re: packet filter: борьба с якорями

Непрочитанное сообщение GHopper » 2008-12-31 19:44:07

Читайте ман господа! Даже такой уважаемый ресурс, как opennet допускает ошибки!

Код: Выделить всё

...
     Anchors may end with the asterisk (`*') character, which signifies that
     all anchors attached at that point should be evaluated in the alphabeti-
     cal ordering of their anchor name.  For example,

           anchor "spam/*"

     will evaluate each rule in each anchor attached to the spam anchor.  Note
     that it will only evaluate anchors that are directly attached to the spam
     anchor, and will not descend to evaluate anchors recursively.
...
По итогу - в конфиге пишем

Код: Выделить всё

icmp_types="{echoreq, unreach}"

block on rl0 all
pass out on rl0 keep state
pass in on rl0 inet proto icmp all icmp-type $icmp_types
anchor "goodguys/*"
А правила добавляем так:

Код: Выделить всё

echo "pass in on rl0  proto tcp from any to any port 22" | pfctl -a goodguys/ssh -f -
И все работает! ;)

GHopper
мл. сержант
Сообщения: 83
Зарегистрирован: 2008-12-11 15:52:22

Re: packet filter: борьба с якорями

Непрочитанное сообщение GHopper » 2009-01-01 10:48:59

Следующая сложность, с которой мне пришлось столкнуться, при переходе на PF:
При поднятии интефейса запускается сктипт:

Код: Выделить всё

#!/bin/sh

echo "pass in quick on $1 proto tcp from $4 to $1:network port {ftp,ssh,http,https,3306,domain} keep state" \
    | /sbin/pfctl -a "pptp_client_anchor/$1" -f -

echo "pass in quick on $1 proto udp from $4 to $1:network port {domain} keep state" \
    | /sbin/pfctl -a "pptp_client_anchor/$1" -f -

echo "nat on ng0 from $4 to any -> (ng0)" | /sbin/pfctl -a "nat_pptp_client_anchor/$1" -f -

sleep 5
/etc/rc.d/named restart
т.е. для каждого нового соединения будет свой собственный подъякорь в pptp_client_anchor/ngX и nat_pptp_client_anchor/ngX. При отключении пользователя записи из pptp_client_anchor/ngX и nat_pptp_client_anchor/ngX удаляются другим скриптом. Все бы хорошо, да вот две проблемки:

1. при выполнении этого скрипта в pptp_client_anchor записывается только последнее правило, т.е. последовательно выполнив команды в консоле

Код: Выделить всё

echo "pass in quick on ng2 proto tcp from 192.168.1.2 to ng2:network port {ftp,ssh,http,https,3306,domain} keep state" \
    | /sbin/pfctl -a "pptp_client_anchor/ng2" -f -

echo "pass in quick on ng2 proto udp from 192.168.1.2 to ng2:network port {domain} keep state" \
    | /sbin/pfctl -a "pptp_client_anchor/ng2" -f -
мы найдет только последнее правило в якоре pptp_client_anchor/ng2. т.е. при добавлении правил командой /sbin/pfctl -a "pptp_client_anchor/ng2" -f - все существующие в pptp_client_anchor/ng2 правила пропадают.

2. Правила для ната. Приходится явно указывать интерфейс, адрес которого будет подставлятся в ip-пакеты. Но у меня два интерфейса до провайдеров и таблица маршрутизации между ними. Т.е. на один ресурс я могу идти через ng0 (первый провайдер), а на другой через ng1(второй провайдер) интерфейсы и заранее мне неизвестно с какого адреса пакеты должны выходить (это записано в таблице маршрутизации). Сейчас у меня пакеты выходят из разных интерфейсов, но возвращаются всегда на один (прописанные в nat_pptp_client_anchor). Это как-то неправильно... в ipfw такой проблемы вообще небыло.