Compare commits

..

40 Commits

Author SHA1 Message Date
Jan Engelhardt
463dceb709 Xtables-addons 1.5.3 2008-03-22 05:17:04 +01:00
Jan Engelhardt
cd323565d7 Merge reworked geoip extension 2008-03-22 05:16:53 +01:00
Jan Engelhardt
a39bfdf98e Add xt_ECHO sample target 2008-03-22 05:16:47 +01:00
Jan Engelhardt
cd7c8fc4fa geoip: minor cleanups in help, opts and logic 2008-03-22 03:59:58 +01:00
Jan Engelhardt
5d431b45f1 geoip: use simpler, preprocessed integer vector lists and fix endian issue
The old database format was in unknown byteorder -- if you run the
converter program yourself, you got a host order file, but if you
downloaded the preprocessed DB file (geoipdb.bin), you got a
little-endian file.

Use a new database format. Instead of having an index and a DB file,
do away with the index and let the filesystem do the indexing, using
one file per country. Also access the database files with a known
endianess type. The converter script now produces two distinct
variants (especially needed for IA-64).

All of this reduces the touched code by half.
2008-03-22 03:59:57 +01:00
Jan Engelhardt
f4c4208e75 geoip: use appropriate and normal types
For the header file, we need __u32 and so on because they are exported
to userspace and rather constitute a kernel header.

Use normal types instead of uintXX_t in the main code.
2008-03-22 03:59:57 +01:00
Jan Engelhardt
52a0ed7f15 geoip: use rcu to reduce time spinlocks are held
spin_lock_bh does not look safe (only disables preempt on current
CPU?). Change to spin_lock, that also avoids the management overhead
of spin_lock_bh. to spin_lock to avoid management overhead.

Use rcu in match and destroy function.
2008-03-22 03:59:57 +01:00
Jan Engelhardt
000d813171 geoip: use real atomic_t and remove casts from uint32_t 2008-03-22 03:59:57 +01:00
Jan Engelhardt
e45cb21ad6 geoip: use struct list_head instead of self-cooked list 2008-03-22 03:59:57 +01:00
Jan Engelhardt
7aae90da5a geoip: use local-portable aligned_u64 pointer values
A 64-bit kernel will interpret the pointer with 64 bits width, while
a 32-bit userspace filled in only 32 of it, leaving the other 32
undefined. This must be avoided.
2008-03-22 03:59:56 +01:00
Jan Engelhardt
fd5321c7d8 geoip: split user/kernel-visible parts of struct geoip_info 2008-03-22 03:59:56 +01:00
Jan Engelhardt
65eeb7f1f6 geoip: use vmalloc due to potential list size
The subnet list may become really large (United States: ~15000
entries), which means a use of roughly 120 KB, and kmalloc may fail
to find a contiguous block in physical memory. Virtual contiguity is
enough, so use vmalloc/vfree.

vfree may not be called within a spin_lock_bh area, so release the
lock first, it is safe to do so.
2008-03-22 03:59:55 +01:00
Jan Engelhardt
848484c08c geoip: use a binary search to replace the current linear one
Certain countries have lots (around 10000) of IP address ranges
(US,GB,DE,...). The current linear search is really bad:

No firewall:
3000 packets transmitted, 3000 received, 0% packet loss, time 1992ms

Testing against the countries with top 50 IP ranges:
3000 packets transmitted, 3000 received, 0% packet loss, time 8998ms

With binary search:
3000 packets transmitted, 3000 received, 0% packet loss, time 2358ms
2008-03-22 03:59:45 +01:00
Jan Engelhardt
8c58a61f52 geoip: address comparison is inclusive
subnet is somewhat a wrong term, geoip actually uses ipranges. Either
way, the comparison needs to be >= and <= instead of > <.
2008-03-22 03:59:45 +01:00
Jan Engelhardt
93c7d0ac47 geoip: lock timing correctness
find_node: The reference count needs to be increased while the lock
is held. Otherwise, the node may disappear right after the lock was
released and increase was attempted, leading to an oops.

remove_node: The reference count needs to be checked while the lock
is held. Otherwise, the node may be used in the match function or
returned from find_node while it has a zero refcount.
2008-03-22 03:59:45 +01:00
Jan Engelhardt
df063ab61c geoip: add missing kfree in error path 2008-03-22 03:59:44 +01:00
Jan Engelhardt
d480ea2b1f geoip: sort #include list 2008-03-22 03:59:44 +01:00
Jan Engelhardt
205a006ac9 geoip: use tabs not spaces and indent 2008-03-22 03:59:44 +01:00
Jan Engelhardt
9f45aa737a geoip: remove redundant casts 2008-03-22 03:59:44 +01:00
Jan Engelhardt
f1615a03f3 geoip: remove unused code and unneeded per-info refcount
- freeing userspace memory is not the kernel's job, really.
- checkentry is called exactly once, as is destroy.
2008-03-22 03:59:44 +01:00
Jan Engelhardt
3554e348bc geoip: import 20080214 code base 2008-03-22 03:59:42 +01:00
Jan Engelhardt
5fd97e9973 compat update: allow building from 2.6.18 onwards 2008-03-12 04:28:40 +01:00
Jan Engelhardt
10e3d8fe0d Update .gitignore 2008-03-12 04:28:38 +01:00
Jan Engelhardt
6c06796e3b Makefile: add missing xtables_CFLAGS variable
If xtables.h is to be found in a directory other than included in the
default preprocessor search path, compilation failed because the path
specified with --with-xtables= was not passed to gcc.
2008-03-05 00:19:15 +01:00
Jan Engelhardt
98f943cb6c Xtables-addons 1.5.2
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-03-04 05:17:00 +01:00
Jan Engelhardt
cedbb110e1 Makefile: add "tarball" target
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-03-04 05:16:35 +01:00
Jan Engelhardt
c703be229a Remove XTABLES_VERSION define, it is now provided by xtables.h
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-03-04 05:13:34 +01:00
Jan Engelhardt
c338e8f827 Move defines in compat_xtables.h down to avoid redeclaration errors
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-03-04 05:12:06 +01:00
Jan Engelhardt
7c09f5db2f Use system's readlink program to make things work with GNU make < 3.81
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-29 13:49:04 +01:00
Jan Engelhardt
6177839a04 Xtables-addons 1.5.1
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 18:56:47 +01:00
Jan Engelhardt
4d22fbd97a Use AF_UNSPEC registration in libxt_LOGMARK
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 18:56:47 +01:00
Jan Engelhardt
dd42c61581 Change IPTABLES_VERSION to XTABLES_VERSION
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 18:56:47 +01:00
Jan Engelhardt
2fbfbe6cd4 Import Chaostables extensions
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 18:56:21 +01:00
Jan Engelhardt
ec9663f680 Remove compat code for kernels below 2.6.22
Some code already uses ip_hdr() functions which did not exist in
2.6.21 and I do not feel like adding more compat code.

Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 13:35:19 +01:00
Jan Engelhardt
75e88a7321 Update compat code for new 2.6.25 code
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-21 13:29:31 +01:00
Jan Engelhardt
1e34f02034 xt_LOGMARK: dump CLASSIFY mark, ctstate and ctstatus
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-20 23:17:55 +01:00
Jan Engelhardt
b69d3de40e Add support for external tarballs
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-16 16:10:40 +01:00
Jan Engelhardt
c1592673fb Allow external projects to be downloaded into the tree and used
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-15 02:21:35 +01:00
Jan Engelhardt
da011c8871 Allow user to select what extensions to compile and install
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-14 17:49:47 +01:00
Jan Engelhardt
f360ec3c85 Only include ksource header directory when explicitly specified
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
2008-02-14 15:28:44 +01:00
40 changed files with 2325 additions and 179 deletions

7
.gitignore vendored
View File

@@ -1,16 +1,13 @@
.*.cmd
*.ko
*.la
*.lo
*.loT
*.mod.c
*.o
.deps
.libs
.tmp_versions
Makefile
Makefile.in
Module.symvers
/downloads
/aclocal.m4
/autom4te*.cache

11
INSTALL
View File

@@ -12,9 +12,16 @@ in combination with the kernel's Kbuild system.
Prerequirements
===============
* xtables(-devel) 1.5.0
* xtables(-devel) 1.5.2
* kernel-source >= 2.6.19 with prepared output directory
* kernel-source >= 2.6.18 with prepared build/output directory
Selecting extensions
====================
You can edit the "mconfig" file to select what modules to build and
install. By default, all modules are enabled.
Configuring and compiling

View File

@@ -2,3 +2,11 @@
AUTOMAKE_OPTIONS = foreign subdir-objects
SUBDIRS = extensions
.PHONY: tarball
tarball:
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};
pushd ${top_srcdir} && git-archive --prefix=xtables-addons-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
pushd /tmp/xtables-addons-${PACKAGE_VERSION} && ./autogen.sh && popd;
tar -C /tmp -cjf xtables-addons-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root xtables-addons-${PACKAGE_VERSION}/;
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};

29
README
View File

@@ -8,3 +8,32 @@ package.
Xtables-addons is different from patch-o-matic in that you do not have
to patch or recompile either kernel or Xtables(iptables). But please
see the INSTALL file for the minimum requirements of this package.
External extensions
===================
The program "xa-download-more" can be used to download more extensions
from 3rd parties into the source tree. The URLs are listed in the
"sources" file. If the "sources" file contains an entry like
http://foobar.org/xa/
xa-download-more will inspect http://foobar.org/xa/xa-index.txt for files
to download. That file may contain
foobar.tar.bz2
and xa-download-more will then retrieve and unpack
http://foobar.org/xa/foobar.tar.bz2.
Files that should be contained in the tarball are an mconfig and Kbuild
files to control building the extension, libxt_foobar.c for the userspace
extension and xt_foobar.c for the kernel extension.
mconfig.foobar
extensions/Kbuild.foobar
extensions/libxt_foobar.c
extensions/libxt_foobar.man
extensions/xt_foobar.c
extensions/xt_foobar.h

View File

@@ -1,5 +1,5 @@
AC_INIT([xtables-addons], [1.5.0])
AC_INIT([xtables-addons], [1.5.3])
AC_CONFIG_HEADERS([config.h])
AC_PROG_INSTALL
AM_INIT_AUTOMAKE
@@ -9,7 +9,6 @@ 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]]]),
@@ -51,12 +50,17 @@ 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\\\" \
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\"";
kinclude_CFLAGS="-I $kbuilddir/include -I $ksourcedir/include";
-Winline -pipe -DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\"";
kinclude_CFLAGS="";
if [[ -n "$kbuilddir" ]]; then
kinclude_CFLAGS="$kinclude_CFLAGS -I $kbuilddir/include";
fi;
if [[ -n "$ksourcedir" ]]; then
kinclude_CFLAGS="$kinclude_CFLAGS -I $ksourcedir/include";
fi;
AC_SUBST([regular_CFLAGS xtables_CFLAGS kinclude_CFLAGS])
AC_SUBST([kbuilddir])
AC_SUBST([ksourcedir])
AC_SUBST([xtlibdir])
AC_OUTPUT([Makefile extensions/Makefile])
AC_OUTPUT([Makefile extensions/GNUmakefile])

10
extensions/.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
.*.cmd
.*.d
.tmp_versions
*.ko
*.mod.c
*.so
*.oo
GNUmakefile
Module.symvers
modules.order

100
extensions/GNUmakefile.in Normal file
View File

@@ -0,0 +1,100 @@
# -*- Makefile -*-
top_srcdir := @top_srcdir@
srcdir := @srcdir@
abstop_srcdir := $(shell readlink -e ${top_srcdir})
abssrcdir := $(shell readlink -e ${srcdir})
ifeq (${abstop_srcdir},)
$(error Path resolution of ${top_srcdir} failed)
endif
ifeq (${abssrcdir},)
$(error Path resolution of ${srcdir} failed)
endif
prefix := @prefix@
exec_prefix := @exec_prefix@
libdir := @libdir@
libexecdir := @libexecdir@
xtlibdir := @xtlibdir@
kbuilddir := @kbuilddir@
CC := @CC@
CCLD := ${CC}
CFLAGS := @CFLAGS@
LDFLAGS := @LDFLAGS@
regular_CFLAGS := @regular_CFLAGS@
kinclude_CFLAGS := @kinclude_CFLAGS@
xtables_CFLAGS := @xtables_CFLAGS@
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS}
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
ifeq (${V},)
AM_LIBTOOL_SILENT = --silent
AM_VERBOSE_CC = @echo " CC " $@;
AM_VERBOSE_CCLD = @echo " CCLD " $@;
AM_VERBOSE_CXX = @echo " CXX " $@;
AM_VERBOSE_CXXLD = @echo " CXXLD " $@;
AM_VERBOSE_AR = @echo " AR " $@;
AM_VERBOSE_GEN = @echo " GEN " $@;
endif
#
# Wildcard module list
#
include ${top_srcdir}/mconfig
-include ${top_srcdir}/mconfig.*
pfx_all_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(wildcard ${srcdir}/libxt_*.c))
pfx_build_mod := $(foreach i,${pfx_all_mod},$(if ${build_${i}},${i},))
pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
#
# Building blocks
#
targets := ${pfx_solibs}
targets_install := ${pfx_solibs}
.SECONDARY:
.PHONY: all install clean distclean FORCE
all: modules ${targets}
install: modules_install ${targets_install}
@mkdir -p "${DESTDIR}${xtlibdir}";
install -pm0755 ${targets_install} "${DESTDIR}${xtlibdir}/";
clean: clean_modules
rm -f *.oo *.so;
distclean: clean
rm -f .*.d;
-include .*.d
#
# Call out to kbuild
#
.PHONY: modules modules_install clean_modules
modules:
make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} modules;
modules_install:
make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} INSTALL_MOD_PATH=${DESTDIR} modules_install;
clean_modules:
make -C ${kbuilddir} M=${abssrcdir} XA_TOPSRCDIR=${abstop_srcdir} clean;
#
# Shared libraries
#
lib%.so: lib%.oo
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
lib%.oo: ${srcdir}/lib%.c
${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;

View File

@@ -1,6 +1,17 @@
# -*- Makefile -*-
obj-m += xt_LOGMARK.o
obj-m += xt_TARPIT.o
obj-m += xt_TEE.o
obj-m += compat_xtables.o
include ${XA_TOPSRCDIR}/mconfig
-include ${XA_TOPSRCDIR}/mconfig.*
obj-m += compat_xtables.o
obj-${build_CHAOS} += xt_CHAOS.o
obj-${build_DELUDE} += xt_DELUDE.o
obj-${build_ECHO} += xt_ECHO.o
obj-${build_LOGMARK} += xt_LOGMARK.o
obj-${build_TARPIT} += xt_TARPIT.o
obj-${build_TEE} += xt_TEE.o
obj-${build_geoip} += xt_geoip.o
obj-${build_portscan} += xt_portscan.o
-include ${M}/*.Kbuild

View File

@@ -1,36 +0,0 @@
# -*- Makefile -*-
AUTOMAKE_OPTIONS = foreign subdir-objects
abssrcdir = $(shell readlink -f ${srcdir})
regular_CFLAGS := @regular_CFLAGS@
xtables_CFLAGS := @xtables_CFLAGS@
kinclude_CFLAGS := @kinclude_CFLAGS@
AM_CFLAGS = ${regular_CFLAGS} -I ${top_srcdir}/include \
${xtables_CFLAGS} ${kinclude_CFLAGS} \
-D_INIT=$*_init
AM_LDFLAGS = -module -avoid-version
xtlib_LTLIBRARIES = \
libxt_LOGMARK.la \
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;

View File

@@ -0,0 +1,20 @@
#ifndef COMPAT_SKBUFF_H
#define COMPAT_SKBUFF_H 1
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->nfmark)
#else
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->mark)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21)
# define ip_hdr(skb) ((skb)->nh.iph)
# define ip_hdrlen(skb) (ip_hdr(skb)->ihl * 4)
# define skb_network_header(skb) ((skb)->nh.raw)
static inline void skb_reset_network_header(struct sk_buff *skb)
{
skb->nh.raw = skb->data;
}
#endif
#endif /* COMPAT_SKBUFF_H */

View File

@@ -1,3 +1,4 @@
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/slab.h>
@@ -5,10 +6,13 @@
#include <linux/version.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp.h>
#include <net/ip.h>
#include <net/route.h>
#include "compat_skbuff.h"
#include "compat_xtnu.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && \
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static int xtnu_match_run(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
const struct xt_match *cm, const void *matchinfo, int offset,
@@ -24,9 +28,17 @@ static int xtnu_match_run(const struct sk_buff *skb,
*hotdrop = lo_drop;
return lo_ret;
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
static int xtnu_match_check(const char *table, const void *entry,
const struct xt_match *cm, void *matchinfo, unsigned int matchinfosize,
unsigned int hook_mask)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static int xtnu_match_check(const char *table, const void *entry,
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
{
struct xtnu_match *nm = xtcompat_numatch(cm);
@@ -36,15 +48,24 @@ static int xtnu_match_check(const char *table, const void *entry,
return true;
return nm->checkentry(table, entry, nm, matchinfo, hook_mask);
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo,
unsigned int matchinfosize)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
{
struct xtnu_match *nm = xtcompat_numatch(cm);
if (nm != NULL && nm->destroy != NULL)
nm->destroy(nm, matchinfo);
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
int xtnu_register_match(struct xtnu_match *nt)
{
struct xt_match *ct;
@@ -114,53 +135,63 @@ void xtnu_unregister_matches(struct xtnu_match *nt, unsigned int num)
EXPORT_SYMBOL_GPL(xtnu_unregister_matches);
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static int xtnu_target_check(const char *table, const void *entry,
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
{
struct xtnu_target *nt = xtcompat_nutarget(ct);
if (nt == NULL)
return false;
if (nt->checkentry == NULL)
/* this is valid, just like if there was no function */
return true;
return nt->checkentry(table, entry, nt, targinfo, hook_mask);
}
#endif
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 23)
static bool xtnu_target_check(const char *table, const void *entry,
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
{
struct xtnu_target *nt = xtcompat_nutarget(ct);
if (nt == NULL)
return false;
if (nt->checkentry == NULL)
/* this is valid, just like if there was no function */
return true;
return nt->checkentry(table, entry, nt, targinfo, hook_mask);
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && \
LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
static unsigned int xtnu_target_run(struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *ct, const void *targinfo,
void *userdata)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
static unsigned int xtnu_target_run(struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
{
struct xtnu_target *nt = xtcompat_nutarget(ct);
if (nt != NULL && nt->target != NULL)
return nt->target(*pskb, in, out, hooknum, nt, targinfo);
return XT_CONTINUE;
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
static int xtnu_target_check(const char *table, const void *entry,
const struct xt_target *ct, void *targinfo,
unsigned int targinfosize, unsigned int hook_mask)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
static int xtnu_target_check(const char *table, const void *entry,
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
static bool xtnu_target_check(const char *table, const void *entry,
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
{
struct xtnu_target *nt = xtcompat_nutarget(ct);
if (nt == NULL)
return false;
if (nt->checkentry == NULL)
/* this is valid, just like if there was no function */
return true;
return nt->checkentry(table, entry, nt, targinfo, hook_mask);
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo,
unsigned int targinfosize)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
{
struct xtnu_target *nt = xtcompat_nutarget(ct);
if (nt != NULL && nt->destroy != NULL)
nt->destroy(nt, targinfo);
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
int xtnu_register_target(struct xtnu_target *nt)
{
struct xt_target *ct;
@@ -230,12 +261,109 @@ void xtnu_unregister_targets(struct xtnu_target *nt, unsigned int num)
EXPORT_SYMBOL_GPL(xtnu_unregister_targets);
#endif
struct xt_match *xtnu_request_find_match(unsigned int af, const char *name,
uint8_t revision)
{
static const char *const xt_prefix[] = {
[AF_UNSPEC] = "x",
[AF_INET] = "ip",
[AF_INET6] = "ip6",
#ifdef AF_ARP
[AF_ARP] = "arp",
#elif defined(NF_ARP) && NF_ARP != AF_UNSPEC
[NF_ARP] = "arp",
#endif
};
struct xt_match *match;
match = try_then_request_module(xt_find_match(af, name, revision),
"%st_%s", xt_prefix[af], name);
if (IS_ERR(match) || match == NULL)
return NULL;
return match;
}
EXPORT_SYMBOL_GPL(xtnu_request_find_match);
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
int xtnu_ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
{
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
return ip_route_me_harder(&skb);
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
return ip_route_me_harder(&skb, addr_type);
#endif
}
EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder);
#endif
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 24)
static int __xtnu_ip_local_out(struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
iph->tot_len = htons(skb->len);
ip_send_check(iph);
return nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
skb->dst->dev, dst_output);
}
int xtnu_ip_local_out(struct sk_buff *skb)
{
int err;
err = __xtnu_ip_local_out(skb);
if (likely(err == 1))
err = dst_output(skb);
return err;
}
EXPORT_SYMBOL_GPL(xtnu_ip_local_out);
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
static int __xtnu_ip_local_out(struct sk_buff **pskb)
{
struct iphdr *iph = ip_hdr(*pskb);
iph->tot_len = htons((*pskb)->len);
ip_send_check(iph);
return nf_hook(PF_INET, NF_IP_LOCAL_OUT, pskb, NULL,
(*pskb)->dst->dev, dst_output);
}
int xtnu_ip_local_out(struct sk_buff *skb)
{
int err;
err = __xtnu_ip_local_out(&skb);
if (likely(err == 1))
err = dst_output(skb);
return err;
}
EXPORT_SYMBOL_GPL(xtnu_ip_local_out);
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
int xtnu_ip_route_output_key(void *net, struct rtable **rp, struct flowi *flp)
{
return ip_route_output_flow(rp, flp, NULL, 0);
}
EXPORT_SYMBOL_GPL(xtnu_ip_route_output_key);
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
int xtnu_neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
{
unsigned int hh_alen;
read_lock_bh(&hh->hh_lock);
hh_alen = HH_DATA_ALIGN(hh->hh_len);
memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len);
return hh->hh_output(skb);
}
EXPORT_SYMBOL_GPL(xtnu_neigh_hh_output);
#endif
MODULE_LICENSE("GPL");

View File

@@ -2,17 +2,50 @@
#define _XTABLES_COMPAT_H 1
#include <linux/version.h>
#include "compat_skbuff.h"
#include "compat_xtnu.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
# warning Kernels below 2.6.18 not supported.
#endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
# if !defined(CONFIG_NF_CONNTRACK_MARK) || !defined(CONFIG_NF_CONNTRACK_SECMARK)
# warning You have CONFIG_NF_CONNTRACK enabled, but CONFIG_NF_CONNTRACK_MARK or CONFIG_NF_CONNTRACK_SECMARK are not (please enable).
# endif
# include <net/netfilter/nf_conntrack.h>
#elif defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
# if !defined(CONFIG_IP_NF_CONNTRACK_MARK) || !defined(CONFIG_IP_NF_CONNTRACK_SECMARK)
# warning You have CONFIG_IP_NF_CONNTRACK enabled, but CONFIG_IP_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_SECMARK are not (please enable).
# endif
# include <linux/netfilter_ipv4/ip_conntrack.h>
# define nf_conn ip_conntrack
# define nf_ct_get ip_conntrack_get
# define nf_conntrack_untracked ip_conntrack_untracked
#else
# warning You need either CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK.
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
# define neigh_hh_output xtnu_neigh_hh_output
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
# define NF_INET_PRE_ROUTING NF_IP_PRE_ROUTING
# define NF_INET_LOCAL_IN NF_IP_LOCAL_IN
# define NF_INET_FORWARD NF_IP_FORWARD
# define NF_INET_LOCAL_OUT NF_IP_LOCAL_OUT
# define NF_INET_POST_ROUTING NF_IP_POST_ROUTING
# define ip_local_out xtnu_ip_local_out
# define ip_route_output_key xtnu_ip_route_output_key
# include "compat_nfinetaddr.h"
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
# include "compat_nfinetaddr.h"
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
# define init_net xtnu_ip_route_output_key /* yes */
# define init_net__loopback_dev (&loopback_dev)
#else
# define init_net__loopback_dev init_net.loopback_dev
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
@@ -32,6 +65,6 @@
# define xt_unregister_targets xtnu_unregister_targets
#endif
#include "compat_xtnu.h"
#define xt_request_find_match xtnu_request_find_match
#endif /* _XTABLES_COMPAT_H */

View File

@@ -5,8 +5,16 @@
#include <linux/netfilter/x_tables.h>
#include <linux/spinlock.h>
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
typedef _Bool bool;
enum { false = 0, true = 1, };
#endif
struct flowi;
struct hh_cache;
struct module;
struct net_device;
struct rtable;
struct sk_buff;
struct xtnu_match {
@@ -59,8 +67,10 @@ static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t)
return q;
}
extern int xtnu_ip_local_out(struct sk_buff *);
extern int xtnu_ip_route_me_harder(struct sk_buff *, unsigned int);
extern int xtnu_register_match(struct xtnu_match *);
extern int xtnu_ip_route_output_key(void *, struct rtable **, struct flowi *);
extern void xtnu_unregister_match(struct xtnu_match *);
extern int xtnu_register_matches(struct xtnu_match *, unsigned int);
extern void xtnu_unregister_matches(struct xtnu_match *, unsigned int);
@@ -68,5 +78,8 @@ extern int xtnu_register_target(struct xtnu_target *);
extern void xtnu_unregister_target(struct xtnu_target *);
extern int xtnu_register_targets(struct xtnu_target *, unsigned int);
extern void xtnu_unregister_targets(struct xtnu_target *, unsigned int);
extern struct xt_match *xtnu_request_find_match(unsigned int,
const char *, uint8_t);
extern int xtnu_neigh_hh_output(struct hh_cache *, struct sk_buff *);
#endif /* _COMPAT_XTNU_H */

113
extensions/libxt_CHAOS.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* CHAOS target for Xtables
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License; either version
* 2 or 3 as published by the Free Software Foundation.
*/
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include "xt_CHAOS.h"
enum {
F_DELUDE = 1 << 0,
F_TARPIT = 1 << 1,
};
static const struct option chaos_tg_opts[] = {
{.name = "delude", .has_arg = false, .val = 'd'},
{.name = "tarpit", .has_arg = false, .val = 't'},
{},
};
static void chaos_tg_help(void)
{
printf(
"CHAOS target options:\n"
" --delude Enable DELUDE processing for TCP\n"
" --tarpit Enable TARPIT processing for TCP\n");
}
static int chaos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_chaos_tginfo *info = (void *)((*target)->data);
switch (c) {
case 'd':
info->variant = XTCHAOS_DELUDE;
*flags |= F_DELUDE;
return true;
case 't':
info->variant = XTCHAOS_TARPIT;
*flags |= F_TARPIT;
return true;
}
return false;
}
static void chaos_tg_check(unsigned int flags)
{
if (flags == (F_DELUDE | F_TARPIT))
/* If flags == 0x03, both were specified, which should not be. */
exit_error(PARAMETER_PROBLEM,
"CHAOS: only one of --tarpit or --delude "
"may be specified");
}
static void chaos_tg_print(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_chaos_tginfo *info = (const void *)target->data;
switch (info->variant) {
case XTCHAOS_DELUDE:
printf("DELUDE ");
break;
case XTCHAOS_TARPIT:
printf("TARPIT ");
break;
}
return;
}
static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_chaos_tginfo *info = (const void *)target->data;
switch (info->variant) {
case XTCHAOS_DELUDE:
printf("--delude ");
break;
case XTCHAOS_TARPIT:
printf("--tarpit ");
break;
}
return;
}
static struct xtables_target chaos_tg_reg = {
.version = XTABLES_VERSION,
.name = "CHAOS",
.family = AF_INET,
.size = XT_ALIGN(sizeof(struct xt_chaos_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_chaos_tginfo)),
.help = chaos_tg_help,
.parse = chaos_tg_parse,
.final_check = chaos_tg_check,
.print = chaos_tg_print,
.save = chaos_tg_save,
.extra_opts = chaos_tg_opts,
};
void _init(void);
void _init(void)
{
xtables_register_target(&chaos_tg_reg);
}

View File

@@ -0,0 +1,18 @@
+Causes confusion on the other end by doing odd things with incoming packets.
+CHAOS will randomly reply (or not) with one of its configurable subtargets:
+.TP
+\fB--delude\fR
+Use the REJECT and DELUDE targets as a base to do a sudden or deferred
+connection reset, fooling some network scanners to return non-deterministic
+(randomly open/closed) results, and in case it is deemed open, it is actually
+closed/filtered.
+.TP
+\fB--tarpit\fR
+Use the REJECT and TARPIT target as a base to hold the connection until it
+times out. This consumes conntrack entries when connection tracking is loaded
+(which usually is on most machines), and routers inbetween you and the Internet
+may fail to do their connection tracking if they have to handle more
+connections than they can.
+.PP
+The randomness factor of not replying vs. replying can be set during load-time
+of the xt_CHAOS module or during runtime in /sys/modules/xt_CHAOS/parameters.

47
extensions/libxt_DELUDE.c Normal file
View File

@@ -0,0 +1,47 @@
/*
* DELUDE target for Xtables
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License; either version
* 2 or 3 as published by the Free Software Foundation.
*/
#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
static void delude_tg_help(void)
{
printf("DELUDE takes no options\n");
}
static int delude_tg_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
return 0;
}
static void delude_tg_check(unsigned int flags)
{
}
static struct xtables_target delude_tg_reg = {
.version = XTABLES_VERSION,
.name = "DELUDE",
.revision = 0,
.family = AF_INET,
.size = XT_ALIGN(0),
.userspacesize = XT_ALIGN(0),
.help = delude_tg_help,
.parse = delude_tg_parse,
.final_check = delude_tg_check,
};
void _init(void);
void _init(void)
{
xtables_register_target(&delude_tg_reg);
}

View File

@@ -0,0 +1,4 @@
The DELUDE target will reply to a SYN packet with SYN-ACK, and to all other
packets with an RST. This will terminate the connection much like REJECT, but
network scanners doing TCP half-open discovery can be spoofed to make them
belive the port is open rather than closed/filtered.

34
extensions/libxt_ECHO.c Normal file
View File

@@ -0,0 +1,34 @@
#include <stdio.h>
#include <getopt.h>
#include <xtables.h>
static void echo_tg_help(void)
{
printf("ECHO takes no options\n\n");
}
static int echo_tg_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
return 0;
}
static void echo_tg_check(unsigned int flags)
{
}
static struct xtables_target echo_tg_reg = {
.version = XTABLES_VERSION,
.name = "ECHO",
.family = AF_UNSPEC,
.size = XT_ALIGN(0),
.userspacesize = XT_ALIGN(0),
.help = echo_tg_help,
.parse = echo_tg_parse,
.final_check = echo_tg_check,
};
static void _init(void)
{
xtables_register_target(&echo_tg_reg);
}

View File

@@ -6,19 +6,13 @@
#include "xt_LOGMARK.h"
enum {
F_LEVEL = 1 << 0,
F_PREFIX = 1 << 1,
F_NFMARK = 1 << 2,
F_CTMARK = 1 << 3,
F_SECMARK = 1 << 4,
F_LEVEL = 1 << 0,
F_PREFIX = 1 << 1,
};
static const struct option logmark_tg_opts[] = {
{.name = "log-level", .has_arg = true, .val = 'l'},
{.name = "log-prefix", .has_arg = true, .val = 'p'},
{.name = "log-nfmark", .has_arg = false, .val = 'n'},
{.name = "log-ctmark", .has_arg = false, .val = 'c'},
{.name = "log-secmark", .has_arg = false, .val = 's'},
{},
};
@@ -28,9 +22,6 @@ static void logmark_tg_help(void)
"LOGMARK target options:\n"
" --log-level level Level of logging (numeric, 0-8)\n"
" --log-prefix prefix Prefix log messages with this string\n"
" --log-nfmark Log the packet mark\n"
" --log-ctmark Log the connection mark\n"
" --log-secmark Log the security mark of the packet\n"
);
}
@@ -72,27 +63,6 @@ logmark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
strncpy(info->prefix, optarg, sizeof(info->prefix));
*flags |= F_PREFIX;
return true;
case 'n': /* --log-nfmark */
param_act(P_ONLY_ONCE, "LOGMARK", "--log-nfmark", *flags & F_NFMARK);
param_act(P_NO_INVERT, "LOGMARK", "--log-nfmark", invert);
info->flags |= XT_LOGMARK_NFMARK;
*flags |= F_NFMARK;
return true;
case 'c': /* --log-ctmark */
param_act(P_ONLY_ONCE, "LOGMARK", "--log-ctmark", *flags & F_CTMARK);
param_act(P_NO_INVERT, "LOGMARK", "--log-ctmark", invert);
info->flags |= XT_LOGMARK_CTMARK;
*flags |= F_CTMARK;
return true;
case 's': /* --log-secmark */
param_act(P_ONLY_ONCE, "LOGMARK", "--log-secmark", *flags & F_SECMARK);
param_act(P_NO_INVERT, "LOGMARK", "--log-secmark", invert);
info->flags |= XT_LOGMARK_SECMARK;
*flags |= F_SECMARK;
return true;
}
return false;
}
@@ -103,14 +73,7 @@ logmark_tg_print(const void *ip, const struct xt_entry_target *target,
{
const struct xt_logmark_tginfo *info = (void *)target->data;
printf("LOGMARK level %u prefix \"%s\"", info->level, info->prefix);
if (info->flags & XT_LOGMARK_NFMARK)
printf(" nfmark");
if (info->flags & XT_LOGMARK_CTMARK)
printf(" ctmark");
if (info->flags & XT_LOGMARK_SECMARK)
printf(" secmark");
printf("; ");
printf("LOGMARK level %u prefix \"%s\" ", info->level, info->prefix);
}
static void
@@ -122,34 +85,13 @@ logmark_tg_save(const void *ip, const struct xt_entry_target *target)
printf("--log-level %u ", info->level);
if (*info->prefix != '\0')
printf("--log-prefix \"%s\" ", info->prefix);
if (info->flags & XT_LOGMARK_NFMARK)
printf("--log-nfmark ");
if (info->flags & XT_LOGMARK_CTMARK)
printf("--log-ctmark ");
if (info->flags & XT_LOGMARK_SECMARK)
printf("--log-secmark ");
}
static struct xtables_target logmark_tg_reg = {
.version = IPTABLES_VERSION,
.version = XTABLES_VERSION,
.name = "LOGMARK",
.revision = 0,
.family = AF_INET,
.size = XT_ALIGN(sizeof(struct xt_logmark_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_logmark_tginfo)),
.help = logmark_tg_help,
.init = logmark_tg_init,
.parse = logmark_tg_parse,
.print = logmark_tg_print,
.save = logmark_tg_save,
.extra_opts = logmark_tg_opts,
};
static struct xtables_target logmark_tg6_reg = {
.version = IPTABLES_VERSION,
.name = "LOGMARK",
.revision = 0,
.family = AF_INET6,
.family = AF_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_logmark_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_logmark_tginfo)),
.help = logmark_tg_help,
@@ -164,5 +106,4 @@ void _init(void);
void _init(void)
{
xtables_register_target(&logmark_tg_reg);
xtables_register_target(&logmark_tg6_reg);
}

View File

@@ -18,7 +18,7 @@ static void tarpit_tg_check(unsigned int flags)
}
static struct xtables_target tarpit_tg_reg = {
.version = IPTABLES_VERSION,
.version = XTABLES_VERSION,
.name = "TARPIT",
.family = AF_INET,
.size = XT_ALIGN(0),

View File

@@ -94,7 +94,7 @@ static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
static struct xtables_target tee_tg_reg = {
.name = "TEE",
.version = IPTABLES_VERSION,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.help = tee_tg_help,

278
extensions/libxt_geoip.c Normal file
View File

@@ -0,0 +1,278 @@
/* Shared library add-on to iptables to add geoip match support.
*
* 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.
*
* Copyright (c) 2004, 2005, 2006, 2007, 2008
* Samuel Jean & Nicolas Bouliane
*
* For comments, bugs or suggestions, please contact
* Samuel Jean <peejix@people.netfilter.org>
* Nicolas Bouliane <peejix@people.netfilter.org>
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <xtables.h>
#include "xt_geoip.h"
#define GEOIP_DB_DIR "/var/geoip"
static void geoip_help(void)
{
printf (
"geoip match options:\n"
"[!] --src-cc, --source-country country[,country...]\n"
" Match packet coming from (one of) the specified country(ies)\n"
"[!] --dst-cc, --destination-country country[,country...]\n"
" Match packet going to (one of) the specified country(ies)\n"
"\n"
"NOTE: The country is inputed by its ISO3166 code.\n"
"\n"
);
}
static struct option geoip_opts[] = {
{.name = "dst-cc", .has_arg = true, .val = '2'},
{.name = "destination-country", .has_arg = true, .val = '2'},
{.name = "src-cc", .has_arg = true, .val = '1'},
{.name = "source-country", .has_arg = true, .val = '1'},
{NULL},
};
static struct geoip_subnet *geoip_get_subnets(const char *code, uint32_t *count)
{
struct geoip_subnet *subnets;
struct stat sb;
char buf[256];
int fd;
/* Use simple integer vector files */
#if __BYTE_ORDER == _BIG_ENDIAN
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv0", code);
#else
snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv0", code);
#endif
if ((fd = open(buf, O_RDONLY)) < 0) {
fprintf(stderr, "Could not open %s: %s\n", buf, strerror(errno));
exit_error(OTHER_PROBLEM, "Could not read geoip database");
}
fstat(fd, &sb);
if (sb.st_size % sizeof(struct geoip_subnet) != 0)
exit_error(OTHER_PROBLEM, "Database file %s seems to be "
"corrupted", buf);
subnets = malloc(sb.st_size);
if (subnets == NULL)
exit_error(OTHER_PROBLEM, "geoip: insufficient memory");
read(fd, subnets, sb.st_size);
close(fd);
*count = sb.st_size / sizeof(struct geoip_subnet);
return subnets;
}
static struct geoip_country_user *geoip_load_cc(const char *code,
unsigned short cc)
{
struct geoip_country_user *ginfo;
ginfo = malloc(sizeof(struct geoip_country_user));
if (!ginfo)
return NULL;
ginfo->subnets = (unsigned long)geoip_get_subnets(code, &ginfo->count);
ginfo->cc = cc;
return ginfo;
}
static u_int16_t
check_geoip_cc(char *cc, u_int16_t cc_used[], u_int8_t count)
{
u_int8_t i;
u_int16_t cc_int16;
if (strlen(cc) != 2) /* Country must be 2 chars long according
to the ISO3166 standard */
exit_error(PARAMETER_PROBLEM,
"geoip: invalid country code '%s'", cc);
// Verification will fail if chars aren't uppercased.
// Make sure they are..
for (i = 0; i < 2; i++)
if (isalnum(cc[i]) != 0)
cc[i] = toupper(cc[i]);
else
exit_error(PARAMETER_PROBLEM,
"geoip: invalid country code '%s'", cc);
/* Convert chars into a single 16 bit integer.
* FIXME: This assumes that a country code is
* exactly 2 chars long. If this is
* going to change someday, this whole
* match will need to be rewritten, anyway.
* - SJ */
cc_int16 = (cc[0] << 8) | cc[1];
// Check for presence of value in cc_used
for (i = 0; i < count; i++)
if (cc_int16 == cc_used[i])
return 0; // Present, skip it!
return cc_int16;
}
static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
union geoip_country_group *mem)
{
char *buffer, *cp, *next;
u_int8_t i, count = 0;
u_int16_t cctmp;
buffer = strdup(ccstr);
if (!buffer)
exit_error(OTHER_PROBLEM,
"geoip: insufficient memory available");
for (cp = buffer, i = 0; cp && i < XT_GEOIP_MAX; cp = next, i++)
{
next = strchr(cp, ',');
if (next) *next++ = '\0';
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
if ((mem[count++].user = (unsigned long)geoip_load_cc(cp, cctmp)) == 0)
exit_error(OTHER_PROBLEM,
"geoip: insufficient memory available");
cc[count-1] = cctmp;
}
}
if (cp)
exit_error(PARAMETER_PROBLEM,
"geoip: too many countries specified");
free(buffer);
if (count == 0)
exit_error(PARAMETER_PROBLEM,
"geoip: don't know what happened");
return count;
}
static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct xt_geoip_match_info *info = (void *)(*match)->data;
switch(c) {
case '1':
// Ensure that XT_GEOIP_SRC *OR* XT_GEOIP_DST haven't been used yet.
if (*flags & (XT_GEOIP_SRC | XT_GEOIP_DST))
exit_error(PARAMETER_PROBLEM,
"geoip: only use --source-country *OR* --destination-country once!");
*flags |= XT_GEOIP_SRC;
break;
case '2':
// Ensure that XT_GEOIP_SRC *OR* XT_GEOIP_DST haven't been used yet.
if (*flags & (XT_GEOIP_SRC | XT_GEOIP_DST))
exit_error(PARAMETER_PROBLEM,
"geoip: only use --source-country *OR* --destination-country once!");
*flags |= XT_GEOIP_DST;
break;
default:
return 0;
}
if (invert)
*flags |= XT_GEOIP_INV;
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
info->flags = *flags;
return 1;
}
static void
geoip_final_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM,
"geoip: missing arguments");
}
static void
geoip_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_geoip_match_info *info = (void*)match->data;
u_int8_t i;
if (info->flags & XT_GEOIP_SRC)
printf("Source ");
else
printf("Destination ");
if (info->count > 1)
printf("countries: ");
else
printf("country: ");
if (info->flags & XT_GEOIP_INV)
printf("! ");
for (i = 0; i < info->count; i++)
printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
printf(" ");
}
static void
geoip_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_geoip_match_info *info = (void *)match->data;
u_int8_t i;
if (info->flags & XT_GEOIP_INV)
printf("! ");
if (info->flags & XT_GEOIP_SRC)
printf("--source-country ");
else
printf("--destination-country ");
for (i = 0; i < info->count; i++)
printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
printf(" ");
}
static struct xtables_match geoip_match = {
.family = AF_INET,
.name = "geoip",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_geoip_match_info)),
.userspacesize = XT_ALIGN(offsetof(struct xt_geoip_match_info, mem)),
.help = geoip_help,
.parse = geoip_parse,
.final_check = geoip_final_check,
.print = geoip_print,
.save = geoip_save,
.extra_opts = geoip_opts,
};
static void _init(void)
{
xtables_register_match(&geoip_match);
}

View File

@@ -0,0 +1,16 @@
Match a packet by its source or destination country.
.TP
[\fB!\fP] \fB--src-cc\fP, \fB--source-country\fP \fIcountry\fP[\fB,\fP\fIcountry\fP\fB...\fP]
Match packet coming from (one of) the specified country(ies)
.TP
[\fB!\fP] \fB--dst-cc\fP, \fB--destination-country\fP \fIcountry\fP[\fB,\fP\fIcountry\fP\fB...\fP]
Match packet going to (one of) the specified country(ies)
.TP
NOTE:
The country is inputed by its ISO3166 code.
.P
The extra files you will need is the binary database files. They are generated
from a country-subnet database with the geoip_csv_iv0.pl tool, available at
http://jengelh.hopto.org/files/geoip/ . The files MUST be moved to /var/geoip/
as the shared library is statically looking for this pathname (e.g.
/var/geoip/LE/de.iv0).

121
extensions/libxt_portscan.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* portscan target for Xtables
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License; either version
* 2 or 3 as published by the Free Software Foundation.
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include "xt_portscan.h"
static const struct option portscan_mt_opts[] = {
{.name = "stealth", .has_arg = false, .val = 'x'},
{.name = "synscan", .has_arg = false, .val = 's'},
{.name = "cnscan", .has_arg = false, .val = 'c'},
{.name = "grscan", .has_arg = false, .val = 'g'},
{},
};
static void portscan_mt_help(void)
{
printf(
"portscan match options:\n"
"(Combining them will make them match by OR-logic)\n"
" --stealth Match TCP Stealth packets\n"
" --synscan Match TCP SYN scans\n"
" --cnscan Match TCP Connect scans\n"
" --grscan Match Banner Grabbing scans\n");
}
static int portscan_mt_parse(int c, char **argv, int invert,
unsigned int *flags, const void *entry, struct xt_entry_match **match)
{
struct xt_portscan_mtinfo *info = (void *)((*match)->data);
switch (c) {
case 'c':
info->match_cn = true;
return true;
case 'g':
info->match_gr = true;
return true;
case 's':
info->match_syn = true;
return true;
case 'x':
info->match_stealth = true;
return true;
}
return false;
}
static void portscan_mt_check(unsigned int flags)
{
}
static void portscan_mt_print(const void *ip,
const struct xt_entry_match *match, int numeric)
{
const struct xt_portscan_mtinfo *info = (const void *)(match->data);
const char *s = "";
printf("portscan ");
if (info->match_stealth) {
printf("STEALTH");
s = ",";
}
if (info->match_syn) {
printf("%sSYNSCAN", s);
s = ",";
}
if (info->match_cn) {
printf("%sCNSCAN", s);
s = ",";
}
if (info->match_gr)
printf("%sGRSCAN", s);
printf(" ");
}
static void portscan_mt_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_portscan_mtinfo *info = (const void *)(match->data);
if (info->match_stealth)
printf("--stealth ");
if (info->match_syn)
printf("--synscan ");
if (info->match_cn)
printf("--cnscan ");
if (info->match_gr)
printf("--grscan ");
}
static struct xtables_match portscan_mt_reg = {
.version = XTABLES_VERSION,
.name = "portscan",
.revision = 0,
.family = AF_INET,
.size = XT_ALIGN(sizeof(struct xt_portscan_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_portscan_mtinfo)),
.help = portscan_mt_help,
.parse = portscan_mt_parse,
.final_check = portscan_mt_check,
.print = portscan_mt_print,
.save = portscan_mt_save,
.extra_opts = portscan_mt_opts,
};
void _init(void);
void _init(void)
{
xtables_register_match(&portscan_mt_reg);
}

View File

@@ -0,0 +1,27 @@
Detects simple port scan attemps based upon the packet's contents. (This is
different from other implementations, which also try to match the rate of new
connections.) Note that an attempt is only discovered after it has been carried
out, but this information can be used in conjunction with other rules to block
the remote host's future connections. So this match module will match on the
(probably) last packet the remote side will send to your machine.
.TP
\fB--stealth\fR
Match if the packet did not belong to any known TCP connection
(Stealth/FIN/XMAS/NULL scan).
.TP
\fB--synscan\fR
Match if the connection was a TCP half-open discovery (SYN scan), i.e. the
connection was torn down after the 2nd packet in the 3-way handshake.
.TP
\fB--cnscan\fR
Match if the connection was a TCP full open discovery (connect scan), i.e. the
connection was torn down after completion of the 3-way handshake.
.TP
\fB--grscan\fR
Match if data in the connection only flew in the direction of the remote side,
e.g. if the connection was terminated after a locally running daemon sent its
identification. (e.g. openssh)
.PP
NOTE: Some clients (Windows XP for example) may do what looks like a SYN scan,
so be advised to carefully use xt_portscan in conjunction with blocking rules,
as it may lock out your very own internal network.

210
extensions/xt_CHAOS.c Normal file
View File

@@ -0,0 +1,210 @@
/*
* CHAOS target for netfilter
* Copyright © CC Computer Consultants GmbH, 2006 - 2007
* Contact: Jan Engelhardt <jengelh@computergmbh.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License; either version
* 2 or 3 as published by the Free Software Foundation.
*/
#include <linux/icmp.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/stat.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_tcpudp.h>
#include <linux/netfilter_ipv4/ipt_REJECT.h>
#include <net/ip.h>
#include "xt_CHAOS.h"
static struct xt_match *xm_tcp;
static struct xt_target *xt_delude, *xt_reject, *xt_tarpit;
#include "compat_xtables.h"
#define PFX KBUILD_MODNAME ": "
/* Module parameters */
static unsigned int reject_percentage = ~0U * .01;
static unsigned int delude_percentage = ~0U * .0101;
module_param(reject_percentage, uint, S_IRUGO | S_IWUSR);
module_param(delude_percentage, uint, S_IRUGO | S_IWUSR);
/* References to other matches/targets */
static int have_delude, have_tarpit;
/* Static data for other matches/targets */
static const struct ipt_reject_info reject_params = {
.with = ICMP_HOST_UNREACH,
};
static const struct xt_tcp tcp_params = {
.spts = {0, ~0},
.dpts = {0, ~0},
};
/* CHAOS functions */
static void xt_chaos_total(const struct xt_chaos_tginfo *info,
struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, unsigned int hooknum)
{
const struct iphdr *iph = ip_hdr(skb);
const int protoff = 4 * iph->ihl;
const int offset = ntohs(iph->frag_off) & IP_OFFSET;
typeof(xt_tarpit) destiny;
bool ret;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
int hotdrop = false;
#else
bool hotdrop = false;
#endif
ret = xm_tcp->match(skb, in, out, xm_tcp, &tcp_params,
offset, protoff, &hotdrop);
if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
return;
destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
destiny->target(&skb, in, out, hooknum, destiny, NULL, NULL);
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
destiny->target(&skb, in, out, hooknum, destiny, NULL);
#else
destiny->target(skb, in, out, hooknum, destiny, NULL);
#endif
return;
}
static unsigned int chaos_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)
{
/*
* Equivalent to:
* -A chaos -m statistic --mode random --probability \
* $reject_percentage -j REJECT --reject-with host-unreach;
* -A chaos -p tcp -m statistic --mode random --probability \
* $delude_percentage -j DELUDE;
* -A chaos -j DROP;
*/
const struct xt_chaos_tginfo *info = targinfo;
const struct iphdr *iph = ip_hdr(skb);
if ((unsigned int)net_random() <= reject_percentage)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
return xt_reject->target(&skb, in, out, hooknum,
target->__compat_target, &reject_params, NULL);
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
return xt_reject->target(&skb, in, out, hooknum,
target->__compat_target, &reject_params);
#else
return xt_reject->target(skb, in, out, hooknum, target,
&reject_params);
#endif
/* TARPIT/DELUDE may not be called from the OUTPUT chain */
if (iph->protocol == IPPROTO_TCP &&
info->variant != XTCHAOS_NORMAL && hooknum != NF_INET_LOCAL_OUT)
xt_chaos_total(info, skb, in, out, hooknum);
return NF_DROP;
}
static bool chaos_tg_check(const char *tablename, const void *entry,
const struct xt_target *target, void *targinfo, unsigned int hook_mask)
{
const struct xt_chaos_tginfo *info = targinfo;
if (info->variant == XTCHAOS_DELUDE && !have_delude) {
printk(KERN_WARNING PFX "Error: Cannot use --delude when "
"DELUDE module not available\n");
return false;
}
if (info->variant == XTCHAOS_TARPIT && !have_tarpit) {
printk(KERN_WARNING PFX "Error: Cannot use --tarpit when "
"TARPIT module not available\n");
return false;
}
return true;
}
static struct xt_target chaos_tg_reg = {
.name = "CHAOS",
.family = AF_INET,
.table = "filter",
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
(1 << NF_INET_LOCAL_OUT),
.target = chaos_tg,
.checkentry = chaos_tg_check,
.targetsize = sizeof(struct xt_chaos_tginfo),
.me = THIS_MODULE,
};
static int __init chaos_tg_init(void)
{
int ret = -EINVAL;
xm_tcp = xt_request_find_match(AF_INET, "tcp", 0);
if (xm_tcp == NULL) {
printk(KERN_WARNING PFX "Error: Could not find or load "
"\"tcp\" match\n");
return -EINVAL;
}
xt_reject = xt_request_find_target(AF_INET, "REJECT", 0);
if (xt_reject == NULL) {
printk(KERN_WARNING PFX "Error: Could not find or load "
"\"REJECT\" target\n");
goto out2;
}
xt_tarpit = xt_request_find_target(AF_INET, "TARPIT", 0);
have_tarpit = xt_tarpit != NULL;
if (!have_tarpit)
printk(KERN_WARNING PFX "Warning: Could not find or load "
"\"TARPIT\" target\n");
xt_delude = xt_request_find_target(AF_INET, "DELUDE", 0);
have_delude = xt_delude != NULL;
if (!have_delude)
printk(KERN_WARNING PFX "Warning: Could not find or load "
"\"DELUDE\" target\n");
if ((ret = xt_register_target(&chaos_tg_reg)) != 0) {
printk(KERN_WARNING PFX "xt_register_target returned "
"error %d\n", ret);
goto out3;
}
return 0;
out3:
if (have_delude)
module_put(xt_delude->me);
if (have_tarpit)
module_put(xt_tarpit->me);
module_put(xt_reject->me);
out2:
module_put(xm_tcp->me);
return ret;
}
static void __exit chaos_tg_exit(void)
{
xt_unregister_target(&chaos_tg_reg);
module_put(xm_tcp->me);
module_put(xt_reject->me);
if (have_delude)
module_put(xt_delude->me);
if (have_tarpit)
module_put(xt_tarpit->me);
return;
}
module_init(chaos_tg_init);
module_exit(chaos_tg_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("Xtables: Network scan slowdown with non-deterministic results");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_CHAOS");

14
extensions/xt_CHAOS.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _LINUX_NETFILTER_XT_CHAOS_H
#define _LINUX_NETFILTER_XT_CHAOS_H 1
enum xt_chaos_target_variant {
XTCHAOS_NORMAL,
XTCHAOS_TARPIT,
XTCHAOS_DELUDE,
};
struct xt_chaos_tginfo {
uint8_t variant;
};
#endif /* _LINUX_NETFILTER_XT_CHAOS_H */

181
extensions/xt_DELUDE.c Normal file
View File

@@ -0,0 +1,181 @@
/*
* DELUDE target
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
*
* Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
*
* xt_DELUDE acts like REJECT, but does reply with SYN-ACK on SYN.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter/x_tables.h>
#ifdef CONFIG_BRIDGE_NETFILTER
# include <linux/netfilter_bridge.h>
#endif
#include <net/tcp.h>
#include "compat_xtables.h"
#define PFX KBUILD_MODNAME ": "
static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
{
struct tcphdr _otcph, *tcph;
const struct tcphdr *oth;
const struct iphdr *oiph;
unsigned int addr_type;
struct sk_buff *nskb;
struct iphdr *niph;
oiph = ip_hdr(oldskb);
/* IP header checks: fragment. */
if (oiph->frag_off & htons(IP_OFFSET))
return;
oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
sizeof(_otcph), &_otcph);
if (oth == NULL)
return;
/* No RST for RST. */
if (oth->rst)
return;
/* Check checksum */
if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
return;
nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
LL_MAX_HEADER, GFP_ATOMIC);
if (nskb == NULL)
return;
skb_reserve(nskb, LL_MAX_HEADER);
skb_reset_network_header(nskb);
niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
niph->version = 4;
niph->ihl = sizeof(struct iphdr) / 4;
niph->tos = 0;
niph->id = 0;
niph->frag_off = htons(IP_DF);
niph->protocol = IPPROTO_TCP;
niph->check = 0;
niph->saddr = oiph->daddr;
niph->daddr = oiph->saddr;
tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
memset(tcph, 0, sizeof(*tcph));
tcph->source = oth->dest;
tcph->dest = oth->source;
tcph->doff = sizeof(struct tcphdr) / 4;
/* DELUDE essential part */
if (oth->syn && !oth->ack && !oth->rst && !oth->fin) {
tcph->syn = true;
tcph->seq = 0;
tcph->ack = true;
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
oldskb->len - ip_hdrlen(oldskb) -
(oth->doff << 2));
} else {
tcph->rst = true;
if (!oth->ack) {
tcph->seq = 0;
tcph->ack = true;
tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn +
oth->fin + oldskb->len -
ip_hdrlen(oldskb) - (oth->doff << 2));
} else {
tcph->seq = oth->ack_seq;
tcph->ack = false;
tcph->ack_seq = 0;
}
}
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), niph->saddr,
niph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#else
tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
niph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#endif
addr_type = RTN_UNSPEC;
#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;
/* ip_route_me_harder expects skb->dst to be set */
dst_hold(oldskb->dst);
nskb->dst = oldskb->dst;
if (ip_route_me_harder(nskb, addr_type))
goto free_nskb;
niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
nskb->ip_summed = CHECKSUM_NONE;
/* "Never happens" */
if (nskb->len > dst_mtu(nskb->dst))
goto free_nskb;
nf_ct_attach(nskb, oldskb);
ip_local_out(nskb);
return;
free_nskb:
kfree_skb(nskb);
}
static unsigned int delude_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)
{
/* WARNING: This code causes reentry within iptables.
This means that the iptables jump stack is now crap. We
must return an absolute verdict. --RR */
delude_send_reset(skb, hooknum);
return NF_DROP;
}
static struct xt_target delude_tg_reg __read_mostly = {
.name = "DELUDE",
.revision = 0,
.family = AF_INET,
.table = "filter",
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
.proto = IPPROTO_TCP,
.target = delude_tg,
.me = THIS_MODULE,
};
static int __init delude_tg_init(void)
{
return xt_register_target(&delude_tg_reg);
}
static void __exit delude_tg_exit(void)
{
xt_unregister_target(&delude_tg_reg);
}
module_init(delude_tg_init);
module_exit(delude_tg_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("Xtables: Close TCP connections after handshake");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_DELUDE");

130
extensions/xt_ECHO.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* ECHO target (RFC 862)
* Copyright © CC Computer Consultants GmbH, 2008
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 or 3 as published by the Free Software Foundation.
*/
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/netfilter/x_tables.h>
#ifdef CONFIG_BRIDGE_NETFILTER
# include <linux/netfilter_bridge.h>
#endif
#include <net/ip.h>
#include "compat_xtables.h"
static unsigned int echo_tg4(struct sk_buff *oldskb,
const struct net_device *in, const struct net_device *out,
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
{
const struct udphdr *oldudp;
const struct iphdr *oldip;
struct udphdr *newudp, oldudp_buf;
struct iphdr *newip;
struct sk_buff *newskb;
unsigned int addr_type, data_len;
void *payload;
/* This allows us to do the copy operation in fewer lines of code. */
skb_linearize(oldskb);
oldip = ip_hdr(oldskb);
oldudp = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
sizeof(struct udphdr), &oldudp_buf);
if (oldudp == NULL)
return NF_DROP;
if (ntohs(oldudp->len) <= sizeof(struct udphdr))
return NF_DROP;
newskb = alloc_skb(LL_MAX_HEADER + sizeof(struct iphdr) +
ntohs(oldudp->len), GFP_ATOMIC);
if (newskb == NULL)
return NF_DROP;
skb_reserve(newskb, LL_MAX_HEADER);
skb_reset_network_header(newskb);
newip = (void *)skb_put(newskb, sizeof(struct iphdr));
newip->version = 4;
newip->ihl = sizeof(struct iphdr) / 4;
newip->tos = oldip->tos;
newip->id = 0;
newip->frag_off = htons(IP_DF);
newip->protocol = oldip->protocol;
newip->check = 0;
newip->saddr = oldip->daddr;
newip->daddr = oldip->saddr;
newudp = (void *)skb_put(newskb, sizeof(struct udphdr));
newudp->source = oldudp->dest;
newudp->dest = oldudp->source;
newudp->len = oldudp->len;
newudp->check = 0;
data_len = htons(oldudp->len) - sizeof(*oldudp);
payload = skb_header_pointer(oldskb, ip_hdrlen(oldskb) +
sizeof(*oldudp), data_len, NULL);
memcpy(skb_put(newskb, data_len), payload, data_len);
addr_type = RTN_UNSPEC;
#ifdef CONFIG_BRIDGE_NETFILTER
if (hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL &&
newskb->nf_bridge->mask & BRNF_BRIDGED))
#else
if (hooknum != NF_INET_FORWARD)
#endif
addr_type = RTN_LOCAL;
/* ip_route_me_harder expects skb->dst to be set */
dst_hold(oldskb->dst);
newskb->dst = oldskb->dst;
if (ip_route_me_harder(newskb, addr_type) < 0)
goto free_nskb;
newip->ttl = dst_metric(newskb->dst, RTAX_HOPLIMIT);
newskb->ip_summed = CHECKSUM_NONE;
/* "Never happens" (?) */
if (newskb->len > dst_mtu(newskb->dst))
goto free_nskb;
nf_ct_attach(newskb, oldskb);
ip_local_out(newskb);
return NF_DROP;
free_nskb:
kfree_skb(newskb);
return NF_DROP;
}
static struct xt_target echo_tg_reg __read_mostly = {
.name = "ECHO",
.revision = 0,
.family = AF_INET,
.proto = IPPROTO_UDP,
.table = "filter",
.target = echo_tg4,
.targetsize = XT_ALIGN(0),
.me = THIS_MODULE,
};
static int __init echo_tg_init(void)
{
return xt_register_target(&echo_tg_reg);
}
static void __exit echo_tg_exit(void)
{
return xt_unregister_target(&echo_tg_reg);
}
module_init(echo_tg_init);
module_exit(echo_tg_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("Xtables: ECHO diagnosis target");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_ECHO");

View File

@@ -11,8 +11,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/x_tables.h>
#include <net/netfilter/nf_conntrack.h>
//#include <net/netfilter/nf_conntrack.h>
#include "compat_xtables.h"
#include "xt_LOGMARK.h"
@@ -22,25 +23,44 @@ logmark_tg(struct sk_buff *skb, const struct net_device *in,
const struct xt_target *target, const void *targinfo)
{
const struct xt_logmark_tginfo *info = targinfo;
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
printk("<%u>%.*s", info->level, sizeof(info->prefix), info->prefix);
printk("<%u>%.*s""nfmark=0x%x secmark=0x%x classify=0x%x",
info->level, (unsigned int)sizeof(info->prefix), info->prefix,
skb_nfmark(skb), skb->secmark, skb->priority);
if (info->flags & XT_LOGMARK_NFMARK)
printk(" nfmark=0x%x", skb->mark);
if (info->flags & XT_LOGMARK_CTMARK) {
const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(skb, &ctinfo);
if (ct == NULL) {
printk(" ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE");
} else if (ct == &nf_conntrack_untracked) {
printk(" ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE");
} else {
printk(" ct=0x%p ctmark=0x%x ctstate=", ct, ct->mark);
ctinfo %= IP_CT_IS_REPLY;
if (ctinfo == IP_CT_NEW)
printk("NEW");
else if (ctinfo == IP_CT_ESTABLISHED)
printk("ESTABLISHED");
else if (ctinfo == IP_CT_RELATED)
printk("RELATED");
if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
printk(",SNAT");
if (test_bit(IPS_DST_NAT_BIT, &ct->status))
printk(",DNAT");
ct = nf_ct_get(skb, &ctinfo);
if (ct == NULL)
printk(" ctmark=X");
else
printk(" ctmark=0x%x", ct->mark);
printk(" ctstatus=");
if (ct->status & IPS_EXPECTED)
printk("EXPECTED");
if (ct->status & IPS_SEEN_REPLY)
printk(",SEEN_REPLY");
if (ct->status & IPS_ASSURED)
printk(",ASSURED");
if (ct->status & IPS_CONFIRMED)
printk(",CONFIRMED");
}
if (info->flags & XT_LOGMARK_SECMARK)
printk(" secmark=0x%x", skb->secmark);
printk("\n");
printk("\n");
return XT_CONTINUE;
}

View File

@@ -1,16 +1,9 @@
#ifndef _LINUX_NETFILTER_XT_LOGMARK_TARGET_H
#define _LINUX_NETFILTER_XT_LOGMARK_TARGET_H 1
enum {
XT_LOGMARK_NFMARK = 1 << 0,
XT_LOGMARK_CTMARK = 1 << 1,
XT_LOGMARK_SECMARK = 1 << 2,
};
struct xt_logmark_tginfo {
char prefix[14];
u_int8_t level;
u_int8_t flags;
};
#endif /* _LINUX_NETFILTER_XT_LOGMARK_TARGET_H */

View File

@@ -90,7 +90,7 @@ static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
/* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb);
nskb->mark = 0;
skb_nfmark(nskb) = 0;
skb_init_secmark(nskb);
skb_shinfo(nskb)->gso_size = 0;
@@ -132,9 +132,15 @@ static inline void tarpit_tcp(struct sk_buff *oldskb, unsigned int hook)
/* Adjust TCP checksum */
tcph->check = 0;
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 20)
tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), niph->saddr,
niph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#else
tcph->check = tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
niph->daddr, csum_partial((char *)tcph,
sizeof(struct tcphdr), 0));
#endif
/* Set DF, id = 0 */
niph->frag_off = htons(IP_DF);

View File

@@ -62,7 +62,7 @@ static bool tee_routing(struct sk_buff *skb,
};
/* Trying to route the packet using the standard routing table. */
err = ip_route_output_key(&rt, &fl);
err = ip_route_output_key(&init_net, &rt, &fl);
if (err != 0) {
if (net_ratelimit())
pr_debug(KBUILD_MODNAME

246
extensions/xt_geoip.c Normal file
View File

@@ -0,0 +1,246 @@
/* iptables kernel module for the geoip match
*
* 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.
*
* Copyright (c) 2004, 2005, 2006, 2007, 2008
* Samuel Jean & Nicolas Bouliane
*/
#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/skbuff.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/netfilter/x_tables.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include "xt_geoip.h"
#include "compat_xtables.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Bouliane");
MODULE_AUTHOR("Samuel Jean");
MODULE_DESCRIPTION("xtables module for geoip match");
MODULE_ALIAS("ipt_geoip");
struct geoip_country_kernel {
struct list_head list;
struct geoip_subnet *subnets;
atomic_t ref;
unsigned int count;
unsigned short cc;
};
static LIST_HEAD(geoip_head);
static DEFINE_SPINLOCK(geoip_lock);
static struct geoip_country_kernel *
geoip_add_node(const struct geoip_country_user __user *umem_ptr)
{
struct geoip_country_user umem;
struct geoip_country_kernel *p;
struct geoip_subnet *s;
if (copy_from_user(&umem, umem_ptr, sizeof(umem)) != 0)
return NULL;
p = kmalloc(sizeof(struct geoip_country_kernel), GFP_KERNEL);
if (p == NULL)
return NULL;
p->count = umem.count;
p->cc = umem.cc;
s = vmalloc(p->count * sizeof(struct geoip_subnet));
if (s == NULL)
goto free_p;
if (copy_from_user(s, (const void __user *)(unsigned long)umem.subnets,
p->count * sizeof(struct geoip_subnet)) != 0)
goto free_s;
p->subnets = s;
atomic_set(&p->ref, 1);
INIT_LIST_HEAD(&p->list);
spin_lock(&geoip_lock);
list_add_tail_rcu(&p->list, &geoip_head);
spin_unlock(&geoip_lock);
return p;
free_s:
vfree(s);
free_p:
kfree(p);
return NULL;
}
static void geoip_try_remove_node(struct geoip_country_kernel *p)
{
spin_lock(&geoip_lock);
if (!atomic_dec_and_test(&p->ref)) {
spin_unlock(&geoip_lock);
return;
}
/* So now am unlinked or the only one alive, right ?
* What are you waiting ? Free up some memory!
*/
list_del_rcu(&p->list);
spin_unlock(&geoip_lock);
synchronize_rcu();
vfree(p->subnets);
kfree(p);
}
static struct geoip_country_kernel *find_node(unsigned short cc)
{
struct geoip_country_kernel *p;
spin_lock(&geoip_lock);
list_for_each_entry_rcu(p, &geoip_head, list)
if (p->cc == cc) {
atomic_inc(&p->ref);
spin_unlock(&geoip_lock);
return p;
}
spin_unlock(&geoip_lock);
return NULL;
}
static bool geoip_bsearch(const struct geoip_subnet *range,
uint32_t addr, int lo, int hi)
{
int mid;
if (hi < lo)
return false;
mid = (lo + hi) / 2;
if (range[mid].begin <= addr && addr <= range[mid].end)
return true;
if (range[mid].begin > addr)
return geoip_bsearch(range, addr, lo, mid - 1);
else if (range[mid].end < addr)
return geoip_bsearch(range, addr, mid + 1, hi);
WARN_ON(true);
return false;
}
static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const struct xt_match *match,
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
{
const struct xt_geoip_match_info *info = matchinfo;
const struct geoip_country_kernel *node;
const struct iphdr *iph = ip_hdr(skb);
unsigned int i;
uint32_t ip;
if (info->flags & XT_GEOIP_SRC)
ip = ntohl(iph->saddr);
else
ip = ntohl(iph->daddr);
rcu_read_lock();
for (i = 0; i < info->count; i++) {
if ((node = info->mem[i].kernel) == NULL) {
printk(KERN_ERR "xt_geoip: what the hell ?? '%c%c' isn't loaded into memory... skip it!\n",
COUNTRY(info->cc[i]));
continue;
}
if (geoip_bsearch(node->subnets, ip, 0, node->count)) {
rcu_read_unlock();
return !(info->flags & XT_GEOIP_INV);
}
}
rcu_read_unlock();
return info->flags & XT_GEOIP_INV;
}
static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
{
struct xt_geoip_match_info *info = matchinfo;
struct geoip_country_kernel *node;
unsigned int i;
for (i = 0; i < info->count; i++) {
node = find_node(info->cc[i]);
if (node == NULL)
if ((node = geoip_add_node((const void __user *)(unsigned long)info->mem[i].user)) == NULL) {
printk(KERN_ERR
"xt_geoip: unable to load '%c%c' into memory\n",
COUNTRY(info->cc[i]));
return false;
}
/* Overwrite the now-useless pointer info->mem[i] with
* a pointer to the node's kernelspace structure.
* This avoids searching for a node in the match() and
* destroy() functions.
*/
info->mem[i].kernel = node;
}
return true;
}
static void xt_geoip_mt_destroy(const struct xt_match *match, void *matchinfo)
{
struct xt_geoip_match_info *info = matchinfo;
struct geoip_country_kernel *node;
unsigned int i;
/* This entry has been removed from the table so
* decrease the refcount of all countries it is
* using.
*/
for (i = 0; i < info->count; i++)
if ((node = info->mem[i].kernel) != NULL) {
/* Free up some memory if that node isn't used
* anymore. */
geoip_try_remove_node(node);
}
else
/* Something strange happened. There's no memory allocated for this
* country. Please send this bug to the mailing list. */
printk(KERN_ERR
"xt_geoip: What happened peejix ? What happened acidfu ?\n"
"xt_geoip: please report this bug to the maintainers\n");
}
static struct xt_match xt_geoip_match __read_mostly = {
.family = AF_INET,
.name = "geoip",
.match = xt_geoip_mt,
.checkentry = xt_geoip_mt_checkentry,
.destroy = xt_geoip_mt_destroy,
.matchsize = sizeof(struct xt_geoip_match_info),
.me = THIS_MODULE,
};
static int __init xt_geoip_mt_init(void)
{
return xt_register_match(&xt_geoip_match);
}
static void __exit xt_geoip_mt_fini(void)
{
xt_unregister_match(&xt_geoip_match);
}
module_init(xt_geoip_mt_init);
module_exit(xt_geoip_mt_fini);

54
extensions/xt_geoip.h Normal file
View File

@@ -0,0 +1,54 @@
/* ipt_geoip.h header file for libipt_geoip.c and ipt_geoip.c
*
* 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.
*
* Copyright (c) 2004, 2005, 2006, 2007, 2008
*
* Samuel Jean
* Nicolas Bouliane
*/
#ifndef _LINUX_NETFILTER_XT_GEOIP_H
#define _LINUX_NETFILTER_XT_GEOIP_H 1
enum {
XT_GEOIP_SRC = 1 << 0, /* Perform check on Source IP */
XT_GEOIP_DST = 1 << 1, /* Perform check on Destination IP */
XT_GEOIP_INV = 1 << 2, /* Negate the condition */
XT_GEOIP_MAX = 15, /* Maximum of countries */
};
/* Yup, an address range will be passed in with host-order */
struct geoip_subnet {
__u32 begin;
__u32 end;
};
struct geoip_country_user {
aligned_u64 subnets;
__u32 count;
__u16 cc;
};
struct geoip_country_kernel;
union geoip_country_group {
aligned_u64 user;
struct geoip_country_kernel *kernel;
};
struct xt_geoip_match_info {
__u8 flags;
__u8 count;
__u16 cc[XT_GEOIP_MAX];
/* Used internally by the kernel */
union geoip_country_group mem[XT_GEOIP_MAX];
};
#define COUNTRY(cc) (cc >> 8), (cc & 0x00FF)
#endif /* _LINUX_NETFILTER_XT_GEOIP_H */

262
extensions/xt_portscan.c Normal file
View File

@@ -0,0 +1,262 @@
/*
* portscan match for netfilter
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License; either version
* 2 or 3 as published by the Free Software Foundation.
*/
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/stat.h>
#include <linux/tcp.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_tcpudp.h>
//#include <net/netfilter/nf_conntrack.h>
#include "xt_portscan.h"
#include "compat_xtables.h"
#define PFX KBUILD_MODNAME ": "
enum {
TCP_FLAGS_ALL3 = TCP_FLAG_FIN | TCP_FLAG_RST | TCP_FLAG_SYN,
TCP_FLAGS_ALL4 = TCP_FLAGS_ALL3 | TCP_FLAG_ACK,
TCP_FLAGS_ALL6 = TCP_FLAGS_ALL4 | TCP_FLAG_PSH | TCP_FLAG_URG,
};
/* Module parameters */
static unsigned int
connmark_mask = ~0,
packet_mask = ~0,
mark_seen = 0x9,
mark_synrcv = 0x1,
mark_closed = 0x2,
mark_synscan = 0x3,
mark_estab1 = 0x4,
mark_estab2 = 0x5,
mark_cnscan = 0x6,
mark_grscan = 0x7,
mark_valid = 0x8;
module_param(connmark_mask, uint, S_IRUGO | S_IWUSR);
module_param(packet_mask, uint, S_IRUGO | S_IWUSR);
module_param(mark_seen, uint, S_IRUGO | S_IWUSR);
module_param(mark_synrcv, uint, S_IRUGO | S_IWUSR);
module_param(mark_closed, uint, S_IRUGO | S_IWUSR);
module_param(mark_synscan, uint, S_IRUGO | S_IWUSR);
module_param(mark_estab1, uint, S_IRUGO | S_IWUSR);
module_param(mark_estab2, uint, S_IRUGO | S_IWUSR);
module_param(mark_cnscan, uint, S_IRUGO | S_IWUSR);
module_param(mark_grscan, uint, S_IRUGO | S_IWUSR);
module_param(mark_valid, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(connmark_mask, "only set specified bits in connection mark");
MODULE_PARM_DESC(packet_mask, "only set specified bits in packet mark");
MODULE_PARM_DESC(mark_seen, "nfmark value for packet-seen state");
MODULE_PARM_DESC(mark_synrcv, "connmark value for SYN Received state");
MODULE_PARM_DESC(mark_closed, "connmark value for closed state");
MODULE_PARM_DESC(mark_synscan, "connmark value for SYN Scan state");
MODULE_PARM_DESC(mark_estab1, "connmark value for Established-1 state");
MODULE_PARM_DESC(mark_estab2, "connmark value for Established-2 state");
MODULE_PARM_DESC(mark_cnscan, "connmark value for Connect Scan state");
MODULE_PARM_DESC(mark_grscan, "connmark value for Grab Scan state");
MODULE_PARM_DESC(mark_valid, "connmark value for Valid state");
/* TCP flag functions */
static inline bool tflg_ack4(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_ACK;
}
static inline bool tflg_ack6(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL6) == TCP_FLAG_ACK;
}
static inline bool tflg_fin(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_FIN;
}
static inline bool tflg_rst(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL3) == TCP_FLAG_RST;
}
static inline bool tflg_rstack(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
(TCP_FLAG_ACK | TCP_FLAG_RST);
}
static inline bool tflg_syn(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL4) == TCP_FLAG_SYN;
}
static inline bool tflg_synack(const struct tcphdr *th)
{
return (tcp_flag_word(th) & TCP_FLAGS_ALL4) ==
(TCP_FLAG_SYN | TCP_FLAG_ACK);
}
/* portscan functions */
static inline bool portscan_mt_stealth(const struct tcphdr *th)
{
/*
* "Connection refused" replies to our own probes must not be matched.
*/
if (tflg_rstack(th))
return false;
if (tflg_rst(th) && printk_ratelimit()) {
printk(KERN_WARNING PFX "Warning: Pure RST received\n");
return false;
}
/*
* -p tcp ! --syn -m conntrack --ctstate INVALID: Looking for non-start
* packets that are not associated with any connection -- this will
* match most scan types (NULL, XMAS, FIN) and ridiculous flag
* combinations (SYN-RST, SYN-FIN, SYN-FIN-RST, FIN-RST, etc.).
*/
return !tflg_syn(th);
}
static inline unsigned int portscan_mt_full(int mark,
enum ip_conntrack_info ctstate, bool loopback, const struct tcphdr *tcph,
unsigned int payload_len)
{
if (mark == mark_estab2) {
/*
* -m connmark --mark $ESTAB2
*/
if (tflg_ack4(tcph) && payload_len == 0)
return mark; /* keep mark */
else if (tflg_rst(tcph) || tflg_fin(tcph))
return mark_grscan;
else
return mark_valid;
} else if (mark == mark_estab1) {
/*
* -m connmark --mark $ESTAB1
*/
if (tflg_rst(tcph) || tflg_fin(tcph))
return mark_cnscan;
else if (!loopback && tflg_ack4(tcph) && payload_len == 0)
return mark_estab2;
else
return mark_valid;
} else if (mark == mark_synrcv) {
/*
* -m connmark --mark $SYN
*/
if (loopback && tflg_synack(tcph))
return mark; /* keep mark */
else if (loopback && tflg_rstack(tcph))
return mark_closed;
else if (tflg_ack6(tcph))
return mark_estab1;
else
return mark_synscan;
} else if (ctstate == IP_CT_NEW && tflg_syn(tcph)) {
/*
* -p tcp --syn --ctstate NEW
*/
return mark_synrcv;
}
return mark;
}
static bool portscan_mt(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
const struct xt_match *match, const void *matchinfo, int offset,
unsigned int protoff, bool *hotdrop)
{
const struct xt_portscan_mtinfo *info = matchinfo;
enum ip_conntrack_info ctstate;
const struct tcphdr *tcph;
struct nf_conn *ctdata;
struct tcphdr tcph_buf;
tcph = skb_header_pointer(skb, protoff, sizeof(tcph_buf), &tcph_buf);
if (tcph == NULL)
return false;
/* Check for invalid packets: -m conntrack --ctstate INVALID */
if ((ctdata = nf_ct_get(skb, &ctstate)) == NULL) {
if (info->match_stealth)
return portscan_mt_stealth(tcph);
/*
* If @ctdata is NULL, we cannot match the other scan
* types, return.
*/
return false;
}
/*
* If -m portscan was previously applied to this packet, the rules we
* simulate must not be run through again. And for speedup, do not call
* it either when the connection is already VALID.
*/
if ((ctdata->mark & connmark_mask) == mark_valid ||
(skb_nfmark(skb) & packet_mask) != mark_seen) {
unsigned int n;
n = portscan_mt_full(ctdata->mark & connmark_mask, ctstate,
in == init_net__loopback_dev, tcph,
skb->len - protoff - 4 * tcph->doff);
ctdata->mark = (ctdata->mark & ~connmark_mask) | n;
skb_nfmark(skb) = (skb_nfmark(skb) & ~packet_mask) ^ mark_seen;
}
return (info->match_syn && ctdata->mark == mark_synscan) ||
(info->match_cn && ctdata->mark == mark_cnscan) ||
(info->match_gr && ctdata->mark == mark_grscan);
}
static bool portscan_mt_check(const char *tablename, const void *entry,
const struct xt_match *match, void *matchinfo, unsigned int hook_mask)
{
const struct xt_portscan_mtinfo *info = matchinfo;
if ((info->match_stealth & ~1) || (info->match_syn & ~1) ||
(info->match_cn & ~1) || (info->match_gr & ~1)) {
printk(KERN_WARNING PFX "Invalid flags\n");
return false;
}
return true;
}
static struct xt_match portscan_mt_reg __read_mostly = {
.name = "portscan",
.revision = 0,
.family = AF_INET,
.match = portscan_mt,
.checkentry = portscan_mt_check,
.matchsize = sizeof(struct xt_portscan_mtinfo),
.proto = IPPROTO_TCP,
.me = THIS_MODULE,
};
static int __init portscan_mt_init(void)
{
return xt_register_match(&portscan_mt_reg);
}
static void __exit portscan_mt_exit(void)
{
xt_unregister_match(&portscan_mt_reg);
return;
}
module_init(portscan_mt_init);
module_exit(portscan_mt_exit);
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
MODULE_DESCRIPTION("netfilter \"portscan\" match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_portscan");

8
extensions/xt_portscan.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef _LINUX_NETFILTER_XT_PORTSCAN_H
#define _LINUX_NETFILTER_XT_PORTSCAN_H 1
struct xt_portscan_mtinfo {
uint8_t match_stealth, match_syn, match_cn, match_gr;
};
#endif /* _LINUX_NETFILTER_XT_PORTSCAN_H */

13
mconfig Normal file
View File

@@ -0,0 +1,13 @@
# -*- Makefile -*-
#
# Only "build_${name}=m" (build extensions) or "build_${name}="
# (do not build) are valid!
#
build_CHAOS=m
build_DELUDE=m
build_ECHO=
build_LOGMARK=m
build_TARPIT=m
build_TEE=m
build_geoip=m
build_portscan=m

3
sources Normal file
View File

@@ -0,0 +1,3 @@
#
# Source URLs for external patchlets
#

83
xa-download-more Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/perl -w
use HTTP::Request;
use LWP::UserAgent;
use strict;
&main(\@ARGV);
sub main ($)
{
local *FH;
if (!-d "downloads") {
if (!mkdir("downloads")) {
die "Could not create downloads/ directory";
}
}
open(FH, "<sources");
while (defined($_ = <FH>)) {
chomp $_;
$_ =~ s/#.*//gs;
$_ =~ s/^\s+|\s+$//gs;
if (length($_) == 0) {
next;
}
&process_index($_);
}
close FH;
}
sub process_index ($)
{
my $top = shift @_;
my($agent, $res, $url);
local *FH;
$agent = LWP::UserAgent->new();
$agent->env_proxy();
$url = &slash_remove("$top/xa-index.txt");
print " GET $url\n";
$res = $agent->get($url);
if (!$res->is_success()) {
print STDERR " `-> ", $res->status_line(), "\n";
return;
}
foreach my $ext (split(/\s+/, $res->content())) {
my($ex_url, $ex_res);
$ex_url = &slash_remove("$top/$ext");
print " GET $ex_url\n";
$ex_res = $agent->mirror($ex_url, "downloads/$ext");
if ($ex_res->code() == 304) {
# "Not modified" = up to date
next;
}
if (!$ex_res->is_success()) {
print STDERR " `-> ", $ex_res->status_line(), "\n";
next;
}
print " UNPACK downloads/$ext\n";
system "tar", "-xjf", "downloads/$ext";
}
}
sub slash_remove ($)
{
my $s = shift @_;
$s =~ s{(\w+://)(.*)}{$1.&slash_remove2($2)}eg;
return $s;
}
sub slash_remove2 ($)
{
my $s = shift @_;
$s =~ s{/+}{/}g;
return $s;
}