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: возможно сработает и на более старых версиях