Just noticed the following issue:
when ipt_netflow is used with kernels 2.6.28 and higher versions,
src_if and dst_if fields in netflow records does not correspond
to real interface indexes:
ipt_netflow: new (1) 2:0 SRC=10.10.16.2:22 DST=10.10.16.31:58196
ipt_netflow: new (2) 2:0 SRC=10.10.16.31:58196 DST=10.10.16.2:22
(10.10.66.2 - is local ip)
With kernel 2.6.27.27 and earlier indexes are correct:
ipt_netflow: new (3) -1:2 SRC=10.10.16.2:22 DST=10.10.16.31:54733
ipt_netflow module versions: 1.6, 1.5.1
kernels (vanilla): 2.6.28.10, 2.6.29.2, 2.6.30.2
iptables package: 1.4.3.2, 1.4.4
OS: debian Gnu/Linux 5.0.2 lenny
module params: modprobe ipt_NETFLOW destination=127.0.0.1:12001 debug=3
p.s. maybe it's not ipt_NETFLOW's issue at all but a result of some changes
in netfilter code. Tried to add debug output (printk) to netflow_target() handler
and it looks like net_device structs 'if_in' and 'if_out' (arguments)
in fact contain the wrong values.
How do you know that indexes are wrong? What is wrong in them or what they should be, in your opinion?
Btw. Interface indexes for your box should be visible by 'ip link' command (iproute2), first number in line for each interface is it's index.
Example:
1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue
^ this is ifi_index.
In the above example two lines correspond to packets
going to the opposite directions:
This one is outgoing locally originated packet
ipt_netflow: new (1) 2:0 SRC=10.10.16.2:22 DST=10.10.16.31:58196
and this is incoming packet with local destination
ipt_netflow: new (2) 2:0 SRC=10.10.16.31:58196 DST=10.10.16.2:22
In both cases interface index pair is the same: "2:0"
Sorry for the typo in the initial comment - local ip is 10.10.16.2,
not 10.10.66.2
With 2.6.27.27 kernel everytihing is fine:
ipt_netflow: new (3) -1:2 SRC=10.10.16.2:22 DST=10.10.16.31:54733
So in index pair "-1:2"
"-1" stands for host itself
"2" = eth0
With kernel 2.6.29.1 and ipt_NETFLOW 1.6 it looks even more obscure:
ipt_netflow: new (1) -30160:0 SRC=10.10.16.2:0 DST=10.10.16.45:8
ipt_netflow: new (2) 27360:0 SRC=10.10.16.45:0 DST=10.10.16.2:0
Tried to add some rough debugging like this:
@@ -1202,6 +1215,12 @@
nf->s_mask = s_mask;
nf->d_mask = d_mask;
+ if(if_in)
+ printk(KERN_ERR "if_in->name: %s\n",if_in->name);
+ if(if_out)
+ printk(KERN_ERR "if_out->name: %s\n",if_out->name);
With 2.6.27.7 it prints:
if_in->name: eth0
..
if_in->name: eth0
while with 2.6.29.2 goes some crap is if if_in->name points
to some unitialized area:
if_out->name: @..ЮXTьыNETFLOW
Well, if nobody else never mentions such a problem
then there must be something wrong with my own
environment.
Do you recompiled module for new kernel? Do you loading correct compiled version of module?
Yes, just deleted module source tree,
unpacked source tarball again and rebuilt
as usual:
#ln -s /usr/src/local/iptables-1.4.4 /usr/src/iptables
#cd /usr/src/local
#tar xzf /usr/archive/src/ipt_netflow-1.6.tgz
#cd /usr/src/local/ipt_netflow-1.6
#./configure
#make all install
Maybe kernel source installation are messed? Your symptoms show that headers to what module compiled are incompatible with your run-time kernel. In normal circumstances this should never happen.
I remember that begins from 2.6.28 or 2.6.29 some changes was in definition of .target in ipt_target. From that moments function prototype begins to look like
unsigned int (*target)(struct sk_buff *skb,const struct xt_target_param * param);
so all info about interfaces moved to param
struct xt_target_param {
const struct net_device *in, *out;
unsigned int hooknum;
const struct xt_target *target;
const void *targinfo;
u_int8_t family;
};
so i think need to make some changes in source code of ipt_NETFLOW module.
I have try to compile it on 2.6.29 kernel. it gives me:
warning: initialization from incompatible pointer type
on next line in ipt_netflow_reg variable.
.target = netflow_target
so it looks like that`s why such garbage present in 'if_in' and 'if_out' (arguments), because it in real not send to function, it need to get this info from param variable.
Oh right, that is since 2.6.28. Thanks ebendyak!
Added change to cvs head, but not tested against real kernel. Would appreciate if somebody try it.
problem
need made changes, because of const struct net_device *in, *out; not if_in if_out
so made such
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
tuple.i_ifc = if_in? if_in->ifindex : -1;
#else
tuple.i_ifc = par->in? par->in->ifindex : -1;
#endif
and
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
nf->o_ifc = if_out? if_out->ifindex : -1;
#else
nf->o_ifc = par->out? par->out->ifindex : -1;
#endif
Corrected. Thanks again!