From: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
To: Harald Welte <laforge@netfilter.org>
Cc: netfilter-devel@lists.netfilter.org
Subject: OSF update: netlink logging
Date: 16 Jan 2004 18:39:59 +0300 [thread overview]
Message-ID: <1074267599.7519.49.camel@uganda> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 981 bytes --]
Hello, Harald.
Hello, all.
This patches add possibility to log OSF events through netlink.
I've stolen NETLINK_NFLOG and mcast group 1 in OSF module from ipt_ULOG,
so you can't use ipt_ULOG and ipt_osf at the same time(or you will catch
some unusal events in ulogd/osfd).
Patchset also adds missing diffs for
Some "smart" hardware/software changes MSS while doing NAT/DSL, so
make additional compare with "good" MSS value(predefined 1460).
Kudos to Michal Zalewski and Mike Frantzen.
Whitespace cleanup.
Packets from outside(loopback is outside too) may have equal to
fingerprint ttl, not necessarily lesser.
If we have timestamp option, do not compare it with one from
fingerprint.
(For now it is always 0).
ip->ttl must be less than finger's ttl if fingerprint is valid.
and probably others.
Patchset is against latest pom-ng/userspace.
Please test and apply.
For testing i also attach trivial osfd.c.
--
Evgeniy Polaykov ( s0mbre )
[-- Attachment #1.2: ipt_osf.h.diff --]
[-- Type: text/plain, Size: 1152 bytes --]
--- cvs_ext/netfilter/patch-o-matic-ng/osf/linux/include/linux/netfilter_ipv4/ipt_osf.h Thu Dec 18 21:28:43 2003
+++ cvs_ext/netfilter/patch-o-matic-ng/osf/linux/include/linux/netfilter_ipv4/ipt_osf.h Fri Jan 16 17:56:43 2004
@@ -26,14 +26,25 @@
#define MAXDETLEN 64
#define IPT_OSF_GENRE 1
-#define IPT_OSF_SMART 2
+#define IPT_OSF_SMART 2
#define IPT_OSF_LOG 4
+#define IPT_OSF_NETLINK 8
-#define IPT_OSF_LOGLEVEL_ALL 0
+#define IPT_OSF_LOGLEVEL_ALL 0
#define IPT_OSF_LOGLEVEL_FIRST 1
#include <linux/list.h>
+#ifndef __KERNEL__
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+struct list_head
+{
+ struct list_head *prev, *next;
+};
+#endif
+
struct ipt_osf_info
{
char genre[MAXGENRELEN];
@@ -59,8 +70,6 @@
struct osf_wc wc;
};
-#ifdef __KERNEL__
-
struct osf_finger
{
struct list_head flist;
@@ -78,6 +87,15 @@
struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
};
+
+struct ipt_osf_nlmsg
+{
+ struct osf_finger f;
+ struct iphdr ip;
+ struct tcphdr tcp;
+};
+
+#ifdef __KERNEL__
/* Defines for IANA option kinds */
[-- Attachment #1.3: libipt_osf.c.diff --]
[-- Type: text/plain, Size: 1557 bytes --]
--- cvs_ext/netfilter/userspace/extensions/libipt_osf.c Sun Jan 4 02:42:10 2004
+++ cvs_ext/netfilter/userspace/extensions/libipt_osf.c Fri Jan 16 17:56:43 2004
@@ -31,9 +31,9 @@
#include <ctype.h>
#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_osf.h>
+#include <linux/netfilter_ipv4/ipt_osf.h>
-#define IPTABLES_VERSION "1.2.6a" /* It looks like FIXME */
+#define IPTABLES_VERSION "1.2.7a" /* Permanent FIXME */
static void help(void)
{
@@ -42,7 +42,8 @@
"--smart Use some smart extensions to determine OS (do not use TTL).\n"
"--log level Log all(or only first) determined genres even if "
"they do not match desired one. "
- "Level may be 0(all) or 1(only first entry).\n",
+ "Level may be 0(all) or 1(only first entry).\n"
+ "--netlink Log through netlink(NETLINK_NFLOG).\n",
IPTABLES_VERSION);
}
@@ -51,6 +52,7 @@
{ .name = "genre", .has_arg = 1, .flag = 0, .val = '1' },
{ .name = "smart", .has_arg = 0, .flag = 0, .val = '2' },
{ .name = "log", .has_arg = 1, .flag = 0, .val = '3' },
+ { .name = "netlink", .has_arg = 0, .flag = 0, .val = '4' },
{ .name = 0 }
};
@@ -101,6 +103,12 @@
*flags |= IPT_OSF_LOG;
info->loglevel = atoi(argv[optind-1]);
info->flags |= IPT_OSF_LOG;
+ break;
+ case '4': /* --netlink */
+ if (*flags & IPT_OSF_NETLINK)
+ exit_error(PARAMETER_PROBLEM, "Can't specify multiple smart parameter");
+ *flags |= IPT_OSF_NETLINK;
+ info->flags |= IPT_OSF_NETLINK;
break;
default:
return 0;
[-- Attachment #1.4: Type: text/x-c, Size: 1944 bytes --]
#include <asm/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "osf/ipt_osf.h"
#ifndef NIPQUAD
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#endif
int main()
{
int s;
char buf[1024];
int len;
struct nlmsghdr *reply;
struct sockaddr_nl l_local;
struct ipt_osf_nlmsg *data;
memset(buf, 0, sizeof(buf));
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_NFLOG);
if (s == -1)
{
perror("socket");
return -1;
}
l_local.nl_family = AF_NETLINK;
l_local.nl_groups = 1;
l_local.nl_pid = getpid();
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1)
{
perror("bind");
close(s);
return -1;
}
while (1)
{
len = recv(s, buf, sizeof(buf), 0);
if (len == -1)
{
perror("recv buf");
close(s);
return -1;
}
reply = (struct nlmsghdr *)buf;
printf("first nlmsghdr received: len=%d\n", len);
printf("nlsmsghdr: len=%d, type=%d, flags=%d, seq=%d, pid=%d, sender_pid=%d\n",
reply->nlmsg_len, reply->nlmsg_type,
reply->nlmsg_flags, reply->nlmsg_seq, reply->nlmsg_pid,
getpid());
switch (reply->nlmsg_type)
{
case NLMSG_ERROR:
printf("Error message received.\n");
break;
case NLMSG_DONE:
data = (struct ipt_osf_nlmsg *)NLMSG_DATA(reply);
printf("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
data->f.genre, data->f.version,
data->f.subtype, data->f.details,
NIPQUAD(data->ip.saddr), ntohs(data->tcp.source),
NIPQUAD(data->ip.daddr), ntohs(data->tcp.dest),
data->f.ttl - data->ip.ttl);
break;
}
}
close(s);
return 0;
}
[-- Attachment #1.5: ipt_osf.c.diff --]
[-- Type: text/plain, Size: 8145 bytes --]
--- cvs_ext/netfilter/patch-o-matic-ng/osf/linux/net/ipv4/netfilter/ipt_osf.c Thu Dec 18 21:56:03 2003
+++ cvs_ext/netfilter/patch-o-matic-ng/osf/linux/net/ipv4/netfilter/ipt_osf.c Fri Jan 16 18:21:40 2004
@@ -30,6 +30,8 @@
#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
#include <linux/smp.h>
#include <linux/module.h>
#include <linux/skbuff.h>
@@ -41,13 +43,14 @@
#include <linux/spinlock.h>
#include <linux/ctype.h>
#include <linux/list.h>
+#include <linux/if.h>
#include <net/sock.h>
#include <net/ip.h>
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_osf.h>
+#include <linux/netfilter_ipv4/ipt_osf.h>
#define OSF_DEBUG
@@ -70,12 +73,16 @@
static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
static struct list_head finger_list;
-
static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
- const void *, int, const void *, u_int16_t, int *);
+ const void *, int,
+ const void *, u_int16_t,
+ int *);
static int checkentry(const char *, const struct ipt_ip *, void *,
unsigned int, unsigned int);
+static unsigned long seq, ipt_osf_groups = 1;
+static struct sock *nts;
+
static struct ipt_match osf_match =
{
{ NULL, NULL },
@@ -86,12 +93,60 @@
THIS_MODULE
};
-static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
+static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
{
+ unsigned int size;
+ struct sk_buff *skb;
+ struct ipt_osf_nlmsg *data;
+ struct nlmsghdr *nlh;
+
+ size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
+
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ {
+ log("skb_alloc() failed.\n");
+ return;
+ }
+
+ nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
+
+ data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
+
+ memcpy(&data->f, f, sizeof(struct osf_finger));
+ memcpy(&data->ip, skb->nh.iph, sizeof(struct iphdr));
+ memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)skb->nh.iph + skb->nh.iph->ihl), sizeof(struct tcphdr));
+
+ NETLINK_CB(skb).dst_groups = ipt_osf_groups;
+ netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
+
+nlmsg_failure:
+ return;
+}
+
+static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
+{
+ struct iphdr *ip = skb->nh.iph;
+
if (flags & IPT_OSF_SMART)
- return 1;
+ {
+ struct in_device *in_dev = in_dev_get(skb->dev);
+
+ for_ifa(in_dev)
+ {
+ if (inet_ifa_match(ip->saddr, ifa))
+ {
+ in_dev_put(in_dev);
+ return (ip->ttl == f_ttl);
+ }
+ }
+ endfor_ifa(in_dev);
+
+ in_dev_put(in_dev);
+ return (ip->ttl <= f_ttl);
+ }
else
- return (ip_ttl == f_ttl);
+ return (ip->ttl == f_ttl);
}
static int
@@ -151,7 +206,7 @@
fmatch = FMATCH_WRONG;
if (totlen == f->ss && df == f->df &&
- smart_dec(info->flags, ip->ttl, f->ttl))
+ smart_dec(skb, info->flags, f->ttl))
{
unsigned long foptsize;
int optnum;
@@ -197,32 +252,57 @@
for (optnum=0; optnum<f->opt_num; ++optnum)
{
- if (f->opt[optnum].kind == (*optp))
+ if (f->opt[optnum].kind == (*optp))
{
unsigned char len = f->opt[optnum].length;
unsigned char *optend = optp + len;
+ int loop_cont = 0;
fmatch = FMATCH_OK;
- if (*optp == OSFOPT_MSS) /* MSS */
- mss = ntohs(*(unsigned short *)(optp+2));
+
+ switch (*optp)
+ {
+ case OSFOPT_MSS:
+ mss = ntohs(*(unsigned short *)(optp+2));
+ break;
+ case OSFOPT_TS:
+ loop_cont = 1;
+ break;
+ }
+
+ if (loop_cont)
+ {
+ optp = optend;
+ continue;
+ }
if (len != 1)
{
/* Skip kind and length fields*/
optp += 2;
- if (f->opt[optnum].wc.wc != 0)
+ if (f->opt[optnum].wc.val != 0)
{
unsigned long tmp = 0;
/* Hmmm... It looks a bit ugly. :) */
- memcpy(&tmp, &f->opt[optnum].wc.val,
+ memcpy(&tmp, optp,
(len > sizeof(unsigned long)?
sizeof(unsigned long):len));
-
- tmp = ntohl(tmp);
- if (tmp != f->opt[optnum].wc.val)
+ /* 2 + 2: optlen(2 bytes) +
+ * kind(1 byte) + length(1 byte) */
+ if (len == 4)
+ tmp = ntohs(tmp);
+ else
+ tmp = ntohl(tmp);
+
+ if (f->opt[optnum].wc.wc == '%')
+ {
+ if ((tmp % f->opt[optnum].wc.val) != 0)
+ fmatch = FMATCH_OPT_WRONG;
+ }
+ else if (tmp != f->opt[optnum].wc.val)
fmatch = FMATCH_OPT_WRONG;
}
}
@@ -243,19 +323,23 @@
switch (check_WSS)
{
case 0:
- if (window == f->wss.val)
+ if (f->wss.val == 0 || window == f->wss.val)
fmatch = FMATCH_OK;
break;
case 1: /* MSS */
- if (window == f->wss.val*mss)
+/* Lurked in OpenBSD */
+#define SMART_MSS 1460
+ if (window == f->wss.val*mss ||
+ window == f->wss.val*SMART_MSS)
fmatch = FMATCH_OK;
break;
case 2: /* MTU */
- if (window == f->wss.val*(mss+40))
+ if (window == f->wss.val*(mss+40) ||
+ window == f->wss.val*(SMART_MSS+40))
fmatch = FMATCH_OK;
break;
case 3: /* MOD */
- if (window % f->wss.val == 0)
+ if ((window % f->wss.val) == 0)
fmatch = FMATCH_OK;
break;
}
@@ -265,18 +349,45 @@
if (fmatch == FMATCH_OK)
{
fcount++;
- log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
- f->genre, f->details,
+ log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
+ f->genre, f->version,
+ f->subtype, f->details,
NIPQUAD(ip->saddr), ntohs(tcp->source),
- NIPQUAD(ip->daddr), ntohs(tcp->dest));
+ NIPQUAD(ip->daddr), ntohs(tcp->dest),
+ f->ttl - ip->ttl);
+ if (info->flags & IPT_OSF_NETLINK)
+ ipt_osf_nlsend(f, skb);
if ((info->flags & IPT_OSF_LOG) &&
info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
break;
}
}
}
+ if (!fcount && (info->flags & IPT_OSF_NETLINK))
+ {
+ struct osf_finger u;
+
+ memset(&u, 0, sizeof(u));
+ snprintf(u.genre, MAXGENRELEN, "Unknown");
+ snprintf(u.version, MAXGENRELEN, "Unknown");
+ snprintf(u.subtype, MAXGENRELEN, "Unknown");
+ u.wss.val = window;
+ u.ttl = ip->ttl;
+ u.df = df;
+ u.ss = totlen;
+ if (optp)
+ {
+ unsigned int optsize;
+
+ optsize = tcp->doff * 4 - sizeof(struct tcphdr);
+ /* optsize <= 40. So it always less than MAXDETLEN (64) */
+ skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr), u.details, optsize);
+ }
+ ipt_osf_nlsend(&u, skb);
+ }
if (!fcount && (info->flags & IPT_OSF_LOG))
{
+
log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
if (optp)
{
@@ -594,7 +705,12 @@
else
finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
}
- if (isdigit(pbeg[0]))
+ else if (pbeg[0] == '%')
+ {
+ finger->wss.wc = '%';
+ finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
+ }
+ else if (isdigit(pbeg[0]))
{
finger->wss.wc = 0;
finger->wss.val = simple_strtoul(pbeg, NULL, 10);
@@ -702,6 +818,15 @@
p->write_proc = osf_proc_write;
p->read_proc = osf_proc_read;
+
+ nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
+ if (!nts)
+ {
+ log("netlink_kernel_create() failed\n");
+ remove_proc_entry("sys/net/ipv4/osf", NULL);
+ ipt_unregister_match(&osf_match);
+ return -ENOMEM;
+ }
return 0;
}
@@ -713,6 +838,8 @@
remove_proc_entry("sys/net/ipv4/osf", NULL);
ipt_unregister_match(&osf_match);
+ if (nts && nts->socket)
+ sock_release(nts->socket);
list_for_each_safe(ent, n, &finger_list)
{
@@ -730,4 +857,3 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Passive OS fingerprint matching.");
-
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
reply other threads:[~2004-01-16 15:39 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1074267599.7519.49.camel@uganda \
--to=johnpol@2ka.mipt.ru \
--cc=laforge@netfilter.org \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.