[linux-l] iptables Problem: Einfuegen nicht moeglich wenn Referenz > 0
Benjamin Schieder
blindcoder at scavenger.homeip.net
Fr Sep 1 16:12:38 CEST 2006
Hi Liste.
Ich habe gerade ein seeehr merkwuerdiges Problem mit iptables.
Folgende Situation:
Ich moechte mein Traffic Accounting Tool (UTA Dragon) mit aktuellem Kernel
2.6.17.7 zum Laufen bringen. Dazu ist ein Kernel Patch vonnoeten, damit
ich Traffic einem User zuordnen kann. Dies ist eine neue Version des
ipt_ownersocketlookup.patch aus iptables patch-o-matic:
---
diff -pruN linux-2.6.17.7-rock/net/ipv4/netfilter/ipt_owner.c linux-2.6.17.7-rock-dragon/net/ipv4/netfilter/ipt_owner.c
--- linux-2.6.17.7-rock/net/ipv4/netfilter/ipt_owner.c 2006-09-01 15:48:39.000000000 +0200
+++ linux-2.6.17.7-rock-dragon/net/ipv4/netfilter/ipt_owner.c 2006-08-30 09:58:15.000000000 +0200
@@ -12,7 +12,13 @@
#include <linux/skbuff.h>
#include <linux/file.h>
#include <linux/rcupdate.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
#include <net/sock.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/inet_hashtables.h>
#include <linux/netfilter_ipv4/ipt_owner.h>
#include <linux/netfilter_ipv4/ip_tables.h>
@@ -32,23 +38,48 @@ match(const struct sk_buff *skb,
int *hotdrop)
{
const struct ipt_owner_info *info = matchinfo;
+ struct iphdr *iph = skb->nh.iph;
+ struct sock *sk = NULL;
+ int ret = 0;
+
+ if (out) {
+ sk = skb->sk;
+ } else {
+ if (iph->protocol == IPPROTO_TCP) {
+ struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
+ sk = inet_lookup(&tcp_hashinfo, iph->saddr, tcph->source, iph->daddr, tcph->dest, skb->dev->ifindex);
+
+ if (sk && sk->sk_state == TCP_TIME_WAIT) {
+ inet_twsk_put((struct inet_timewait_sock *)sk);
+ return ret;
+ }
+ } else if (iph->protocol == IPPROTO_UDP) {
+ struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+ sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr, udph->dest, skb->dev->ifindex);
+ }
+ }
- if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
- return 0;
+ if (!sk || !sk->sk_socket || !sk->sk_socket->file)
+ goto out;
if(info->match & IPT_OWNER_UID) {
- if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
+ if ((sk->sk_socket->file->f_uid != info->uid) ^
!!(info->invert & IPT_OWNER_UID))
- return 0;
+ goto out;
}
if(info->match & IPT_OWNER_GID) {
- if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
+ if ((sk->sk_socket->file->f_gid != info->gid) ^
!!(info->invert & IPT_OWNER_GID))
- return 0;
+ goto out;
}
- return 1;
+ ret = 1;
+
+out:
+ if (in && sk)
+ sock_put(sk);
+ return ret;
}
static int
diff -pruN linux-2.6.17.7-rock/net/ipv4/udp.c linux-2.6.17.7-rock-dragon/net/ipv4/udp.c
--- linux-2.6.17.7-rock/net/ipv4/udp.c 2006-08-30 08:44:09.000000000 +0200
+++ linux-2.6.17.7-rock-dragon/net/ipv4/udp.c 2006-08-30 15:23:36.000000000 +0200
@@ -1587,6 +1587,7 @@ EXPORT_SYMBOL(udp_port_rover);
EXPORT_SYMBOL(udp_prot);
EXPORT_SYMBOL(udp_sendmsg);
EXPORT_SYMBOL(udp_poll);
+EXPORT_SYMBOL(udp_v4_lookup);
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(udp_proc_register);
diff -pruN linux-2.6.17.7-rock/include/net/udp.h linux-2.6.17.7-rock-dragon/include/net/udp.h
--- linux-2.6.17.7-rock/include/net/udp.h 2006-08-30 08:46:19.000000000 +0200
+++ linux-2.6.17.7-rock-dragon/include/net/udp.h 2006-08-30 17:17:26.000000000 +0200
@@ -74,6 +74,8 @@ extern int udp_disconnect(struct sock *s
extern unsigned int udp_poll(struct file *file, struct socket *sock,
poll_table *wait);
+static struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
+
DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
#define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
---
Wenn ich jetzt das Programm starte und es seine Initialisierung durchfuehrt,
bricht es beim einfuegen der User ab:
iptables -A DRAGONUSER_INPUT -p tcp -d 192.168.1.6 -m owner --uid-owner 0 -j RETURN
iptables: Unknown error 4294967295
dmesg:
ip_tables: owner match: bad hook_mask 2
iptables -L sieht jetzt so aus:
root at ceres:/usr/src/dragon_0.3# iptables -vnxL
root at ceres:/usr/src/dragon_0.3# iptables -vnxL
Chain INPUT (policy ACCEPT 26730 packets, 7854290 bytes)
pkts bytes target prot opt in out source destination
# 95 46248 DRAGON_INPUT all -- * * 0.0.0.0/0 192.168.1.6
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 26123 packets, 9843675 bytes)
pkts bytes target prot opt in out source destination
90 33282 DRAGON_OUTPUT all -- * * 192.168.1.6 0.0.0.0/0
Chain DRAGONPROGRAM_INPUT (1 references)
pkts bytes target prot opt in out source destination
Chain DRAGONPROGRAM_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
#Chain DRAGONUSER_INPUT (1 references)
# pkts bytes target prot opt in out source destination
Chain DRAGONUSER_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
Chain DRAGON_INPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 127.0.0.0/8 0.0.0.0/0
35 2540 RETURN all -- * * 192.168.1.0/24 0.0.0.0/0
# 60 43708 DRAGONUSER_INPUT all -- * * 0.0.0.0/0 0.0.0.0/0
60 43708 DRAGONPROGRAM_INPUT all -- * * 0.0.0.0/0 0.0.0.0/0
50 42425 RETURN tcp -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
10 1283 RETURN udp -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
0 0 RETURN all -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
Chain DRAGON_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 0.0.0.0/0 127.0.0.0/8
24 2928 RETURN all -- * * 0.0.0.0/0 192.168.1.0/24
66 30354 DRAGONUSER_OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0
66 30354 DRAGONPROGRAM_OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0
56 28791 RETURN tcp -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
0 0 RETURN udp -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
10 1563 RETURN all -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
Die Zeilen mit # am Anfang hab ich markiert, die sind hier wichtig. Traffic
wird von INPUT nach DRAGON_INPUT geschickt, dort wird er gezaehlt. DRAGON_INPUT
schickt ihn nach DRAGONUSER_INPUT, wo er auf die User accounted werden soll.
Wenn ich aus DRAGON_INPUT die entsprechende Zeile loesche, funktioniert
komischerweise das Einfuegen in DRAGONUSER_INPUT:
root at ceres:/usr/src# iptables -D DRAGON_INPUT -j DRAGONUSER_INPUT
root at ceres:/usr/src# iptables -A DRAGONUSER_INPUT -p tcp -d 192.168.1.6 -m owner --uid-owner 0 -j RETURN
root at ceres:/usr/src# iptables -vnxL
Chain INPUT (policy ACCEPT 39814 packets, 13602839 bytes)
pkts bytes target prot opt in out source destination
12948 5775994 DRAGON_INPUT all -- * * 0.0.0.0/0 192.168.1.6
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 37753 packets, 13783989 bytes)
pkts bytes target prot opt in out source destination
11489 3954793 DRAGON_OUTPUT all -- * * 192.168.1.6 0.0.0.0/0
Chain DRAGONPROGRAM_INPUT (1 references)
pkts bytes target prot opt in out source destination
Chain DRAGONPROGRAM_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
Chain DRAGONUSER_INPUT (0 references)
pkts bytes target prot opt in out source destination
# 0 0 RETURN tcp -- * * 0.0.0.0/0 192.168.1.6 OWNER UID match 0
Chain DRAGONUSER_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
Chain DRAGON_INPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 127.0.0.0/8 0.0.0.0/0
3840 301809 RETURN all -- * * 192.168.1.0/24 0.0.0.0/0
9108 5474185 DRAGONPROGRAM_INPUT all -- * * 0.0.0.0/0 0.0.0.0/0
8429 5387893 RETURN tcp -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
679 86292 RETURN udp -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
0 0 RETURN all -- * * 0.0.0.0/0 192.168.1.6 /* total_in */
Chain DRAGON_OUTPUT (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 0.0.0.0/0 127.0.0.0/8
2520 485625 RETURN all -- * * 0.0.0.0/0 192.168.1.0/24
8969 3469168 DRAGONUSER_OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0
8969 3469168 DRAGONPROGRAM_OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0
8290 3363864 RETURN tcp -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
0 0 RETURN udp -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
679 105304 RETURN all -- * * 192.168.1.6 0.0.0.0/0 /* total_out */
In DRAGONUSER_OUTPUT kann ich problemlos einfuegen.
Hat jemand von euch eine Idee?
Gruesse,
Benjamin
--
Benjamin 'blindCoder' Schieder
Registered Linux User #289529: http://counter.li.org
finger blindcoder at scavenger.homeip.net | gpg --import
--
http://www.rocklinux.org/ The Distribution Build Kit
-------------- nächster Teil --------------
Ein Dateianhang mit Binärdaten wurde abgetrennt...
Dateiname : nicht verfügbar
Dateityp : application/pgp-signature
Dateigröße : 189 bytes
Beschreibung: nicht verfügbar
URL : <https://mlists.in-berlin.de/pipermail/linux-l-mlists.in-berlin.de/attachments/20060901/b72fae9b/attachment.sig>
Mehr Informationen über die Mailingliste linux-l