Skip to content

Commit b96af92

Browse files
ffmanceraummakynes
authored andcommitted
netfilter: nf_tables: implement Passive OS fingerprint module in nft_osf
Add basic module functions into nft_osf.[ch] in order to implement OSF module in nf_tables. Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent f932495 commit b96af92

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,13 @@ enum nft_flowtable_hook_attributes {
14631463
};
14641464
#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1)
14651465

1466+
enum nft_osf_attributes {
1467+
NFTA_OSF_UNSPEC,
1468+
NFTA_OSF_DREG,
1469+
__NFTA_OSF_MAX,
1470+
};
1471+
#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
1472+
14661473
/**
14671474
* enum nft_device_attributes - nf_tables device netlink attributes
14681475
*

net/netfilter/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,13 @@ config NFT_SOCKET
627627
This option allows matching for the presence or absence of a
628628
corresponding socket and its attributes.
629629

630+
config NFT_OSF
631+
tristate "Netfilter nf_tables passive OS fingerprint support"
632+
depends on NETFILTER_ADVANCED
633+
select NETFILTER_NETLINK_OSF
634+
help
635+
This option allows matching packets from an specific OS.
636+
630637
if NF_TABLES_NETDEV
631638

632639
config NF_DUP_NETDEV

net/netfilter/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ obj-$(CONFIG_NFT_FIB) += nft_fib.o
110110
obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o
111111
obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o
112112
obj-$(CONFIG_NFT_SOCKET) += nft_socket.o
113+
obj-$(CONFIG_NFT_OSF) += nft_osf.o
113114

114115
# nf_tables netdev
115116
obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o

net/netfilter/nft_osf.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#include <net/ip.h>
2+
#include <net/tcp.h>
3+
4+
#include <net/netfilter/nf_tables.h>
5+
#include <linux/netfilter/nf_osf.h>
6+
7+
#define OSF_GENRE_SIZE 32
8+
9+
struct nft_osf {
10+
enum nft_registers dreg:8;
11+
};
12+
13+
static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = {
14+
[NFTA_OSF_DREG] = { .type = NLA_U32 },
15+
};
16+
17+
static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
18+
const struct nft_pktinfo *pkt)
19+
{
20+
struct nft_osf *priv = nft_expr_priv(expr);
21+
u32 *dest = &regs->data[priv->dreg];
22+
struct sk_buff *skb = pkt->skb;
23+
const struct tcphdr *tcp;
24+
struct tcphdr _tcph;
25+
const char *os_name;
26+
27+
tcp = skb_header_pointer(skb, ip_hdrlen(skb),
28+
sizeof(struct tcphdr), &_tcph);
29+
if (!tcp) {
30+
regs->verdict.code = NFT_BREAK;
31+
return;
32+
}
33+
if (!tcp->syn) {
34+
regs->verdict.code = NFT_BREAK;
35+
return;
36+
}
37+
38+
os_name = nf_osf_find(skb, nf_osf_fingers);
39+
if (!os_name)
40+
strncpy((char *)dest, "unknown", IFNAMSIZ);
41+
else
42+
strncpy((char *)dest, os_name, IFNAMSIZ);
43+
}
44+
45+
static int nft_osf_init(const struct nft_ctx *ctx,
46+
const struct nft_expr *expr,
47+
const struct nlattr * const tb[])
48+
{
49+
struct nft_osf *priv = nft_expr_priv(expr);
50+
int err;
51+
52+
priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);
53+
err = nft_validate_register_store(ctx, priv->dreg, NULL,
54+
NFTA_DATA_VALUE, OSF_GENRE_SIZE);
55+
if (err < 0)
56+
return err;
57+
58+
return 0;
59+
}
60+
61+
static int nft_osf_dump(struct sk_buff *skb, const struct nft_expr *expr)
62+
{
63+
const struct nft_osf *priv = nft_expr_priv(expr);
64+
65+
if (nft_dump_register(skb, NFTA_OSF_DREG, priv->dreg))
66+
goto nla_put_failure;
67+
68+
return 0;
69+
70+
nla_put_failure:
71+
return -1;
72+
}
73+
74+
static struct nft_expr_type nft_osf_type;
75+
static const struct nft_expr_ops nft_osf_op = {
76+
.eval = nft_osf_eval,
77+
.size = NFT_EXPR_SIZE(sizeof(struct nft_osf)),
78+
.init = nft_osf_init,
79+
.dump = nft_osf_dump,
80+
.type = &nft_osf_type,
81+
};
82+
83+
static struct nft_expr_type nft_osf_type __read_mostly = {
84+
.ops = &nft_osf_op,
85+
.name = "osf",
86+
.owner = THIS_MODULE,
87+
.policy = nft_osf_policy,
88+
.maxattr = NFTA_OSF_MAX,
89+
};
90+
91+
static int __init nft_osf_module_init(void)
92+
{
93+
return nft_register_expr(&nft_osf_type);
94+
}
95+
96+
static void __exit nft_osf_module_exit(void)
97+
{
98+
return nft_unregister_expr(&nft_osf_type);
99+
}
100+
101+
module_init(nft_osf_module_init);
102+
module_exit(nft_osf_module_exit);
103+
104+
MODULE_LICENSE("GPL");
105+
MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
106+
MODULE_ALIAS_NFT_EXPR("osf");

0 commit comments

Comments
 (0)