mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c168a2f142 | ||
![]() |
68af6989b1 | ||
![]() |
446c67018a | ||
![]() |
0fe8e180c4 | ||
![]() |
7cdfc0ac3d | ||
![]() |
85cab10371 | ||
![]() |
61d8425cb6 | ||
![]() |
d49b6244c1 | ||
![]() |
10c2b97786 | ||
![]() |
9ed364ed36 | ||
![]() |
b95e5f6417 | ||
![]() |
4afebf88eb | ||
![]() |
d523158e92 | ||
![]() |
1fd1787a1c | ||
![]() |
fbbca68790 | ||
![]() |
4cdfd49637 | ||
![]() |
31c01cf107 | ||
![]() |
879e964f60 | ||
![]() |
019c9de291 | ||
![]() |
af370f81f0 | ||
![]() |
598c7ede37 | ||
![]() |
2f66755226 | ||
![]() |
d01a5f3d17 | ||
![]() |
bbda3e53da | ||
![]() |
22e73ea31f | ||
![]() |
6b37f201d7 | ||
![]() |
94ecf3847b | ||
![]() |
ee968691d7 | ||
![]() |
22db3bcb9c | ||
![]() |
7da803e908 | ||
![]() |
4aad07bdc4 | ||
![]() |
7a3f874753 | ||
![]() |
f77a8e2eda | ||
![]() |
bd99e950f5 | ||
![]() |
fdb7f34bc8 | ||
![]() |
85e3c24167 | ||
![]() |
aab8dd360f | ||
![]() |
a8f60d0d4b |
13
INSTALL
13
INSTALL
@@ -65,6 +65,19 @@ If you want to enable debugging, use
|
||||
much easier.)
|
||||
|
||||
|
||||
Build-time options
|
||||
==================
|
||||
|
||||
V= controls the kernel's make verbosity.
|
||||
V=0 "silent" (output filename)
|
||||
V=1 "verbose" (entire gcc command line)
|
||||
|
||||
VU= controls the Xt-a make verbosity.
|
||||
VU=0 output filename
|
||||
VU=1 output filename and source file
|
||||
VU=2 entire gcc command line
|
||||
|
||||
|
||||
Note to distribution packagers
|
||||
==============================
|
||||
|
||||
|
@@ -1,12 +1,13 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
SUBDIRS = extensions extensions/ipset
|
||||
SUBDIRS = extensions
|
||||
|
||||
man_MANS := xtables-addons.8
|
||||
|
||||
xtables-addons.8: ${srcdir}/xtables-addons.8.in extensions/matches.man extensions/targets.man
|
||||
${AM_VERBOSE_GEN} sed -e '/@MATCHES@/ r extensions/matches.man' -e '/@TARGET@/ r extensions/targets.man' $< >$@;
|
||||
${am__verbose_GEN}sed -e '/@MATCHES@/ r extensions/matches.man' -e '/@TARGET@/ r extensions/targets.man' $< >$@;
|
||||
|
||||
extensions/%:
|
||||
${MAKE} ${AM_MAKEFLAGS} -C $(@D) $(@F)
|
||||
|
@@ -1,8 +1,9 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.6])
|
||||
AC_INIT([xtables-addons], [1.9])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_INIT_AUTOMAKE([-Wall])
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_DISABLE_STATIC
|
||||
@@ -63,4 +64,5 @@ AC_SUBST([kinclude_CFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_OUTPUT([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile])
|
||||
AC_CONFIG_FILES([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile])
|
||||
AC_OUTPUT
|
||||
|
@@ -30,15 +30,17 @@ 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
|
||||
VU := 0
|
||||
am__1verbose_CC_0 = @echo " CC " $@;
|
||||
am__1verbose_CCLD_0 = @echo " CCLD " $@;
|
||||
am__1verbose_GEN_0 = @echo " GEN " $@;
|
||||
am__1verbose_CC_1 = @echo " CC " $@ "<-" $<;
|
||||
am__1verbose_CCLD_1 = @echo " CCLD " $@ "<-" $^;
|
||||
am__1verbose_GEN_1 = @echo " GEN " $@ "<-" $<;
|
||||
am__verbose_CC = ${am__1verbose_CC_${VU}}
|
||||
am__verbose_CCLD = ${am__1verbose_CCLD_${VU}}
|
||||
am__verbose_GEN = ${am__1verbose_GEN_${VU}}
|
||||
|
||||
|
||||
#
|
||||
# Wildcard module list
|
||||
@@ -53,22 +55,30 @@ include ${srcdir}/Mbuild
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := ${obj-m}
|
||||
targets_install := ${obj-m}
|
||||
targets := $(filter-out %/,${obj-m})
|
||||
targets_install := ${targets}
|
||||
subdirs_list := $(filter %/,${obj-m})
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean distclean FORCE
|
||||
|
||||
all: modules user matches.man targets.man
|
||||
all: subdirs modules user matches.man targets.man
|
||||
|
||||
subdirs:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i; done;
|
||||
|
||||
subdirs-install:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i install; done;
|
||||
|
||||
user: ${targets}
|
||||
|
||||
install: modules_install ${targets_install}
|
||||
install: modules_install subdirs-install ${targets_install}
|
||||
@mkdir -p "${DESTDIR}${xtlibdir}";
|
||||
install -pm0755 ${targets_install} "${DESTDIR}${xtlibdir}/";
|
||||
|
||||
clean: clean_modules
|
||||
@for i in ${subdirs_list}; do make -C $$i clean; done;
|
||||
rm -f *.oo *.so;
|
||||
|
||||
distclean: clean
|
||||
@@ -96,10 +106,10 @@ clean_modules:
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
${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 $<;
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
|
||||
#
|
||||
@@ -116,8 +126,7 @@ wlist_targets := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_targets})
|
||||
rm -f $@.tmp;
|
||||
|
||||
man_run = \
|
||||
${AM_VERBOSE_GEN} \
|
||||
for ext in $(1); do \
|
||||
${am__verbose_GEN}for ext in $(1); do \
|
||||
f="${srcdir}/libxt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo ".SS $$ext"; \
|
||||
|
@@ -19,6 +19,7 @@ obj-${build_fuzzy} += xt_fuzzy.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_length2} += xt_length2.o
|
||||
obj-${build_portscan} += xt_portscan.o
|
||||
obj-${build_quota2} += xt_quota2.o
|
||||
|
||||
|
@@ -11,5 +11,7 @@ obj-${build_condition} += libxt_condition.so
|
||||
obj-${build_fuzzy} += libxt_fuzzy.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_length2} += libxt_length2.so
|
||||
obj-${build_portscan} += libxt_portscan.so
|
||||
obj-${build_quota2} += libxt_quota2.so
|
||||
|
@@ -32,20 +32,20 @@ xtables_CFLAGS := @xtables_CFLAGS@
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS} -DIPSET_LIB_DIR=\"${xtlibdir}\"
|
||||
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
|
||||
VU := 0
|
||||
am__1verbose_CC_0 = @echo " CC " $@;
|
||||
am__1verbose_CCLD_0 = @echo " CCLD " $@;
|
||||
am__1verbose_CC_1 = @echo " CC " $@ "<-" $<;
|
||||
am__1verbose_CCLD_1 = @echo " CCLD " $@ "<-" $^;
|
||||
am__verbose_CC = ${am__1verbose_CC_${VU}}
|
||||
am__verbose_CCLD = ${am__1verbose_CCLD_${VU}}
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := $(addsuffix .so,$(addprefix libipset_,iphash ipmap ipporthash iptree iptreemap macipmap nethash portmap))
|
||||
targets := $(addsuffix .so,$(addprefix libipset_, \
|
||||
iphash ipmap ipporthash ipportiphash ipportnethash iptree \
|
||||
iptreemap macipmap nethash portmap setlist))
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
@@ -69,16 +69,16 @@ distclean: clean
|
||||
|
||||
|
||||
ipset: ipset.o
|
||||
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -o $@ $< -ldl -rdynamic;
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -o $@ $< -ldl -rdynamic;
|
||||
|
||||
#
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
|
||||
libipset_%.oo: ${srcdir}/ipset_%.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
%.o: %.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} ${CFLAGS} -o $@ -c $<;
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} ${CFLAGS} -o $@ -c $<;
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
|
||||
#endif
|
||||
|
||||
#define IPSET_VERSION "2.4.5"
|
||||
#define IPSET_VERSION "2.4.7"
|
||||
|
||||
char program_name[] = "ipset";
|
||||
char program_version[] = IPSET_VERSION;
|
||||
|
@@ -106,8 +106,7 @@ static struct xtables_target chaos_tg_reg = {
|
||||
.extra_opts = chaos_tg_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void chaos_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&chaos_tg_reg);
|
||||
}
|
||||
|
@@ -41,8 +41,7 @@ static struct xtables_target delude_tg_reg = {
|
||||
.final_check = delude_tg_check,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void delude_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&delude_tg_reg);
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ static struct xtables_target dhcpaddr_tg_reg = {
|
||||
.extra_opts = dhcpaddr_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void dhcpaddr_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&dhcpaddr_tg_reg);
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@ static struct xtables_target echo_tg_reg = {
|
||||
.final_check = echo_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void echo_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&echo_tg_reg);
|
||||
}
|
||||
|
4
extensions/libxt_ECHO.man
Normal file
4
extensions/libxt_ECHO.man
Normal file
@@ -0,0 +1,4 @@
|
||||
The \fBECHO\fP target will send back all packets it received. It serves as an
|
||||
examples for an Xtables target.
|
||||
.PP
|
||||
ECHO takes no options.
|
@@ -68,7 +68,7 @@ static int ipmark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
exit_error(PARAMETER_PROBLEM, "Bad addr value `%s' - should be `src' or `dst'", optarg);
|
||||
*flags |= FL_ADDR_USED;
|
||||
return true;
|
||||
|
||||
|
||||
case '2':
|
||||
param_act(P_ONLY_ONCE, "IPMARK", "and-mask", *flags & FL_AND_MASK_USED);
|
||||
param_act(P_NO_INVERT, "IPMARK", "and-mask", invert);
|
||||
@@ -175,7 +175,7 @@ static struct xtables_target ipmark_tg6_reg = {
|
||||
.extra_opts = ipmark_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void ipmark_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&ipmark_tg4_reg);
|
||||
xtables_register_target(&ipmark_tg6_reg);
|
||||
|
@@ -111,8 +111,7 @@ static struct xtables_target logmark_tg_reg = {
|
||||
.extra_opts = logmark_tg_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void logmark_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&logmark_tg_reg);
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ static struct xtables_target sysrq_tg6_reg = {
|
||||
.final_check = sysrq_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void sysrq_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&sysrq_tg4_reg);
|
||||
xtables_register_target(&sysrq_tg6_reg);
|
||||
|
@@ -1,17 +1,19 @@
|
||||
The SYSRQ target allows to remotely trigger sysrq on the local machine over the
|
||||
network. This can be useful when vital parts of the machine hang, for example
|
||||
an oops in a filesystem causing locks to be not released and processes to get
|
||||
stuck as a result -- if still possible, use /proc/sysrq-trigger. Even when
|
||||
stuck as a result - if still possible, use /proc/sysrq-trigger. Even when
|
||||
processes are stuck, interrupts are likely to be still processed, and as such,
|
||||
sysrq can be triggered through incoming network packets.
|
||||
.PP
|
||||
This xt_SYSRQ implementation does not use any encryption, so you should change
|
||||
the SYSRQ password after use unless you have made sure it was transmitted
|
||||
securely and no one sniffed the network, e.g. by use of an IPsec tunnel whose
|
||||
endpoint is at the machine where you want to trigger the sysrq. Also, you
|
||||
should limit as to who can issue commands using \fB-s\fP and/or \fB-m mac\fP,
|
||||
and also that the destination is correct using \fB-d\fP (to protect against
|
||||
potential broadcast packets), noting that it is still short of MAC/IP spoofing:
|
||||
The xt_SYSRQ implementation uses a salted hash and a sequence number to prevent
|
||||
network sniffers from either guessing the password or replaying earlier
|
||||
requests. The initial sequence number comes from the time of day so you will
|
||||
have a small window of vulnerability should time go backwards at a reboot.
|
||||
However, the file /sys/module/xt_SYSREQ/seqno can be used to both query and
|
||||
update the current sequence number. Also, you should limit as to who can issue
|
||||
commands using \fB-s\fP and/or \fB-m mac\fP, and also that the destination is
|
||||
correct using \fB-d\fP (to protect against potential broadcast packets), noting
|
||||
that it is still short of MAC/IP spoofing:
|
||||
.IP
|
||||
-A INPUT -s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
|
||||
-p udp --dport 9 -j SYSRQ
|
||||
@@ -20,28 +22,59 @@ potential broadcast packets), noting that it is still short of MAC/IP spoofing:
|
||||
ipsec --proto esp --tunnel-src 10.10.25.1 --tunnel-dst 10.10.25.7
|
||||
-p udp --dport 9 -j SYSRQ
|
||||
.PP
|
||||
You should also limit the rate at which connections can be received to limit
|
||||
the CPU time taken by illegal requests, for example:
|
||||
.IP
|
||||
-A INPUT 0s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
|
||||
-p udp --dport 9 -m limit --limit 5/minute -j SYSRQ
|
||||
.PP
|
||||
This extension does not take any options. The \fB-p udp\fP options are
|
||||
required.
|
||||
.PP
|
||||
The SYSRQ password can be changed through
|
||||
/sys/module/xt_SYSRQ/parameters/password; note you need to use `echo -n` to
|
||||
not add a newline to the password, i.e.
|
||||
/sys/module/xt_SYSRQ/parameters/password, for example:
|
||||
.IP
|
||||
echo -n "password" >/sys/.../password
|
||||
echo -n "password" >/sys/module/xt_SYSRQ/parameters/password
|
||||
.PP
|
||||
Alternatively, the password may be specified at modprobe time, but this is
|
||||
insecure as people can possible see it through ps(1). You can use an option
|
||||
line in /etc/modprobe.d/sysrq if it is properly guarded, that is, only readable
|
||||
by root.
|
||||
line in e.g. /etc/modprobe.d/xt_sysrq if it is properly guarded, that is, only
|
||||
readable by root.
|
||||
.IP
|
||||
options xt_SYSRQ password=cookies
|
||||
.PP
|
||||
To trigger SYSRQ from a remote host, just use netcat or socat, specifying the
|
||||
action (only one) as first character, followed by the password:
|
||||
The hash algorithm can also be specified as a module option, for example, to
|
||||
use SHA-256 instead of the default SHA-1:
|
||||
.IP
|
||||
echo -n "scookies" | socat stdin udp-sendto:10.10.25.7:9
|
||||
.IP
|
||||
echo -n "scookies" | netcat -u 10.10.25.7 9
|
||||
options xt_SYSRQ hash=sha256
|
||||
.PP
|
||||
See the Linux docs for possible sysrq keys. Important ones are:
|
||||
re(b)oot, power(o)ff, (s)ync filesystems, (u)mount and remount readonly.
|
||||
The xt_SYSRQ module is normally silent unless a successful request is received,
|
||||
but the \fIdebug\fP module parameter can be used to find exactly why a
|
||||
seemingly correct request is not being processed.
|
||||
.PP
|
||||
To trigger SYSRQ from a remote host, just use netcat or socat:
|
||||
.PP
|
||||
.nf
|
||||
sysrq_key="s" # the SysRq key(s)
|
||||
password="password"
|
||||
seqno="$(date +%s)"
|
||||
salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
|
||||
openssl enc -base64)"
|
||||
req="$sysrq_key,$seqno,$salt"
|
||||
req="$req,$(echo -n "$req,$password" | sha1sum | cut -c1-40)"
|
||||
|
||||
echo "$req" | socat stdin udp-sendto:10.10.25.7:9
|
||||
# or
|
||||
echo "$req" | netcat -uw1 10.10.25.7 9
|
||||
.fi
|
||||
.PP
|
||||
See the Linux docs for possible sysrq keys. Important ones are: re(b)oot,
|
||||
power(o)ff, (s)ync filesystems, (u)mount and remount readonly. More than one
|
||||
sysrq key can be used at once, but bear in mind that, for example, a sync may
|
||||
not complete before a subsequent reboot or poweroff.
|
||||
.PP
|
||||
The hashing scheme should be enough to prevent mis-use of SYSRQ in many
|
||||
environments, but it is not perfect: take reasonable precautions to
|
||||
protect your machines. Most importantly ensure that each machine has a
|
||||
different password; there is scant protection for a SYSRQ packet being
|
||||
applied to a machine that happens to have the same password.
|
||||
|
@@ -32,7 +32,7 @@ static struct xtables_target tarpit_tg_reg = {
|
||||
.final_check = tarpit_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void tarpit_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&tarpit_tg_reg);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* "TEE" target extension for iptables
|
||||
* Copyright © Sebastian Claßen <sebastian.classen [at] freenet.ag>, 2007
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
@@ -53,10 +53,6 @@ static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
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,
|
||||
@@ -70,6 +66,31 @@ static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tee_tg6_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 in6_addr *ia;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
if (*flags & FLAG_GATEWAY)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gw more than once");
|
||||
|
||||
ia = numeric_to_ip6addr(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)
|
||||
@@ -83,9 +104,20 @@ static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
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));
|
||||
else
|
||||
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_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 ", ip6addr_to_numeric(&info->gw.in6));
|
||||
else
|
||||
printf("TEE gw:%s ", ip6addr_to_anyname(&info->gw.in6));
|
||||
}
|
||||
|
||||
static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
@@ -95,9 +127,18 @@ static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
printf("--gateway %s ", ipaddr_to_numeric(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf("--gateway %s ", ip6addr_to_numeric(&info->gw.in6));
|
||||
}
|
||||
|
||||
static struct xtables_target tee_tg_reg = {
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
@@ -108,7 +149,23 @@ static struct xtables_target tee_tg_reg = {
|
||||
.extra_opts = tee_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static struct xtables_target tee_tg6_reg = {
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
.parse = tee_tg6_parse,
|
||||
.final_check = tee_tg_check,
|
||||
.print = tee_tg6_print,
|
||||
.save = tee_tg6_save,
|
||||
.extra_opts = tee_tg_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void tee_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&tee_tg_reg);
|
||||
xtables_register_target(&tee_tg6_reg);
|
||||
}
|
||||
|
8
extensions/libxt_TEE.man
Normal file
8
extensions/libxt_TEE.man
Normal file
@@ -0,0 +1,8 @@
|
||||
The \fBTEE\fP target will clone a packet and redirect this clone to another
|
||||
machine on the \fBlocal\fP network segment. In other words, the nexthop
|
||||
must be the target, or you will have to configure the nexthop to forward it
|
||||
further if so desired.
|
||||
.TP
|
||||
\fB--gw\fP \fIipaddr\fP
|
||||
Send the cloned packet to the host reachable at the given IP address.
|
||||
Use of 0.0.0.0 (for IPv4 packets) or :: (IPv6) is invalid.
|
@@ -92,7 +92,7 @@ static struct xtables_match condition_mt_reg = {
|
||||
.extra_opts = condition_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void condition_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&condition_mt_reg);
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ static struct xtables_match dhcpaddr_mt_reg = {
|
||||
.extra_opts = dhcpaddr_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void dhcpaddr_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&dhcpaddr_mt_reg);
|
||||
}
|
||||
|
@@ -112,7 +112,7 @@ static struct xtables_match fuzzy_mt_reg = {
|
||||
.extra_opts = fuzzy_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void fuzzy_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&fuzzy_mt_reg);
|
||||
}
|
||||
|
@@ -272,7 +272,7 @@ static struct xtables_match geoip_match = {
|
||||
.extra_opts = geoip_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void geoip_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&geoip_match);
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@
|
||||
static void ipp2p_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"IPP2P v%s options:\n"
|
||||
"ipp2p v%s match options:\n"
|
||||
" --edk [tcp,udp] All known eDonkey/eMule/Overnet packets\n"
|
||||
" --dc [tcp] All known Direct Connect packets\n"
|
||||
" --kazaa [tcp,udp] All known KaZaA packets\n"
|
||||
@@ -32,19 +32,10 @@ static void ipp2p_mt_help(void)
|
||||
" --winmx [tcp] All known WinMX\n"
|
||||
" --soul [tcp] All known SoulSeek\n"
|
||||
" --ares [tcp] All known Ares\n\n"
|
||||
"EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
|
||||
"EXPERIMENTAL protocols:\n"
|
||||
" --mute [tcp] All known Mute packets\n"
|
||||
" --waste [tcp] All known Waste packets\n"
|
||||
" --xdcc [tcp] All known XDCC packets (only xdcc login)\n\n"
|
||||
"DEBUG SUPPPORT, use only if you know why\n"
|
||||
" --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
|
||||
"\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
|
||||
"You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
|
||||
"\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
|
||||
"\nExamples:\n"
|
||||
" iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
|
||||
" iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
|
||||
" iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
|
||||
, IPP2P_VERSION);
|
||||
}
|
||||
|
||||
@@ -242,7 +233,7 @@ static struct xtables_match ipp2p_mt_reg = {
|
||||
.extra_opts = ipp2p_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void ipp2p_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&ipp2p_mt_reg);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
This module matches certain packets in P2P flows. It is not
|
||||
designed to match all packets belonging to a P2P connection -
|
||||
use IPP2P together with CONNMARK for this purpose. Also visit
|
||||
http://www.ipp2p.org for detailed information.
|
||||
|
||||
use IPP2P together with CONNMARK for this purpose.
|
||||
.PP
|
||||
Use it together with -p tcp or -p udp to search these protocols
|
||||
only or without -p switch to search packets of both protocols.
|
||||
|
||||
IPP2P provides the following options:
|
||||
.PP
|
||||
IPP2P provides the following options, of which one or more may be specified
|
||||
on the command line:
|
||||
.TP
|
||||
.B "--edk "
|
||||
Matches as many eDonkey/eMule packets as possible.
|
||||
@@ -38,3 +38,11 @@ Matches Ares and AresLite packets. Use together with -j DROP only.
|
||||
.B "--debug "
|
||||
Prints some information about each hit into kernel logfile. May
|
||||
produce huge logfiles so beware!
|
||||
.PP
|
||||
Note that ipp2p may not (and often, does not) identify all packets that are
|
||||
exchanged as a result of running filesharing programs.
|
||||
.PP
|
||||
There is more information on http://ipp2p.org/ , but it has not been updated
|
||||
since September 2006, and the syntax there is different from the ipp2p.c
|
||||
provided in Xtables-addons; most importantly, the --ipp2p flag was removed due
|
||||
to its ambiguity to match "all known" protocols.
|
||||
|
18
extensions/libxt_length.man
Normal file
18
extensions/libxt_length.man
Normal file
@@ -0,0 +1,18 @@
|
||||
This module matches the length of a packet against a specific value or range of
|
||||
values.
|
||||
.TP
|
||||
[\fB!\fR] \fB--length\fR \fIlength\fR[\fB:\fR\fIlength\fR]
|
||||
Match exact length or length range.
|
||||
.TP
|
||||
\fB--layer3\fR
|
||||
Match the layer3 frame size (e.g. IPv4/v6 header plus payload).
|
||||
.TP
|
||||
\fB--layer4\fR
|
||||
Match the layer4 frame size (e.g. TCP/UDP header plus payload).
|
||||
.TP
|
||||
\fB--layer5\fR
|
||||
Match the layer5 frame size (e.g. TCP/UDP payload, often called layer7).
|
||||
.PP
|
||||
If no --layer* option is given, --layer3 is assumed by default. Note that using
|
||||
--layer5 may not match a packet if it is not one of the recognized types
|
||||
(currently TCP, UDP, UDPLite, ICMP, AH and ESP) or which has no 5th layer.
|
173
extensions/libxt_length2.c
Normal file
173
extensions/libxt_length2.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <getopt.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_length2.h"
|
||||
|
||||
enum {
|
||||
F_LAYER = 1 << 0,
|
||||
F_LENGTH = 1 << 1,
|
||||
|
||||
XT_LENGTH_LAYER_MASK = XT_LENGTH_LAYER3 | XT_LENGTH_LAYER4 |
|
||||
XT_LENGTH_LAYER5 | XT_LENGTH_LAYER7,
|
||||
};
|
||||
|
||||
static void length_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"length match options:\n"
|
||||
" --layer3 Match against layer3 size (e.g. L4 + IPv6 header)\n"
|
||||
" --layer4 Match against layer4 size (e.g. L5 + SCTP header)\n"
|
||||
" --layer5 Match against layer5 size (e.g. L7 + chunk headers)\n"
|
||||
" --layer7 Match against layer7 payload (e.g. SCTP payload)\n"
|
||||
"[!] --length n[:n] Match packet length against value or range\n"
|
||||
" of values (inclusive)\n"
|
||||
);
|
||||
}
|
||||
|
||||
static const struct option length_mt_opts[] = {
|
||||
{.name = "layer3", .has_arg = false, .val = '3'},
|
||||
{.name = "layer4", .has_arg = false, .val = '4'},
|
||||
{.name = "layer5", .has_arg = false, .val = '5'},
|
||||
{.name = "layer7", .has_arg = false, .val = '7'},
|
||||
{.name = "length", .has_arg = true, .val = '='},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void length_mt_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct xt_length_mtinfo2 *info = (void *)match->data;
|
||||
|
||||
info->flags = XT_LENGTH_LAYER3;
|
||||
}
|
||||
|
||||
static int length_mt_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct xt_length_mtinfo2 *info = (void *)(*match)->data;
|
||||
unsigned int from, to;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case '3': /* --layer3 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER3;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '4': /* --layer4 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER4;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '5': /* --layer5 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER5;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '7': /* --layer7 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER7;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '=': /* --length */
|
||||
param_act(P_ONLY_ONCE, "length", "--length", *flags & F_LENGTH);
|
||||
if (invert)
|
||||
info->flags |= XT_LENGTH_INVERT;
|
||||
if (!strtonum(optarg, &end, &from, 0, ~0U))
|
||||
param_act(P_BAD_VALUE, "length", "--length", optarg);
|
||||
to = from;
|
||||
if (*end == ':')
|
||||
if (!strtonum(end + 1, &end, &to, 0, ~0U))
|
||||
param_act(P_BAD_VALUE, "length",
|
||||
"--length", optarg);
|
||||
if (*end != '\0')
|
||||
param_act(P_BAD_VALUE, "length", "--length", optarg);
|
||||
info->min = from;
|
||||
info->max = to;
|
||||
*flags |= F_LENGTH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void length_mt_check(unsigned int flags)
|
||||
{
|
||||
if (!(flags & F_LENGTH))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"length: You must specify \"--length\"");
|
||||
if (!(flags & F_LAYER))
|
||||
fprintf(stderr, "iptables: length match: Defaulting to "
|
||||
"--layer3. Consider specifying it explicitly.\n");
|
||||
}
|
||||
|
||||
static void length_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
printf("layer3 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
printf("layer4 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
printf("layer5 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
printf("layer7 ");
|
||||
printf("length ");
|
||||
if (info->flags & XT_LENGTH_INVERT)
|
||||
printf("! ");
|
||||
if (info->min == info->max)
|
||||
printf("%u ", (unsigned int)info->min);
|
||||
else
|
||||
printf("%u-%u ", (unsigned int)info->min,
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static void length_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
printf("--layer3 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
printf("--layer4 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
printf("--layer5 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
printf("--layer7 ");
|
||||
if (info->flags & XT_LENGTH_INVERT)
|
||||
printf("! ");
|
||||
printf("--length ");
|
||||
if (info->min == info->max)
|
||||
printf("%u ", (unsigned int)info->min);
|
||||
else
|
||||
printf("%u:%u ", (unsigned int)info->min,
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static struct xtables_match length2_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "length2",
|
||||
.revision = 2,
|
||||
.family = PF_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_length_mtinfo2)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_length_mtinfo2)),
|
||||
.init = length_mt_init,
|
||||
.help = length_mt_help,
|
||||
.parse = length_mt_parse,
|
||||
.final_check = length_mt_check,
|
||||
.print = length_mt_print,
|
||||
.save = length_mt_save,
|
||||
.extra_opts = length_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_match(&length2_mt_reg);
|
||||
}
|
@@ -116,8 +116,7 @@ static struct xtables_match portscan_mt_reg = {
|
||||
.extra_opts = portscan_mt_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void portscan_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&portscan_mt_reg);
|
||||
}
|
||||
|
@@ -20,7 +20,11 @@ connection was torn down after completion of the 3-way handshake.
|
||||
\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)
|
||||
identification. (E.g. openssh, smtp, ftpd.) This may falsely trigger on
|
||||
warranted single-direction data flows, usually bulk data transfers such as
|
||||
FTP DATA connections or IRC DCC. Grab Scan Detection should only be used on
|
||||
ports where a protocol runs that is guaranteed to do a bidirectional exchange
|
||||
of bytes.
|
||||
.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,
|
||||
|
@@ -133,7 +133,7 @@ static struct xtables_match quota_mt2_reg = {
|
||||
.extra_opts = quota_mt2_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void quota2_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match("a_mt2_reg);
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_target_param *par)
|
||||
unsigned int addr_type, data_len;
|
||||
void *payload;
|
||||
|
||||
printk(KERN_INFO "dst_out=%p\n", (*poldskb)->dst->output);
|
||||
|
||||
/* This allows us to do the copy operation in fewer lines of code. */
|
||||
if (skb_linearize(*poldskb) < 0)
|
||||
return NF_DROP;
|
||||
@@ -75,10 +77,10 @@ echo_tg4(struct sk_buff **poldskb, const struct xt_target_param *par)
|
||||
|
||||
addr_type = RTN_UNSPEC;
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL &&
|
||||
if (par->hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL &&
|
||||
newskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
#else
|
||||
if (hooknum != NF_INET_FORWARD)
|
||||
if (par->hooknum != NF_INET_FORWARD)
|
||||
#endif
|
||||
addr_type = RTN_LOCAL;
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk>
|
||||
* xt_SYSRQ does not use hashing or timestamps.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -19,15 +18,145 @@
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <net/ip.h>
|
||||
#include "compat_xtables.h"
|
||||
|
||||
static bool sysrq_once;
|
||||
static char sysrq_password[64];
|
||||
static char sysrq_hash[16] = "sha1";
|
||||
static long sysrq_seqno;
|
||||
static int sysrq_debug;
|
||||
module_param_string(password, sysrq_password, sizeof(sysrq_password),
|
||||
S_IRUSR | S_IWUSR);
|
||||
module_param_string(hash, sysrq_hash, sizeof(sysrq_hash), S_IRUSR);
|
||||
module_param_named(seqno, sysrq_seqno, long, S_IRUSR | S_IWUSR);
|
||||
module_param_named(debug, sysrq_debug, int, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(password, "password for remote sysrq");
|
||||
MODULE_PARM_DESC(hash, "hash algorithm, default sha1");
|
||||
MODULE_PARM_DESC(seqno, "sequence number for remote sysrq");
|
||||
MODULE_PARM_DESC(debug, "debugging: 0=off, 1=on");
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
static struct crypto_hash *sysrq_tfm;
|
||||
static int sysrq_digest_size;
|
||||
static unsigned char *sysrq_digest_password;
|
||||
static unsigned char *sysrq_digest;
|
||||
static char *sysrq_hexdigest;
|
||||
|
||||
/*
|
||||
* The data is of the form "<requests>,<seqno>,<salt>,<hash>" where <requests>
|
||||
* is a series of sysrq requests; <seqno> is a sequence number that must be
|
||||
* greater than the last sequence number; <salt> is some random bytes; and
|
||||
* <hash> is the hash of everything up to and including the preceding ","
|
||||
* together with the password.
|
||||
*
|
||||
* For example
|
||||
*
|
||||
* salt=$RANDOM
|
||||
* req="s,$(date +%s),$salt"
|
||||
* echo "$req,$(echo -n $req,secret | sha1sum | cut -c1-40)"
|
||||
*
|
||||
* You will want a better salt and password than that though :-)
|
||||
*/
|
||||
static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
{
|
||||
const char *data = pdata;
|
||||
int i, n;
|
||||
struct scatterlist sg[2];
|
||||
struct hash_desc desc;
|
||||
int ret;
|
||||
long new_seqno = 0;
|
||||
|
||||
if (*sysrq_password == '\0') {
|
||||
if (!sysrq_once)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": No password set\n");
|
||||
sysrq_once = true;
|
||||
return NF_DROP;
|
||||
}
|
||||
if (len == 0)
|
||||
return NF_DROP;
|
||||
|
||||
for (i = 0; sysrq_password[i] != '\0' &&
|
||||
sysrq_password[i] != '\n'; ++i)
|
||||
/* loop */;
|
||||
sysrq_password[i] = '\0';
|
||||
|
||||
i = 0;
|
||||
for (n = 0; n < len - 1; ++n) {
|
||||
if (i == 1 && '0' <= data[n] && data[n] <= '9')
|
||||
new_seqno = 10L * new_seqno + data[n] - '0';
|
||||
if (data[n] == ',' && ++i == 3)
|
||||
break;
|
||||
}
|
||||
++n;
|
||||
if (i != 3) {
|
||||
if (sysrq_debug)
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": badly formatted request\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
if (sysrq_seqno >= new_seqno) {
|
||||
if (sysrq_debug)
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": old sequence number ignored\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
desc.tfm = sysrq_tfm;
|
||||
desc.flags = 0;
|
||||
ret = crypto_hash_init(&desc);
|
||||
if (ret != 0)
|
||||
goto hash_fail;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||
sg_init_table(sg, 2);
|
||||
#endif
|
||||
sg_set_buf(&sg[0], data, n);
|
||||
strcpy(sysrq_digest_password, sysrq_password);
|
||||
i = strlen(sysrq_digest_password);
|
||||
sg_set_buf(&sg[1], sysrq_digest_password, i);
|
||||
ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest);
|
||||
if (ret != 0)
|
||||
goto hash_fail;
|
||||
|
||||
for (i = 0; i < sysrq_digest_size; ++i) {
|
||||
sysrq_hexdigest[2*i] =
|
||||
"0123456789abcdef"[(sysrq_digest[i] >> 4) & 0xf];
|
||||
sysrq_hexdigest[2*i+1] =
|
||||
"0123456789abcdef"[sysrq_digest[i] & 0xf];
|
||||
}
|
||||
sysrq_hexdigest[2*sysrq_digest_size] = '\0';
|
||||
if (len - n < sysrq_digest_size) {
|
||||
if (sysrq_debug)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": Short digest,"
|
||||
" expected %s\n", sysrq_hexdigest);
|
||||
return NF_DROP;
|
||||
}
|
||||
if (strncmp(data + n, sysrq_hexdigest, sysrq_digest_size) != 0) {
|
||||
if (sysrq_debug)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": Bad digest,"
|
||||
" expected %s\n", sysrq_hexdigest);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
/* Now we trust the requester */
|
||||
sysrq_seqno = new_seqno;
|
||||
for (i = 0; i < len && data[i] != ','; ++i) {
|
||||
printk(KERN_INFO KBUILD_MODNAME ": SysRq %c\n", data[i]);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
handle_sysrq(data[i], NULL);
|
||||
#else
|
||||
handle_sysrq(data[i], NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
return NF_ACCEPT;
|
||||
|
||||
hash_fail:
|
||||
printk(KERN_WARNING KBUILD_MODNAME ": digest failure\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
#else
|
||||
static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
{
|
||||
const char *data = pdata;
|
||||
@@ -57,6 +186,7 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
|
||||
#endif
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
@@ -73,9 +203,11 @@ sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
udph = (void *)iph + ip_hdrlen(skb);
|
||||
len = ntohs(udph->len) - sizeof(struct udphdr);
|
||||
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " NIPQUAD_FMT ":%u -> :%u len=%u\n",
|
||||
NIPQUAD(iph->saddr), htons(udph->source), htons(udph->dest),
|
||||
len);
|
||||
if (sysrq_debug)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": " NIPQUAD_FMT ":%u -> :%u len=%u\n",
|
||||
NIPQUAD(iph->saddr), htons(udph->source),
|
||||
htons(udph->dest), len);
|
||||
return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
|
||||
}
|
||||
|
||||
@@ -94,14 +226,17 @@ sysrq_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
udph = udp_hdr(skb);
|
||||
len = ntohs(udph->len) - sizeof(struct udphdr);
|
||||
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " NIP6_FMT ":%hu -> :%hu len=%u\n",
|
||||
NIP6(iph->saddr), ntohs(udph->source),
|
||||
ntohs(udph->dest), len);
|
||||
if (sysrq_debug)
|
||||
printk(KERN_INFO KBUILD_MODNAME
|
||||
": " NIP6_FMT ":%hu -> :%hu len=%u\n",
|
||||
NIP6(iph->saddr), ntohs(udph->source),
|
||||
ntohs(udph->dest), len);
|
||||
return sysrq_tg(udph + sizeof(struct udphdr), len);
|
||||
}
|
||||
|
||||
static bool sysrq_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
|
||||
if (par->target->family == NFPROTO_IPV4) {
|
||||
const struct ipt_entry *entry = par->entryinfo;
|
||||
|
||||
@@ -146,11 +281,64 @@ static struct xt_target sysrq_tg_reg[] __read_mostly = {
|
||||
|
||||
static int __init sysrq_tg_init(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
struct timeval now;
|
||||
|
||||
sysrq_tfm = crypto_alloc_hash(sysrq_hash, 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(sysrq_tfm)) {
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": Error: Could not find or load %s hash\n",
|
||||
sysrq_hash);
|
||||
sysrq_tfm = NULL;
|
||||
goto fail;
|
||||
}
|
||||
sysrq_digest_size = crypto_hash_digestsize(sysrq_tfm);
|
||||
sysrq_digest = kmalloc(sysrq_digest_size, GFP_KERNEL);
|
||||
if (sysrq_digest == NULL) {
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": Cannot allocate digest\n");
|
||||
goto fail;
|
||||
}
|
||||
sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL);
|
||||
if (sysrq_hexdigest == NULL) {
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": Cannot allocate hexdigest\n");
|
||||
goto fail;
|
||||
}
|
||||
sysrq_digest_password = kmalloc(sizeof(sysrq_password), GFP_KERNEL);
|
||||
if (sysrq_digest_password == NULL) {
|
||||
printk(KERN_WARNING KBUILD_MODNAME
|
||||
": Cannot allocate password digest space\n");
|
||||
goto fail;
|
||||
}
|
||||
do_gettimeofday(&now);
|
||||
sysrq_seqno = now.tv_sec;
|
||||
return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
|
||||
|
||||
fail:
|
||||
if (sysrq_tfm)
|
||||
crypto_free_hash(sysrq_tfm);
|
||||
if (sysrq_digest)
|
||||
kfree(sysrq_digest);
|
||||
if (sysrq_hexdigest)
|
||||
kfree(sysrq_hexdigest);
|
||||
if (sysrq_digest_password)
|
||||
kfree(sysrq_digest_password);
|
||||
return -EINVAL;
|
||||
#else
|
||||
printk(KERN_WARNING "xt_SYSRQ does not provide crypto for <= 2.6.18\n");
|
||||
return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __exit sysrq_tg_exit(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
|
||||
crypto_free_hash(sysrq_tfm);
|
||||
kfree(sysrq_digest);
|
||||
kfree(sysrq_hexdigest);
|
||||
kfree(sysrq_digest_password);
|
||||
#endif
|
||||
return xt_unregister_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* "TEE" target extension for Xtables
|
||||
* Copyright © Sebastian Claßen <sebastian.classen [at] freenet de>, 2007
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
|
||||
*
|
||||
* based on ipt_ROUTE.c from Cédric de Launois
|
||||
* <delaunois [at] info ucl ac be>
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <net/checksum.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/route.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
|
||||
@@ -29,7 +30,7 @@ static struct nf_conn tee_track;
|
||||
#include "compat_xtables.h"
|
||||
#include "xt_TEE.h"
|
||||
|
||||
static const union nf_inet_addr zero_address;
|
||||
static const union nf_inet_addr tee_zero_address;
|
||||
|
||||
/*
|
||||
* Try to route the packet according to the routing keys specified in
|
||||
@@ -47,21 +48,16 @@ static const union nf_inet_addr zero_address;
|
||||
* 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)
|
||||
static bool
|
||||
tee_tg_route4(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,
|
||||
}
|
||||
}
|
||||
};
|
||||
struct flowi fl;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.nl_u.ip4_u.daddr = info->gw.ip;
|
||||
fl.nl_u.ip4_u.scope = RT_SCOPE_UNIVERSE;
|
||||
|
||||
/* Trying to route the packet using the standard routing table. */
|
||||
err = ip_route_output_key(&init_net, &rt, &fl);
|
||||
@@ -72,22 +68,14 @@ static bool tee_routing(struct sk_buff *skb,
|
||||
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;
|
||||
}
|
||||
|
||||
static bool dev_hh_avail(const struct net_device *dev)
|
||||
static inline bool dev_hh_avail(const struct net_device *dev)
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return dev->hard_header != NULL;
|
||||
@@ -103,14 +91,14 @@ static bool dev_hh_avail(const struct net_device *dev)
|
||||
* 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)
|
||||
static void tee_tg_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_hh_avail(dev)) {
|
||||
if (unlikely(skb_headroom(skb) < hh_len && dev_hh_avail(dev))) {
|
||||
struct sk_buff *skb2;
|
||||
|
||||
skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
|
||||
@@ -142,7 +130,7 @@ static void tee_ip_direct_send(struct sk_buff *skb)
|
||||
* packets when we see they already have that ->nfct.
|
||||
*/
|
||||
static unsigned int
|
||||
tee_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
@@ -200,8 +188,78 @@ tee_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
nf_conntrack_get(skb->nfct);
|
||||
#endif
|
||||
|
||||
if (tee_routing(skb, info))
|
||||
tee_ip_direct_send(skb);
|
||||
/*
|
||||
* Normally, we would just use ip_local_out. Because iph->check is
|
||||
* already correct, we could take a shortcut and call dst_output
|
||||
* [forwards to ip_output] directly. ip_output however will invoke
|
||||
* Netfilter hooks and cause reentrancy. So we skip that too and go
|
||||
* directly to ip_finish_output. Since we should not do XFRM, control
|
||||
* passes to ip_finish_output2. That function is not exported, so it is
|
||||
* copied here as tee_ip_direct_send.
|
||||
*
|
||||
* We do no XFRM on the cloned packet on purpose! The choice of
|
||||
* iptables match options will control whether the raw packet or the
|
||||
* transformed version is cloned.
|
||||
*
|
||||
* Also on purpose, no fragmentation is done, to preserve the
|
||||
* packet as best as possible.
|
||||
*/
|
||||
if (tee_tg_route4(skb, info))
|
||||
tee_tg_send(skb);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info)
|
||||
{
|
||||
struct dst_entry *dst;
|
||||
struct flowi fl;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.nl_u.ip6_u.daddr = info->gw.in6;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 25)
|
||||
dst = ip6_route_output(NULL, &fl);
|
||||
#else
|
||||
dst = ip6_route_output(dev_net(skb->dev), NULL, &fl);
|
||||
#endif
|
||||
if (dst == NULL) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR "ip6_route_output failed for tee\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dst_release(skb->dst);
|
||||
skb->dst = dst;
|
||||
skb->dev = skb->dst->dev;
|
||||
skb->protocol = htons(ETH_P_IPV6);
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
tee_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
|
||||
/* Try silence. */
|
||||
#ifdef WITH_CONNTRACK
|
||||
if (skb->nfct == &tee_track.ct_general)
|
||||
return NF_DROP;
|
||||
#endif
|
||||
|
||||
if ((skb = skb_copy(skb, GFP_ATOMIC)) == NULL)
|
||||
return XT_CONTINUE;
|
||||
|
||||
#ifdef WITH_CONNTRACK
|
||||
nf_conntrack_put(skb->nfct);
|
||||
skb->nfct = &tee_track.ct_general;
|
||||
skb->nfctinfo = IP_CT_NEW;
|
||||
nf_conntrack_get(skb->nfct);
|
||||
#endif
|
||||
if (tee_tg_route6(skb, info))
|
||||
tee_tg_send(skb);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
@@ -211,18 +269,31 @@ static bool tee_tg_check(const struct xt_tgchk_param *par)
|
||||
const struct xt_tee_tginfo *info = par->targinfo;
|
||||
|
||||
/* 0.0.0.0 and :: not allowed */
|
||||
return memcmp(&info->gw, &zero_address, sizeof(zero_address)) != 0;
|
||||
return memcmp(&info->gw, &tee_zero_address,
|
||||
sizeof(tee_zero_address)) != 0;
|
||||
}
|
||||
|
||||
static struct xt_target tee_tg_reg __read_mostly = {
|
||||
.name = "TEE",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "mangle",
|
||||
.target = tee_tg,
|
||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||
.checkentry = tee_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
static struct xt_target tee_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "TEE",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "mangle",
|
||||
.target = tee_tg4,
|
||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||
.checkentry = tee_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "TEE",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV6,
|
||||
.table = "mangle",
|
||||
.target = tee_tg6,
|
||||
.targetsize = sizeof(struct xt_tee_tginfo),
|
||||
.checkentry = tee_tg_check,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tee_tg_init(void)
|
||||
@@ -241,19 +312,20 @@ static int __init tee_tg_init(void)
|
||||
tee_track.status |= IPS_NAT_DONE_MASK;
|
||||
#endif
|
||||
|
||||
return xt_register_target(&tee_tg_reg);
|
||||
return xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
|
||||
}
|
||||
|
||||
static void __exit tee_tg_exit(void)
|
||||
{
|
||||
xt_unregister_target(&tee_tg_reg);
|
||||
xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(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_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_DESCRIPTION("Xtables: Reroute packet copy");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_TEE");
|
||||
MODULE_ALIAS("ip6t_TEE");
|
||||
|
@@ -597,27 +597,51 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen)
|
||||
}
|
||||
|
||||
/* check for KaZaA download commands and other typical data */
|
||||
/* plen is guaranteed to be >= 5 (see @matchlist) */
|
||||
static unsigned int
|
||||
search_all_kazaa(const unsigned char *payload, const unsigned int plen)
|
||||
{
|
||||
if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) {
|
||||
if (memcmp(payload, "GIVE ", 5) == 0)
|
||||
return IPP2P_KAZAA * 100 + 1;
|
||||
uint16_t c, end, rem;
|
||||
|
||||
if (memcmp(payload, "GET /", 5) == 0) {
|
||||
uint16_t c = 8;
|
||||
const uint16_t end = plen - 22;
|
||||
if (plen < 5)
|
||||
/* too short for anything we test for - early bailout */
|
||||
return 0;
|
||||
|
||||
while (c < end) {
|
||||
if (payload[c] == 0x0a &&
|
||||
payload[c+1] == 0x0d &&
|
||||
(memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0 ||
|
||||
memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0))
|
||||
return IPP2P_KAZAA * 100 + 2;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
if (plen >= 65535) {
|
||||
/* Something seems _really_ fishy */
|
||||
printk(KERN_WARNING KBUILD_MODNAME ": %s: plen (%u) >= 65535\n",
|
||||
__func__, plen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (payload[plen-2] != 0x0d || payload[plen-1] != 0x0a)
|
||||
return 0;
|
||||
|
||||
if (memcmp(payload, "GIVE ", 5) == 0)
|
||||
return IPP2P_KAZAA * 100 + 1;
|
||||
|
||||
if (memcmp(payload, "GET /", 5) != 0)
|
||||
return 0;
|
||||
|
||||
if (plen < 18)
|
||||
/* The next tests would not succeed anyhow. */
|
||||
return 0;
|
||||
|
||||
end = plen - 18;
|
||||
rem = plen - 5;
|
||||
for (c = 5; c < end; ++c, --rem) {
|
||||
if (payload[c] != 0x0d)
|
||||
continue;
|
||||
if (payload[c+1] != 0x0a)
|
||||
continue;
|
||||
if (rem >= 18 &&
|
||||
memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0)
|
||||
return IPP2P_KAZAA * 100 + 2;
|
||||
if (rem >= 24 &&
|
||||
memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)
|
||||
return IPP2P_KAZAA * 100 + 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -813,7 +837,7 @@ ipp2p_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
switch (ip->protocol) {
|
||||
case IPPROTO_TCP: /* what to do with a TCP packet */
|
||||
{
|
||||
const struct tcphdr *tcph = tcp_hdr(skb);
|
||||
const struct tcphdr *tcph = (const void *)ip + ip_hdrlen(skb);
|
||||
|
||||
if (tcph->fin) return 0; /* if FIN bit is set bail out */
|
||||
if (tcph->syn) return 0; /* if SYN bit is set bail out */
|
||||
@@ -840,7 +864,7 @@ ipp2p_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
|
||||
case IPPROTO_UDP: /* what to do with an UDP packet */
|
||||
{
|
||||
const struct udphdr *udph = udp_hdr(skb);
|
||||
const struct udphdr *udph = (const void *)ip + ip_hdrlen(skb);
|
||||
|
||||
while (udp_list[i].command) {
|
||||
if ((info->cmd & udp_list[i].command) == udp_list[i].command &&
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#ifndef __IPT_IPP2P_H
|
||||
#define __IPT_IPP2P_H
|
||||
#define IPP2P_VERSION "0.9"
|
||||
#define IPP2P_VERSION "0.10"
|
||||
|
||||
enum {
|
||||
IPP2N_EDK,
|
||||
|
262
extensions/xt_length2.c
Normal file
262
extensions/xt_length2.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* xt_length - Netfilter module to match packet length
|
||||
* Copyright © Jan Engelhardt <jengelh@medozas.de>, 2007 - 2009
|
||||
*
|
||||
* 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 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <linux/dccp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include "xt_length2.h"
|
||||
#include "compat_xtables.h"
|
||||
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
|
||||
# define WITH_IPV6 1
|
||||
#endif
|
||||
#ifndef NEXTHDR_IPV4
|
||||
# define NEXTHDR_IPV4 4
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_DESCRIPTION("Xtables: Packet length (Layer3,4,5) match");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_length2");
|
||||
MODULE_ALIAS("ip6t_length2");
|
||||
|
||||
static bool
|
||||
xtlength_layer5_tcp(unsigned int *length, const struct sk_buff *skb,
|
||||
unsigned int offset)
|
||||
{
|
||||
const struct tcphdr *tcph;
|
||||
struct tcphdr buf;
|
||||
|
||||
tcph = skb_header_pointer(skb, offset, sizeof(buf), &buf);
|
||||
if (tcph == NULL)
|
||||
return false;
|
||||
|
||||
*length = skb->len - offset;
|
||||
if (*length >= 4 * tcph->doff)
|
||||
*length -= 4 * tcph->doff;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
xtlength_layer5_dccp(unsigned int *length, const struct sk_buff *skb,
|
||||
unsigned int offset)
|
||||
{
|
||||
const struct dccp_hdr *dh;
|
||||
struct dccp_hdr dhbuf;
|
||||
|
||||
dh = skb_header_pointer(skb, offset, sizeof(dhbuf), &dhbuf);
|
||||
if (dh == NULL)
|
||||
return false;
|
||||
|
||||
*length = skb->len - offset;
|
||||
if (*length >= 4 * dh->dccph_doff)
|
||||
*length -= 4 * dh->dccph_doff;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
xtlength_layer5(unsigned int *length, const struct sk_buff *skb,
|
||||
unsigned int prot, unsigned int offset)
|
||||
{
|
||||
switch (prot) {
|
||||
case IPPROTO_TCP:
|
||||
return xtlength_layer5_tcp(length, skb, offset);
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
*length = skb->len - offset - sizeof(struct udphdr);
|
||||
return true;
|
||||
case IPPROTO_SCTP:
|
||||
*length = skb->len - offset - sizeof(struct sctphdr);
|
||||
return true;
|
||||
case IPPROTO_DCCP:
|
||||
return xtlength_layer5_dccp(length, skb, offset);
|
||||
case IPPROTO_ICMP:
|
||||
*length = skb->len - offset - sizeof(struct icmphdr);
|
||||
return true;
|
||||
case IPPROTO_ICMPV6:
|
||||
*length = skb->len - offset -
|
||||
offsetof(struct icmp6hdr, icmp6_dataun);
|
||||
return true;
|
||||
case IPPROTO_AH:
|
||||
*length = skb->len - offset - sizeof(struct ip_auth_hdr);
|
||||
return true;
|
||||
case IPPROTO_ESP:
|
||||
*length = skb->len - offset - sizeof(struct ip_esp_hdr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
xtlength_layer7_sctp(unsigned int *length, const struct sk_buff *skb,
|
||||
unsigned int offset)
|
||||
{
|
||||
const struct sctp_chunkhdr *ch;
|
||||
struct sctp_chunkhdr chbuf;
|
||||
unsigned int pos;
|
||||
|
||||
*length = 0;
|
||||
for (pos = sizeof(struct sctphdr); pos < skb->len;
|
||||
pos += ntohs(ch->length))
|
||||
{
|
||||
ch = skb_header_pointer(skb, offset + pos,
|
||||
sizeof(chbuf), &chbuf);
|
||||
if (ch == NULL)
|
||||
return false;
|
||||
if (ch->type != SCTP_CID_DATA)
|
||||
continue;
|
||||
*length += ntohs(ch->length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool xtlength_layer7(unsigned int *length, const struct sk_buff *skb,
|
||||
unsigned int proto, unsigned int offset)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_SCTP:
|
||||
return xtlength_layer7_sctp(length, skb, offset);
|
||||
default:
|
||||
return xtlength_layer5(length, skb, proto, offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* llayer4_proto - figure out the L4 protocol in an IPv6 packet
|
||||
* @skb: skb pointer
|
||||
* @offset: position at which L4 starts (equal to 'protoff' in IPv4 code)
|
||||
* @hotdrop: hotdrop pointer
|
||||
*
|
||||
* Searches for a recognized L4 header. On success, fills in @offset and
|
||||
* returns the protocol number. If not found, %NEXTHDR_MAX is returned.
|
||||
* On error, @hotdrop is set.
|
||||
*/
|
||||
static unsigned int
|
||||
llayer4_proto(const struct sk_buff *skb, unsigned int *offset, bool *hotdrop)
|
||||
{
|
||||
/*
|
||||
* Do encapsulation first so that %NEXTHDR_TCP does not hit the TCP
|
||||
* part in an IPv6-in-IPv6 encapsulation.
|
||||
*/
|
||||
static const unsigned int types[] =
|
||||
{IPPROTO_IPV6, IPPROTO_IPIP, IPPROTO_ESP, IPPROTO_AH,
|
||||
IPPROTO_ICMP, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_UDPLITE,
|
||||
IPPROTO_SCTP, IPPROTO_DCCP};
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(types); ++i) {
|
||||
err = ipv6_find_hdr(skb, offset, types[i], NULL);
|
||||
if (err >= 0)
|
||||
return types[i];
|
||||
if (err != -ENOENT) {
|
||||
*hotdrop = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NEXTHDR_MAX;
|
||||
}
|
||||
|
||||
static bool
|
||||
length2_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = par->matchinfo;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
unsigned int len = 0;
|
||||
bool hit = true;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
len = ntohs(iph->tot_len);
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
len = ntohs(iph->tot_len) - par->thoff;
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
hit = xtlength_layer5(&len, skb, iph->protocol, par->thoff);
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
hit = xtlength_layer7(&len, skb, iph->protocol, par->thoff);
|
||||
if (!hit)
|
||||
return false;
|
||||
|
||||
return (len >= info->min && len <= info->max) ^
|
||||
!!(info->flags & XT_LENGTH_INVERT);
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static bool
|
||||
length2_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = par->matchinfo;
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
unsigned int len = 0, l4proto;
|
||||
unsigned int thoff = par->thoff;
|
||||
bool hit = true;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3) {
|
||||
len = sizeof(struct ipv6hdr) + ntohs(iph->payload_len);
|
||||
} else {
|
||||
l4proto = llayer4_proto(skb, &thoff, par->hotdrop);
|
||||
if (l4proto == NEXTHDR_MAX)
|
||||
return false;
|
||||
if (info->flags & XT_LENGTH_LAYER4)
|
||||
len = skb->len - thoff;
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
hit = xtlength_layer5(&len, skb, l4proto, thoff);
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
hit = xtlength_layer7(&len, skb, l4proto, thoff);
|
||||
}
|
||||
if (!hit)
|
||||
return false;
|
||||
|
||||
return (len >= info->min && len <= info->max) ^
|
||||
!!(info->flags & XT_LENGTH_INVERT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct xt_match length2_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "length2",
|
||||
.revision = 2,
|
||||
.family = NFPROTO_IPV4,
|
||||
.match = length2_mt,
|
||||
.matchsize = sizeof(struct xt_length_mtinfo2),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#ifdef WITH_IPV6
|
||||
{
|
||||
.name = "length2",
|
||||
.revision = 2,
|
||||
.family = NFPROTO_IPV6,
|
||||
.match = length2_mt6,
|
||||
.matchsize = sizeof(struct xt_length_mtinfo2),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init length2_mt_init(void)
|
||||
{
|
||||
return xt_register_matches(length2_mt_reg, ARRAY_SIZE(length2_mt_reg));
|
||||
}
|
||||
|
||||
static void __exit length2_mt_exit(void)
|
||||
{
|
||||
xt_unregister_matches(length2_mt_reg, ARRAY_SIZE(length2_mt_reg));
|
||||
}
|
||||
|
||||
module_init(length2_mt_init);
|
||||
module_exit(length2_mt_exit);
|
22
extensions/xt_length2.h
Normal file
22
extensions/xt_length2.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _LINUX_NETFILTER_XT_LENGTH2_H
|
||||
#define _LINUX_NETFILTER_XT_LENGTH2_H
|
||||
|
||||
enum {
|
||||
XT_LENGTH_INVERT = 1 << 0,
|
||||
|
||||
/* IP header plus payload */
|
||||
XT_LENGTH_LAYER3 = 1 << 1,
|
||||
/* Strip IP header: */
|
||||
XT_LENGTH_LAYER4 = 1 << 2,
|
||||
/* Strip TCP/UDP/etc. header */
|
||||
XT_LENGTH_LAYER5 = 1 << 3,
|
||||
/* TCP/UDP/SCTP payload */
|
||||
XT_LENGTH_LAYER7 = 1 << 4,
|
||||
};
|
||||
|
||||
struct xt_length_mtinfo2 {
|
||||
u_int32_t min, max;
|
||||
u_int16_t flags;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_NETFILTER_XT_LENGTH2_H */
|
2
m4/.gitignore
vendored
Normal file
2
m4/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/libtool.m4
|
||||
/lt*.m4
|
1
mconfig
1
mconfig
@@ -14,5 +14,6 @@ build_fuzzy=m
|
||||
build_geoip=m
|
||||
build_ipp2p=m
|
||||
build_ipset=m
|
||||
build_length2=m
|
||||
build_portscan=m
|
||||
build_quota2=m
|
||||
|
@@ -1,9 +1,9 @@
|
||||
.TH xtables\-addons 8 2008\-11\-18
|
||||
.SH NAME
|
||||
.TH xtables\-addons 8 "v1.9 (2009\-01\-30)" "" "v1.9 (2009\-01\-30)"
|
||||
.SH Name
|
||||
Xtables\-addons - additional extensions for iptables, ip6tables, etc.
|
||||
.SH TARGETS
|
||||
.SH Targets
|
||||
.\" @TARGET@
|
||||
.SH MATCHES
|
||||
.SH Matches
|
||||
.\" @MATCHES@
|
||||
.SH "SEE ALSO"
|
||||
\fBiptables\fP(8), \fBip6tables\fP(8)
|
||||
|
Reference in New Issue
Block a user