mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-05 12:16:38 +02:00
Initial commit.
Populate the iptables-addons repository with two modules, xt_TARPIT and xt_TEE, as a starting point. Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
This commit is contained in:
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
.*.cmd
|
||||
*.ko
|
||||
*.la
|
||||
*.lo
|
||||
*.loT
|
||||
*.mod.c
|
||||
*.o
|
||||
.deps
|
||||
.libs
|
||||
.tmp_versions
|
||||
Makefile
|
||||
Makefile.in
|
||||
Module.symvers
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te*.cache
|
||||
/compile
|
||||
/config.*
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/missing
|
||||
/stamp-h1
|
58
INSTALL
Normal file
58
INSTALL
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
Prerequirements
|
||||
===============
|
||||
|
||||
* iptables-devel 1.4.1
|
||||
|
||||
* kernel-source
|
||||
|
||||
|
||||
Compiling
|
||||
=========
|
||||
|
||||
./configure [options]
|
||||
|
||||
--with-kbuild=
|
||||
|
||||
Specifies the path to the kernel build output directory. We
|
||||
need it for building the kernel extensions. For example, on
|
||||
openSUSE:
|
||||
|
||||
--with-kbuild=/usr/src/linux-obj/x86_64/default
|
||||
|
||||
--with-ksource=
|
||||
|
||||
Specifies the path to the kernel source directory. This is
|
||||
currently needed for building the userspace extensions because
|
||||
we use unsanitized kernel headers, but the option MAY
|
||||
DISAPPEAR IN FUTURE.
|
||||
|
||||
--with-ksource=/usr/src/linux
|
||||
|
||||
--with-iptables=
|
||||
|
||||
Specifies the path to the directory where we may find
|
||||
xtables.h, should it not be within the standard C compiler
|
||||
include path, or if you want to override it. The directory
|
||||
will be checked for xtables.h and include/xtables.h. (This is
|
||||
to support the following specs:)
|
||||
|
||||
--with-iptables=/usr/src/iptables
|
||||
--with-iptables=/usr/src/iptables/include
|
||||
--with-iptables=/opt/iptables/include
|
||||
|
||||
--with-iptdir=
|
||||
|
||||
Specifies the path to where the newly built extensions should
|
||||
be installed when `make install` is run. It uses the same
|
||||
default as the iptables package, ${libexecdir}/iptables.
|
||||
|
||||
|
||||
Note to distribution packagers
|
||||
==============================
|
||||
|
||||
Except for --with-kbuild, distributions should not have a need to
|
||||
supply any other flags (besides --prefix=/usr and perhaps
|
||||
--libdir=/usr/lib64, etc.) to configure when all prerequired packages
|
||||
are installed. If iptables-devel is installed, necessary headers
|
||||
should be in /usr/include, so --with-iptables is not needed.
|
4
Makefile.am
Normal file
4
Makefile.am
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
SUBDIRS = extensions
|
7
README
Normal file
7
README
Normal file
@@ -0,0 +1,7 @@
|
||||
iptables-addons
|
||||
===============
|
||||
|
||||
iptables-addons is what previously has been patch-o-matic and
|
||||
patch-o-matic-ng. Extensions that do not need immediate kernel
|
||||
patching are collected here in this repository and can immediately be
|
||||
built against a kernel and iptables.
|
4
autogen.sh
Executable file
4
autogen.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
autoreconf -fi;
|
||||
rm -Rf autom4te*.cache;
|
62
configure.ac
Normal file
62
configure.ac
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
AC_INIT([iptables-addons], [1.4.1])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_DISABLE_STATIC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
kbuilddir="/lib/modules/$(uname -r)/build";
|
||||
ksourcedir="/lib/modules/$(uname -r)/source";
|
||||
AC_ARG_WITH([kbuild],
|
||||
AS_HELP_STRING([--with-kbuild=PATH],
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]]),
|
||||
[kbuilddir="$withval"])
|
||||
AC_ARG_WITH([ksource],
|
||||
AS_HELP_STRING([--with-ksource=PATH],
|
||||
[Path to kernel source directory [[/lib/modules/CURRENT/source]]]),
|
||||
[ksourcedir="$withval"])
|
||||
AC_ARG_WITH([iptables],
|
||||
AS_HELP_STRING([--with-iptables=PATH],
|
||||
[Path to the iptables includes [[PREFIX/include]]]),
|
||||
[iptables_location="$withval"])
|
||||
AC_ARG_WITH([iptdir],
|
||||
AS_HELP_STRING([--with-iptdir=PATH],
|
||||
[Path to iptables modules [[LIBEXECDIR/iptables]]]),
|
||||
[iptdir="$withval"],
|
||||
[iptdir='${libexecdir}/iptables'])
|
||||
|
||||
AC_CHECK_HEADER([netinet/ip6.h], [], [AC_MSG_ERROR(but we need that for IPv6)])
|
||||
|
||||
AC_MSG_CHECKING([xtables.h presence])
|
||||
if [[ -n "$iptables_location" ]]; then
|
||||
if [[ -f "$iptables_location/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$iptables_location/xtables.h])
|
||||
iptables_CFLAGS="-I$iptables_location";
|
||||
elif [[ -f "$iptables_location/include/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$iptables_location/include/xtables.h])
|
||||
iptables_CFLAGS="-I$iptables_location/include";
|
||||
fi;
|
||||
fi;
|
||||
if [[ -z "$iptables_CFLAGS" ]]; then
|
||||
if [[ -f "$includedir/xtables.h" ]]; then
|
||||
AC_MSG_RESULT([$includedir/xtables.h])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi;
|
||||
fi;
|
||||
|
||||
regular_CFLAGS="-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 \
|
||||
-D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Winline -pipe -DIPTABLES_VERSION=\\\"$PACKAGE_VERSION\\\" \
|
||||
-DIPT_LIB_DIR=\\\"\${iptdir}\\\" -DIP6T_LIB_DIR=\\\"\${iptdir}\\\"";
|
||||
kinclude_CFLAGS="-I\"$kbuilddir/include\" -I\"$ksourcedir/include\"";
|
||||
|
||||
AC_SUBST([regular_CFLAGS iptables_CFLAGS kinclude_CFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([iptdir])
|
||||
AC_OUTPUT([Makefile extensions/Makefile])
|
4
extensions/Kbuild
Normal file
4
extensions/Kbuild
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += xt_TARPIT.o
|
||||
obj-m += xt_TEE.o
|
34
extensions/Makefile.am
Normal file
34
extensions/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
abssrcdir = $(shell readlink -f ${srcdir})
|
||||
|
||||
regular_CFLAGS := @regular_CFLAGS@
|
||||
iptables_CFLAGS := @iptables_CFLAGS@
|
||||
kinclude_CFLAGS := @kinclude_CFLAGS@
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${iptables_CFLAGS} ${kinclude_CFLAGS} \
|
||||
-D_INIT=$*_init
|
||||
AM_LDFLAGS = -module -avoid-version
|
||||
ipt_LTLIBRARIES = \
|
||||
libxt_TARPIT.la \
|
||||
libxt_TEE.la
|
||||
|
||||
#
|
||||
# Call out to kbuild
|
||||
#
|
||||
.PHONY: modules modules_install clean_modules
|
||||
|
||||
all-local: modules
|
||||
|
||||
install-exec-local: modules_install
|
||||
|
||||
clean-local: clean_modules
|
||||
|
||||
modules:
|
||||
make -C ${kbuilddir} M=${abssrcdir} modules;
|
||||
|
||||
modules_install:
|
||||
make -C ${kbuilddir} M=${abssrcdir} INSTALL_MOD_PATH=${DESTDIR} modules_install;
|
||||
|
||||
clean_modules:
|
||||
make -C ${kbuilddir} M=${abssrcdir} clean;
|
34
extensions/libxt_TARPIT.c
Normal file
34
extensions/libxt_TARPIT.c
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
|
||||
static void tarpit_tg_help(void)
|
||||
{
|
||||
printf("TARPIT takes no options\n\n");
|
||||
}
|
||||
|
||||
static int tarpit_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tarpit_tg_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static struct xtables_target tarpit_tg_reg = {
|
||||
.version = IPTABLES_VERSION,
|
||||
.name = "TARPIT",
|
||||
.family = AF_INET,
|
||||
.size = XT_ALIGN(0),
|
||||
.userspacesize = XT_ALIGN(0),
|
||||
.help = tarpit_tg_help,
|
||||
.parse = tarpit_tg_parse,
|
||||
.final_check = tarpit_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_target(&tarpit_tg_reg);
|
||||
}
|
33
extensions/libxt_TARPIT.man
Normal file
33
extensions/libxt_TARPIT.man
Normal file
@@ -0,0 +1,33 @@
|
||||
+Captures and holds incoming TCP connections using no local per-connection
|
||||
+resources. Connections are accepted, but immediately switched to the persist
|
||||
+state (0 byte window), in which the remote side stops sending data and asks to
|
||||
+continue every 60-240 seconds. Attempts to close the connection are ignored,
|
||||
+forcing the remote side to time out the connection in 12-24 minutes.
|
||||
+
|
||||
+This offers similar functionality to LaBrea
|
||||
+<http://www.hackbusters.net/LaBrea/> but does not require dedicated hardware or
|
||||
+IPs. Any TCP port that you would normally DROP or REJECT can instead become a
|
||||
+tarpit.
|
||||
+
|
||||
+To tarpit connections to TCP port 80 destined for the current machine:
|
||||
+.IP
|
||||
+-A INPUT -p tcp -m tcp --dport 80 -j TARPIT
|
||||
+.P
|
||||
+To significantly slow down Code Red/Nimda-style scans of unused address space,
|
||||
+forward unused ip addresses to a Linux box not acting as a router (e.g. "ip
|
||||
+route 10.0.0.0 255.0.0.0 ip.of.linux.box" on a Cisco), enable IP forwarding on
|
||||
+the Linux box, and add:
|
||||
+.IP
|
||||
+-A FORWARD -p tcp -j TARPIT
|
||||
+.IP
|
||||
+-A FORWARD -j DROP
|
||||
+.TP
|
||||
+NOTE:
|
||||
+If you use the conntrack module while you are using TARPIT, you should also use
|
||||
+the NOTRACK target, or the kernel will unnecessarily allocate resources for
|
||||
+each TARPITted connection. To TARPIT incoming connections to the standard IRC
|
||||
+port while using conntrack, you could:
|
||||
+.IP
|
||||
+-t raw -A PREROUTING -p tcp --dport 6667 -j NOTRACK
|
||||
+.IP
|
||||
+-A INPUT -p tcp --dport 6667 -j TARPIT
|
111
extensions/libxt_TEE.c
Normal file
111
extensions/libxt_TEE.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* libxt_TEE
|
||||
*
|
||||
* Copyright © Sebastian Claßen <sebastian.classen@freenet.ag>, 2007
|
||||
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
|
||||
* Jan Engelhardt <jengelh@computergmbh.de>
|
||||
*/
|
||||
#include <sys/socket.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_TEE.h"
|
||||
|
||||
enum {
|
||||
FLAG_GATEWAY = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option tee_tg_opts[] = {
|
||||
{.name = "gateway", .has_arg = true, .val = 'g'},
|
||||
{},
|
||||
};
|
||||
|
||||
static void tee_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"TEE target options:\n"
|
||||
" --gateway IPADDR Route packet via the gateway given by address\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_tee_tginfo *info = (void *)(*target)->data;
|
||||
const struct in_addr *ia;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
if (*flags & FLAG_GATEWAY)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gw more than once");
|
||||
|
||||
if (check_inverse(optarg, &invert, NULL, 0))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Unexpected \"!\" after --gateway");
|
||||
|
||||
ia = numeric_to_ipaddr(optarg);
|
||||
if (ia == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid IP address %s", optarg);
|
||||
|
||||
memcpy(&info->gw, &ia, sizeof(ia));
|
||||
*flags |= FLAG_GATEWAY;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void tee_tg_check(unsigned int flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM, "TEE target: "
|
||||
"--gateway parameter required");
|
||||
}
|
||||
|
||||
static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (numeric)
|
||||
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
|
||||
else
|
||||
printf("TEE gw:%s ", ipaddr_to_numeric(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf("--gateway %s ", ipaddr_to_numeric(&info->gw.in));
|
||||
}
|
||||
|
||||
static struct xtables_target tee_tg_reg = {
|
||||
.name = "TEE",
|
||||
.version = IPTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
.parse = tee_tg_parse,
|
||||
.final_check = tee_tg_check,
|
||||
.print = tee_tg_print,
|
||||
.save = tee_tg_save,
|
||||
.extra_opts = tee_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_target(&tee_tg_reg);
|
||||
}
|
16
extensions/xt_TARPIT.Kconfig
Normal file
16
extensions/xt_TARPIT.Kconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
config NETFILTER_XT_TARGET_TARPIT
|
||||
tristate '"TARPIT" target support'
|
||||
depends on NETFILTER_XTABLES
|
||||
---help---
|
||||
Adds a TARPIT target to iptables, which captures and holds incoming TCP
|
||||
connections using no local per-connection resources. Connections are
|
||||
accepted, but immediately switched to the persist state (0 byte
|
||||
window), in which the remote side stops sending data and asks to
|
||||
continue every 60-240 seconds. Attempts to close the connection are
|
||||
ignored, forcing the remote side to time out the connection in 12-24
|
||||
minutes.
|
||||
|
||||
This offers similar functionality to LaBrea
|
||||
<http://www.hackbusters.net/LaBrea/>, but does not require dedicated
|
||||
hardware or IPs. Any TCP port that you would normally DROP or REJECT
|
||||
can instead become a tar pit.
|
237
extensions/xt_TARPIT.c
Normal file
237
extensions/xt_TARPIT.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Kernel module to capture and hold incoming TCP connections using
|
||||
* no local per-connection resources.
|
||||
*
|
||||
* Based on ipt_REJECT.c and offering functionality similar to
|
||||
* LaBrea <http://www.hackbusters.net/LaBrea/>.
|
||||
*
|
||||
* Copyright (c) 2002 Aaron Hopkins <tools@die.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* Goal:
|
||||
* - Allow incoming TCP connections to be established.
|
||||
* - Passing data should result in the connection being switched to the
|
||||
* persist state (0 byte window), in which the remote side stops sending
|
||||
* data and asks to continue every 60 seconds.
|
||||
* - Attempts to shut down the connection should be ignored completely, so
|
||||
* the remote side ends up having to time it out.
|
||||
*
|
||||
* This means:
|
||||
* - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
|
||||
* - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
|
||||
* - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
|
||||
*/
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
# include <linux/netfilter_bridge.h>
|
||||
#endif
|
||||
#include <net/route.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
|
||||
{
|
||||
struct tcphdr _otcph, *oth, *tcph;
|
||||
unsigned int addr_type;
|
||||
struct sk_buff *nskb;
|
||||
struct iphdr *niph;
|
||||
u_int16_t tmp;
|
||||
|
||||
/* A truncated TCP header is not going to be useful */
|
||||
if (oldskb->len < ip_hdrlen(oldskb) + sizeof(struct tcphdr))
|
||||
return;
|
||||
|
||||
oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
|
||||
sizeof(_otcph), &_otcph);
|
||||
if (oth == NULL)
|
||||
return;
|
||||
|
||||
/* No replies for RST, FIN or !SYN,!ACK */
|
||||
if (oth->rst || oth->fin || (!oth->syn && !oth->ack))
|
||||
return;
|
||||
|
||||
/* Rate-limit replies to !SYN,ACKs */
|
||||
#if 0
|
||||
if (!oth->syn && oth->ack)
|
||||
if (!xrlim_allow(&ort->u.dst, HZ))
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Check checksum. */
|
||||
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Copy skb (even if skb is about to be dropped, we cannot just
|
||||
* clone it because there may be other things, such as tcpdump,
|
||||
* interested in it)
|
||||
*/
|
||||
nskb = skb_copy_expand(oldskb, LL_MAX_HEADER,
|
||||
skb_tailroom(oldskb), GFP_ATOMIC);
|
||||
if (nskb == NULL)
|
||||
return;
|
||||
|
||||
/* This packet will not be the same as the other: clear nf fields */
|
||||
nf_reset(nskb);
|
||||
nskb->mark = 0;
|
||||
skb_init_secmark(nskb);
|
||||
|
||||
skb_shinfo(nskb)->gso_size = 0;
|
||||
skb_shinfo(nskb)->gso_segs = 0;
|
||||
skb_shinfo(nskb)->gso_type = 0;
|
||||
|
||||
tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));
|
||||
|
||||
/* Swap source and dest */
|
||||
niph = ip_hdr(nskb);
|
||||
niph->daddr = xchg(&niph->saddr, niph->daddr);
|
||||
tmp = tcph->source;
|
||||
tcph->source = tcph->dest;
|
||||
tcph->dest = tmp;
|
||||
|
||||
/* Truncate to length (no data) */
|
||||
tcph->doff = sizeof(struct tcphdr) / 4;
|
||||
skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
|
||||
niph->tot_len = htons(nskb->len);
|
||||
|
||||
/* Use supplied sequence number or make a new one */
|
||||
tcph->seq = oth->ack ? oth->ack_seq : 0;
|
||||
|
||||
/* Our SYN-ACKs must have a >0 window */
|
||||
tcph->window = (oth->syn && !oth->ack) ? htons(5) : 0;
|
||||
tcph->urg_ptr = 0;
|
||||
|
||||
/* Reset flags */
|
||||
((u_int8_t *)tcph)[13] = 0;
|
||||
|
||||
if (oth->syn && oth->ack) {
|
||||
tcph->rst = true;
|
||||
tcph->ack_seq = false;
|
||||
} else {
|
||||
tcph->syn = oth->syn;
|
||||
tcph->ack = 1;
|
||||
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn);
|
||||
}
|
||||
|
||||
/* Adjust TCP checksum */
|
||||
tcph->check = 0;
|
||||
tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
|
||||
niph->daddr, csum_partial((char *)tcph,
|
||||
sizeof(struct tcphdr), 0));
|
||||
|
||||
/* Set DF, id = 0 */
|
||||
niph->frag_off = htons(IP_DF);
|
||||
niph->id = 0;
|
||||
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (hook != NF_INET_FORWARD || (nskb->nf_bridge != NULL &&
|
||||
nskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
#else
|
||||
if (hook != NF_INET_FORWARD)
|
||||
#endif
|
||||
addr_type = RTN_LOCAL;
|
||||
|
||||
if (ip_route_me_harder(nskb, addr_type))
|
||||
goto free_nskb;
|
||||
|
||||
nskb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
/* Adjust IP TTL */
|
||||
niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
|
||||
|
||||
/* Adjust IP checksum */
|
||||
niph->check = 0;
|
||||
niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl);
|
||||
|
||||
/* "Never happens" */
|
||||
if (nskb->len > dst_mtu(nskb->dst))
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(nskb, oldskb);
|
||||
|
||||
NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
|
||||
dst_output);
|
||||
return;
|
||||
|
||||
free_nskb:
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
tarpit_tg(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
const struct rtable *rt = (const void *)skb->dst;
|
||||
|
||||
/* Do we have an input route cache entry? (Not in PREROUTING.) */
|
||||
if (rt == NULL)
|
||||
return NF_DROP;
|
||||
|
||||
/* No replies to physical multicast/broadcast */
|
||||
/* skb != PACKET_OTHERHOST handled by ip_rcv() */
|
||||
if (skb->pkt_type != PACKET_HOST)
|
||||
return NF_DROP;
|
||||
|
||||
/* Now check at the protocol level */
|
||||
if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
||||
return NF_DROP;
|
||||
|
||||
/*
|
||||
* Our naive response construction does not deal with IP
|
||||
* options, and probably should not try.
|
||||
*/
|
||||
if (ip_hdrlen(skb) != sizeof(struct iphdr))
|
||||
return NF_DROP;
|
||||
|
||||
/* We are not interested in fragments */
|
||||
if (iph->frag_off & htons(IP_OFFSET))
|
||||
return NF_DROP;
|
||||
|
||||
tarpit_tcp(skb, hooknum);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static struct xt_target tarpit_tg_reg __read_mostly = {
|
||||
.name = "TARPIT",
|
||||
.family = AF_INET,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
|
||||
.proto = IPPROTO_TCP,
|
||||
.target = tarpit_tg,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init tarpit_tg_init(void)
|
||||
{
|
||||
return xt_register_target(&tarpit_tg_reg);
|
||||
}
|
||||
|
||||
static void __exit tarpit_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&tarpit_tg_reg);
|
||||
}
|
||||
|
||||
module_init(tarpit_tg_init);
|
||||
module_exit(tarpit_tg_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
MODULE_DESCRIPTION("Xtables: \"TARPIT\", capture and hold TCP connections");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_TARPIT");
|
9
extensions/xt_TEE.Kconfig
Normal file
9
extensions/xt_TEE.Kconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
config NETFILTER_XT_TARGET_TEE
|
||||
tristate '"TEE" target support'
|
||||
depends on NETFILTER_XTABLES
|
||||
depends on NETFILTER_ADVANCED
|
||||
depends on IP_NF_MANGLE || IP6_NF_MANGLE
|
||||
---help---
|
||||
This option adds a "TEE" target, which enables you to duplicate
|
||||
packets and route those duplicates to a different gateway.
|
||||
The target has to be used inside the mangle table.
|
248
extensions/xt_TEE.c
Normal file
248
extensions/xt_TEE.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* This implements the TEE target.
|
||||
*
|
||||
* Copyright (C) 2007 Sebastian Claßen <sebastian.classen@freenet.de> and
|
||||
* CC Computer Consultants GmbH, 2007
|
||||
*
|
||||
* based on ipt_ROUTE.c from Cédric de Launois <delaunois@info.ucl.ac.be>
|
||||
*
|
||||
* This software is distributed under GNU GPL v2, 1991
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/route.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/route.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#ifdef CONFIG_NETFILTER_XT_TARGET_TEE
|
||||
# include <linux/netfilter/xt_TEE.h>
|
||||
#else
|
||||
# include "xt_TEE.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
# define WITH_CONNTRACK 1
|
||||
# include <net/netfilter/nf_conntrack.h>
|
||||
static struct nf_conn tee_track;
|
||||
#endif
|
||||
|
||||
static const union nf_inet_addr zero_address;
|
||||
|
||||
/*
|
||||
* Try to route the packet according to the routing keys specified in
|
||||
* route_info. Keys are :
|
||||
* - ifindex :
|
||||
* 0 if no oif preferred,
|
||||
* otherwise set to the index of the desired oif
|
||||
* - route_info->gateway :
|
||||
* 0 if no gateway specified,
|
||||
* otherwise set to the next host to which the pkt must be routed
|
||||
* If success, skb->dev is the output device to which the packet must
|
||||
* be sent and skb->dst is not NULL
|
||||
*
|
||||
* RETURN: false - if an error occured
|
||||
* true - if the packet was succesfully routed to the
|
||||
* destination desired
|
||||
*/
|
||||
static bool tee_routing(struct sk_buff *skb,
|
||||
const struct xt_tee_tginfo *info)
|
||||
{
|
||||
int err;
|
||||
struct rtable *rt;
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct flowi fl = {
|
||||
.nl_u = {
|
||||
.ip4_u = {
|
||||
.daddr = info->gw.ip,
|
||||
.tos = RT_TOS(iph->tos),
|
||||
.scope = RT_SCOPE_UNIVERSE,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Trying to route the packet using the standard routing table. */
|
||||
err = ip_route_output_key(&rt, &fl);
|
||||
if (err != 0) {
|
||||
if (net_ratelimit())
|
||||
pr_debug(KBUILD_MODNAME
|
||||
": could not route packet (%d)", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Drop old route. */
|
||||
dst_release(skb->dst);
|
||||
skb->dst = NULL;
|
||||
|
||||
/*
|
||||
* Success if no oif specified or if the oif correspond to the
|
||||
* one desired.
|
||||
* [SC]: always the case, because we have no oif.
|
||||
*/
|
||||
skb->dst = &rt->u.dst;
|
||||
skb->dev = skb->dst->dev;
|
||||
skb->protocol = htons(ETH_P_IP);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stolen from ip_finish_output2
|
||||
* PRE : skb->dev is set to the device we are leaving by
|
||||
* skb->dst is not NULL
|
||||
* POST: the packet is sent with the link layer header pushed
|
||||
* the packet is destroyed
|
||||
*/
|
||||
static void tee_ip_direct_send(struct sk_buff *skb)
|
||||
{
|
||||
const struct dst_entry *dst = skb->dst;
|
||||
const struct net_device *dev = dst->dev;
|
||||
unsigned int hh_len = LL_RESERVED_SPACE(dev);
|
||||
|
||||
/* Be paranoid, rather than too clever. */
|
||||
if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops != NULL)) {
|
||||
struct sk_buff *skb2;
|
||||
|
||||
skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
|
||||
if (skb2 == NULL) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
if (skb->sk != NULL)
|
||||
skb_set_owner_w(skb2, skb->sk);
|
||||
kfree_skb(skb);
|
||||
skb = skb2;
|
||||
}
|
||||
|
||||
if (dst->hh != NULL) {
|
||||
neigh_hh_output(dst->hh, skb);
|
||||
} else if (dst->neighbour != NULL) {
|
||||
dst->neighbour->output(skb);
|
||||
} else {
|
||||
if (net_ratelimit())
|
||||
pr_debug(KBUILD_MODNAME "no hdr & no neighbour cache!\n");
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To detect and deter routed packet loopback when using the --tee option, we
|
||||
* take a page out of the raw.patch book: on the copied skb, we set up a fake
|
||||
* ->nfct entry, pointing to the local &route_tee_track. We skip routing
|
||||
* packets when we see they already have that ->nfct.
|
||||
*/
|
||||
static unsigned int
|
||||
tee_tg(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = targinfo;
|
||||
|
||||
#ifdef WITH_CONNTRACK
|
||||
if (skb->nfct == &tee_track.ct_general) {
|
||||
/*
|
||||
* Loopback - a packet we already routed, is to be
|
||||
* routed another time. Avoid that, now.
|
||||
*/
|
||||
if (net_ratelimit())
|
||||
pr_debug(KBUILD_MODNAME "loopback - DROP!\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we are in INPUT, the checksum must be recalculated since
|
||||
* the length could have changed as a result of defragmentation.
|
||||
*/
|
||||
if (hooknum == NF_INET_LOCAL_IN) {
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
iph->check = 0;
|
||||
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the skb, and route the copy. Will later return %XT_CONTINUE for
|
||||
* the original skb, which should continue on its way as if nothing has
|
||||
* happened. The copy should be independantly delivered to the TEE --gw.
|
||||
*/
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
if (net_ratelimit())
|
||||
pr_debug(KBUILD_MODNAME "copy failed!\n");
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef WITH_CONNTRACK
|
||||
/*
|
||||
* Tell conntrack to forget this packet since it may get confused
|
||||
* when a packet is leaving with dst address == our address.
|
||||
* Good idea? Dunno. Need advice.
|
||||
*
|
||||
* NEW: mark the skb with our &tee_track, so we avoid looping
|
||||
* on any already routed packet.
|
||||
*/
|
||||
nf_conntrack_put(skb->nfct);
|
||||
skb->nfct = &tee_track.ct_general;
|
||||
skb->nfctinfo = IP_CT_NEW;
|
||||
nf_conntrack_get(skb->nfct);
|
||||
#endif
|
||||
|
||||
if (tee_routing(skb, info))
|
||||
tee_ip_direct_send(skb);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static bool tee_tg_check(const char *tablename, const void *entry,
|
||||
const struct xt_target *target, void *targinfo,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = targinfo;
|
||||
|
||||
/* 0.0.0.0 and :: not allowed */
|
||||
return memcmp(&info->gw, &zero_address, sizeof(zero_address)) != 0;
|
||||
}
|
||||
|
||||
static struct xt_target tee_tg_reg __read_mostly = {
|
||||
.name = "TEE",
|
||||
.family = AF_INET,
|
||||
.table = "mangle",
|
||||
.target = tee_tg,
|
||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||
.checkentry = tee_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init tee_tg_init(void)
|
||||
{
|
||||
#ifdef WITH_CONNTRACK
|
||||
/*
|
||||
* Set up fake conntrack (stolen from raw.patch):
|
||||
* - to never be deleted, not in any hashes
|
||||
*/
|
||||
atomic_set(&tee_track.ct_general.use, 1);
|
||||
|
||||
/* - and look it like as a confirmed connection */
|
||||
set_bit(IPS_CONFIRMED_BIT, &tee_track.status);
|
||||
|
||||
/* Initialize fake conntrack so that NAT will skip it */
|
||||
tee_track.status |= IPS_NAT_DONE_MASK;
|
||||
#endif
|
||||
|
||||
return xt_register_target(&tee_tg_reg);
|
||||
}
|
||||
|
||||
static void __exit tee_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&tee_tg_reg);
|
||||
/* [SC]: shoud not we cleanup tee_track here? */
|
||||
}
|
||||
|
||||
module_init(tee_tg_init);
|
||||
module_exit(tee_tg_exit);
|
||||
MODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
MODULE_DESCRIPTION("Xtables: Reroute packet copy");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_TEE");
|
8
extensions/xt_TEE.h
Normal file
8
extensions/xt_TEE.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef _XT_TEE_TARGET_H
|
||||
#define _XT_TEE_TARGET_H
|
||||
|
||||
struct xt_tee_tginfo {
|
||||
union nf_inet_addr gw;
|
||||
};
|
||||
|
||||
#endif /* _XT_TEE_TARGET_H */
|
Reference in New Issue
Block a user