Hi. Passive OS fingerprinting netfilter module allows to passively detect remote OS and perform various netfilter actions based on that knowledge. This module compares some data (WS, MSS, options and it's order, ttl, df and others) from packets with SYN bit set with dynamically loaded OS fingerprints. Fingerprint matching rules can be downloaded from OpenBSD source tree and loaded via netlink connector into the kernel via special util found in archive. It will also listen for events about matching packets. Archive also contains library file (also attached), which was shipped with iptables extensions some time ago (at least when ipt_osf existed in patch-o-matic). This release implements suggestions found during the code review like codying style, structure split and tighter packing, bool and %pi4 usage and similar changes. Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os Example usage: # modrpobe xt_osf # ./ucon_osf -f ./pf.os ^C Daemon will listen for incoming match events -d switch removes fingerprints # iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 0 --ttl 2 --connector You will find something like this in the syslog: ipt_osf: Windows [2000:SP3:Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139 Please consider for inclusion. Thank you. Passive OS fingerprint homepage (archives, examples): http://www.ioremap.net/projects/osf Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> diff --git a/include/linux/connector.h b/include/linux/connector.h index 34f2789..da6595e 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -39,6 +39,8 @@ #define CN_IDX_V86D 0x4 #define CN_VAL_V86D_UVESAFB 0x1 #define CN_IDX_BB 0x5 /* BlackBoard, from the TSP GPL sampling framework */ +#define CN_IDX_OSF 0x6 /* Passive OS fingerprint iptables module */ +#define CN_VAL_OSF 0x0 #define CN_NETLINK_USERS 6 diff --git a/include/linux/netfilter/xt_osf.h ...
Not the latest version, it misses the following fix from the parallel
tree.
Fixed TCP header copy to the userspace when given option is enabled.
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 3114bbd..e619f09 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -83,7 +83,7 @@ static void ipt_osf_send_connector(struct ipt_osf_user_finger *f,
struct ipt_osf_message *msg = &per_cpu(ipt_osf_mbuf, smp_processor_id());
struct ipt_osf_nlmsg *data = &msg->nlmsg;
struct iphdr *iph = ip_hdr(skb);
- struct tcphdr *tcph = tcp_hdr(skb);
+ struct tcphdr *tcp;
memcpy(&msg->cmsg.id, &cn_osf_id, sizeof(struct cn_msg));
msg->cmsg.seq = osf_seq++;
@@ -92,7 +92,9 @@ static void ipt_osf_send_connector(struct ipt_osf_user_finger *f,
memcpy(&data->f, f, sizeof(struct ipt_osf_user_finger));
memcpy(&data->ip, iph, sizeof(struct iphdr));
- memcpy(&data->tcp, tcph, sizeof(struct tcphdr));
+ tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &data->tcp);
+ if (tcp)
+ memcpy(&data->tcp, tcp, sizeof(struct tcphdr));
cn_netlink_send(&msg->cmsg, CN_IDX_OSF, GFP_ATOMIC);
}
--
Evgeniy Polyakov
--
Since the module's name is xt_osf now, it would make sense to follow Just a minor thing, could you add "osf" somewhere in the short-text so that people instantly know the name of the module (without having to consult the help text), like the other entries. For example A bit of rewording I suggest. This option selects the Passive OS Fingerprinting match module that allows to passively match the should -> can Rules and loading software can be downloaded from Please have the list sorted alphabetically. (This keeps merge conflicts iph and tcph are only used in memcpy and could be directly substituted: memcpy(&data->ip, ip_hdr(skb), ...) xt_osf does not look at TCP options, is not it? Note that you cannot directly use tcp_hdr(skb) as the skb->transport_header has not yet been initialized (it still points at skb->network_header) because the packet has not yet been seen by the next handler. This affects PREROUTING, and INPUT chains (and BROUTING, for ebtables people, but irrelevant here). The packet may also be fragmented or non-linear. -Jan --
Hi Jan. Thanks for the review, I will incorporate the changes and respin it soon. -- Evgeniy Polyakov --
You can remove this function, as it does no initialization. This would allow specifying --ttl 12345. Use of xtables_strtoui (v1.4.3-rc1+git) for bounds checking, and use of optarg seem beneficial: unsigned int num; if (!xtables_strtoui(optarg, NULL, &num, 0, UINT8_MAX)) exit_error(PARAMETER_PROBLEM, "*shrug*"); Needs .family = NFPROTO_IPV4. --
In some of my code I call synchronize_net(), is it enough to call rcu_barrier()? What is the difference between: synchronize_rcu() synchronize_net() rcu_barrier() Hilsen Jesper Brouer -- ------------------------------------------------------------------- MSc. Master of Computer Science Dept. of Computer Science, University of Copenhagen Author of http://www.adsl-optimizer.dk ------------------------------------------------------------------- --
Hi. Not required at this place - all users are already unregistered and It is enough here, rcu_barrier() will wait until all scheduled call_rcu() are completed, that's what we need. But in some cases we should only wait for the whole grace period to elapse, then one has to use synchronize_rcu() and friends. rcu_barrier() will wait for the callbacks to be executed, while they are executed after grace period has elapsed, so it implicitly includes synchronize_rcu(), but effectively they are the same: both functions register rcu callback and wait for the completion, rcu_barrier() is a bit more enhanced, since it has several Those are essentially the same - synchronize_net() has additional might_sleep() call. Both will wait until grace period elapced - i.e. It will wait until all scheduled rcu callbacks are executed. So from the description they look different, but implementation suggestes that effectively they are the same, except that there are a bit different invocation types for the barrier. -- Evgeniy Polyakov --
synchronize_net() is just a call to synchronize_rcu(), so their functionality is equivalent. synchronize_net() is however only supposed to synchronize with RX packet processing, which is usually not enough for netfilter. So I prefer synchronize_rcu() for clarity. --
I like this feature. We have nfnetlink so I don't see why we should use the netlink connector instead. BTW, is there any difference with regards to userspace p0f apart from having this integrated into iptables? -- "Los honestos son inadaptados sociales" -- Les Luthiers --
Hi Pablo. OSF exists about 6 years already, netlink configuration was added in 2005, I do not remember if nfnetlink existed those days (IIRC it did not, since I reused ULOG netlink first), right now I just cleanup There should be no major differences, there are some tweaks for the MTU comparison, maybe something else. -- Evgeniy Polyakov --
We do have nfnetlink today however, so this argument does no longer apply. I don't mind the order in which things are fixed up of course, but before merging, it needs to be converted to nfnetlink. --
