zed.0xff.me

ng_sbinat – (Symmetric | Simple) Bidirectional NAT

1. что это?

это такой простой двусторонний нат.
работает в ядре freebsd, внутри нетграфа.
вешается непосредственно на ng_ether интерфейс (напр. em0)

2. для чего это?

для трансляции одной /16 сетки в другую (например 192.168.×.y <—> 10.22.×.y)

3. требования?

  • freebsd >= 7.0
  • netgraph
  • сорцы ядра
  • прямые руки :)

4. где взять / more info ?

http://github.com/zed-0xff/ng_sbinat

[PATCH] ng_netflow: ifIndex from vlan

Во время оптимизации ng_netflow и выносом его на отдельную машину возникла такая проблема, что вместе с логами трафика из ng_netflow нужно сохранять и номер vlan’а, в котором пришел этот трафик.
Самое очевидное – использовать для этого netflow-поле ifIndex, благо трафик собирается с единственного (пока) роутера, и физических интерфейсов на нём негусто, так что ifIndex фактически не используется.
Самое неочевидное – заставить ng_netflow прописывать в потоках в ifIndex номер vlan’а..

Я пошел недеструктивным путём, и постарался при добавлении нового функционала ничего не сломать :)
В результате в команду NGM_NETFLOW_SETCONFIG добавлено новое значение: NG_NETFLOW_CONF_VLAN = 16, и включается новый режим на интерфейсе так:
(вместо iface=0 и conf=19 пропишите соответственно номер интерфейса и флаги, которые вам нужны, обращая внимание на +16 к значению conf если нужен новый режим установки ifIndex по vlan’у)

1
2
3
ngctl msg netflow: setconfig \{ iface=0 conf=19 \}   # 16 = NG_NETFLOW_CONF_VLAN
                                                     #  2 = NG_NETFLOW_CONF_EGRESS
                                                     #  1 = NG_NETFLOW_CONF_INGRESS

а вот, собственно, и патч:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
diff -ur /usr/src/sys/netgraph/netflow/ng_netflow.c kld/ng_netflow.c
--- /usr/src/sys/netgraph/netflow/ng_netflow.c        2009-04-15 09:14:26.000000000 +0600
+++ kld/ng_netflow.c        2009-09-04 06:25:42.000000000 +0600
@@ -486,7 +486,7 @@
         struct m_tag *mtag;
         int pullup_len = 0;
         int error = 0, bypass = 0;
-        unsigned int src_if_index;
+        unsigned int src_if_index = 0;
 
         if (hook == priv->export) {
                 /*
@@ -585,6 +585,10 @@
                         M_CHECK(sizeof(struct ip));
                         eh = mtod(m, struct ether_header *);
                         ip = (struct ip *)(eh + 1);
+                        if( (m->m_flags & M_VLANTAG) && (iface->info.conf & NG_NETFLOW_CONF_VLAN) ){
+                                // tag is stored out-of-band
+                                src_if_index = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
+                        }
                         break;
                 case ETHERTYPE_VLAN:
                     {
@@ -596,6 +600,9 @@
                         if (ntohs(evh->evl_proto) == ETHERTYPE_IP) {
                                 M_CHECK(sizeof(struct ip));
                                 ip = (struct ip *)(evh + 1);
+                                if (iface->info.conf & NG_NETFLOW_CONF_VLAN){
+                                        src_if_index = evh->evl_tag;
+                                }
                                 break;
                         }
                     }
@@ -639,6 +647,10 @@
                 switch (ntohs(eh->ether_type)) {
                 case ETHERTYPE_IP:
                         ip = (struct ip *)(eh + 1);
+                        if( (m->m_flags & M_VLANTAG) && (iface->info.conf & NG_NETFLOW_CONF_VLAN) ){
+                                // tag is stored out-of-band
+                                src_if_index = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
+                        }
                         break;
                 case ETHERTYPE_VLAN:
                     {
@@ -646,6 +658,9 @@
 
                         evh = mtod(m, struct ether_vlan_header *);
                         ip = (struct ip *)(evh + 1);
+                        if (iface->info.conf & NG_NETFLOW_CONF_VLAN){
+                                src_if_index = evh->evl_tag;
+                        }
                         break;
                      }
                 default:
@@ -662,13 +677,16 @@
 
 #undef        M_CHECK
 
+
         /* Determine packet input interface. Prefer configured. */
-        src_if_index = 0;
-        if (hook == iface->out || iface->info.ifinfo_index == 0) {
-                if (m->m_pkthdr.rcvif != NULL)
-                        src_if_index = m->m_pkthdr.rcvif->if_index;
-        } else
-                src_if_index = iface->info.ifinfo_index;
+        if(!(iface->info.conf & NG_NETFLOW_CONF_VLAN) || src_if_index == 0){
+                src_if_index = 0;
+                if (hook == iface->out || iface->info.ifinfo_index == 0) {
+                        if (m->m_pkthdr.rcvif != NULL)
+                                src_if_index = m->m_pkthdr.rcvif->if_index;
+                } else
+                        src_if_index = iface->info.ifinfo_index;
+        }
 
         error = ng_netflow_flow_add(priv, ip, src_if_index);
 
diff -ur /usr/src/sys/netgraph/netflow/ng_netflow.h kld/ng_netflow.h
--- /usr/src/sys/netgraph/netflow/ng_netflow.h        2009-04-15 09:14:26.000000000 +0600
+++ kld/ng_netflow.h        2009-09-03 19:27:03.000000000 +0600
@@ -98,6 +98,7 @@
 #define NG_NETFLOW_CONF_EGRESS                2
 #define NG_NETFLOW_CONF_ONCE                4
 #define NG_NETFLOW_CONF_THISONCE        8
+#define NG_NETFLOW_CONF_VLAN                16
 
 /* This structure is passed to NGM_NETFLOW_SETCONFIG */
 struct ng_netflow_setconfig {

netgraph не умеет ловить исходящие пакеты в тэгированном интерфейсе

1
2
3
4
5
6
7
ifconfig vlan10 create
ifconfig vlan10 vlandev em0 vlan 10
ifconfig vlan10 10.10.0.2/24

ngctl mkpeer em0: tee lower left
ngctl name em0:lower tee0
ngctl conn em0: tee0: upper right

напускаем в em0 тэгированного трафика, либо смотрим на живом роутере. результат один и тот же:

nghook -a tee0: left2right – трафик есть.
nghook -a tee0: right2leftтрафика нет!!

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

по этой причине и пришлось вынести netflow на отдельную машину, что вцелом более правильно и красиво :)

оптимизировали ng_netflow

как было :( как стало :)

(картинки кликабельны)

FreeBSD & more than 32 arpd's

0. Предыстория

  • Есть фрибсд-сервер.
  • На сервере есть куча интерфейсов (~200).
  • На некоторых интерфейсах надо пускать arpd.

1. Bug

  • 16 arpd-ей запустились нормально.
  • На запуске 17-го получаем “arpd: bad interface configuration: not IP or Ethernet
  • Копание в исходниках показало что проблема в libdnet, в коем гвоздями прибито не юзать /dev/bpf’ы с номером более 32

3. Patch for /usr/ports/net/libdnet

1
2
3
4
5
6
7
8
9
10
11
--- src/eth-bsd.c.orig        2009-04-16 14:22:44.000000000 +0600
+++ src/eth-bsd.c        2009-04-16 14:23:31.000000000 +0600
@@ -45,7 +45,7 @@
         int i;
 
         if ((e = calloc(1, sizeof(*e))) != NULL) {
-                for (i = 0; i < 32; i++) {
+                for (i = 0; i < 256; i++) {
                         snprintf(file, sizeof(file), "/dev/bpf%d", i);
                         e->fd = open(file, O_WRONLY);
                         if (e->fd != -1 || errno != EBUSY)

4. FreeBSD PR: ports/133772

отложенный шеллбомбинг в freebsd 7.1 :)

(но необходим доступ на запись в /etc :-\ )

1
2
3
4
5
6
echo ipfw > /etc/ipfw
echo ipfw >> /etc/ipfw
echo ipfw >> /etc/ipfw
echo ipfw >> /etc/ipfw
echo ipfw >> /etc/ipfw
chmod +x /etc/ipfw

и всё жестоко встанет колом в 3 часа ночи :) (в 80-90% инсталляций)
и причину найти будет достаточно неочевидно.

PS: возможно сработает и на более старых версиях