Started to implement add_pinhole() for netfilter (linux)

This commit is contained in:
Thomas Bernard 2012-04-26 16:08:39 +02:00
parent d9cb61b124
commit 0440f0b8a7
17 changed files with 329 additions and 17 deletions

View File

@ -1,9 +1,16 @@
$Id: Changelog.txt,v 1.274 2012/04/25 22:26:03 nanard Exp $
$Id: Changelog.txt,v 1.275 2012/04/26 14:01:15 nanard Exp $
2012/04/26:
Started to implement add_pinhole() for netfilter (linux)
2012/04/25:
Fixed a bug in upnphttp that happened when POST is received in several
recv() calls and realloc() is called so the buffer used is moved.
2012/04/23:
Implement CheckPinholeWorking GetPinholePackets. WANIPv6FirewallControl
UpdatePinhole still to be done. And also netfilter/ipf/ipfw versions
2012/04/20:
Enough WANIPv6FirewallControl is implemented on pf so that AddPinhole() and
DeletePinhole() works !

View File

@ -1,4 +1,4 @@
# $Id: Makefile.linux,v 1.64 2012/04/20 12:54:01 nanard Exp $
# $Id: Makefile.linux,v 1.65 2012/04/24 22:41:52 nanard Exp $
# MiniUPnP project
# (c) 2006-2012 Thomas Bernard
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -40,7 +40,7 @@ BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \
upnpevents.o upnputils.o getconnstatus.o
LNXOBJS = linux/getifstats.o linux/ifacewatcher.o
NETFILTEROBJS = netfilter/iptcrdr.o
NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o
ALLOBJS = $(BASEOBJS) $(LNXOBJS) $(NETFILTEROBJS)
@ -129,6 +129,8 @@ install: miniupnpd genuuid
$(INSTALL) -d $(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_init.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/iptables_removeall.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_init.sh $(ETCINSTALLDIR)
$(INSTALL) netfilter/ip6tables_removeall.sh $(ETCINSTALLDIR)
$(INSTALL) --mode=0644 -b miniupnpd.conf $(ETCINSTALLDIR)
$(INSTALL) -d $(PREFIX)/etc/init.d
$(INSTALL) linux/miniupnpd.init.d.script $(PREFIX)/etc/init.d/miniupnpd

View File

@ -1,5 +1,5 @@
# $Id: Makefile,v 1.3 2011/03/02 16:04:23 nanard Exp $
CFLAGS?=-Wall -g -DDEBUG
# $Id: Makefile,v 1.6 2012/04/26 13:50:48 nanard Exp $
CFLAGS?=-Wall -g -D_GNU_SOURCE -DDEBUG -Wstrict-prototypes -Wdeclaration-after-statement -ansi
CC = gcc
#LIBS = -liptc
@ -26,7 +26,8 @@ LIBS = $(IPTABLESPATH)/libiptc/libiptc.a
endif
else
# check for system-wide iptables files. Test if iptables version >= 1.4.3
TEST := $(shell test -f /usr/include/iptables/internal.h && grep -q "\#define IPTABLES_VERSION" /usr/include/iptables/internal.h && echo 1)
#TEST := $(shell test -f /usr/include/iptables/internal.h && grep -q "\#define IPTABLES_VERSION" /usr/include/iptables/internal.h && echo 1)
TEST := $(shell test -f /usr/include/xtables.h && grep -q "XTABLES_VERSION_CODE" /usr/include/xtables.h && echo 1)
ifeq ($(TEST), 1)
CFLAGS := $(CFLAGS) -DIPTABLES_143
LIBS = -liptc
@ -37,15 +38,19 @@ endif
endif
endif
all: iptcrdr.o testiptcrdr
all: iptcrdr.o testiptcrdr iptpinhole.o testiptpinhole
clean:
$(RM) *.o testiptcrdr
$(RM) *.o testiptcrdr testiptpinhole
testiptcrdr: testiptcrdr.o iptcrdr.o upnpglobalvars.o $(LIBS)
testiptpinhole: testiptpinhole.o iptpinhole.o upnpglobalvars.o $(LIBS)
iptcrdr.o: iptcrdr.c iptcrdr.h
iptpinhole.o: iptpinhole.c iptpinhole.h
upnpglobalvars.o: ../upnpglobalvars.c ../upnpglobalvars.h
$(CC) -c -o $@ $<

View File

@ -0,0 +1,8 @@
#! /bin/sh
# $Id: ip6tables_display.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $
IPTABLES=/sbin/ip6tables
#display all chains relative to miniupnpd
$IPTABLES -v -n -t filter -L FORWARD
$IPTABLES -v -n -t filter -L MINIUPNPD

View File

@ -0,0 +1,7 @@
#! /bin/sh
# $Id: ip6tables_flush.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $
IPTABLES=/sbin/ip6tables
#flush all rules owned by miniupnpd
$IPTABLES -t filter -F MINIUPNPD

View File

@ -0,0 +1,12 @@
#! /bin/sh
# $Id: ip6tables_init.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $
IPTABLES=/sbin/ip6tables
#change this parameters :
EXTIF=eth0
#adding the MINIUPNPD chain for filter
$IPTABLES -t filter -N MINIUPNPD
#adding the rule to MINIUPNPD
$IPTABLES -t filter -A FORWARD -i $EXTIF ! -o $EXTIF -j MINIUPNPD

View File

@ -0,0 +1,22 @@
#! /bin/sh
# $Id: ip6tables_init_and_clean.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $
# Improved Miniupnpd iptables init script.
# Checks for state of filter before doing anything..
EXTIF=eth0
IPTABLES=/sbin/ip6tables
FDIRTY="`LC_ALL=C /sbin/ip6tables -t filter -L -n | grep 'MINIUPNPD' | awk '{printf $1}'`"
if [[ $FDIRTY = "MINIUPNPDChain" ]]; then
echo "Filter table dirty; Cleaning..."
$IPTABLES -t filter -F MINIUPNPD
elif [[ $FDIRTY = "Chain" ]]; then
echo "Dirty filter chain but no reference..? Fixsted."
$IPTABLES -t filter -I FORWARD 4 -i $EXTIF ! -o $EXTIF -j MINIUPNPD
$IPTABLES -t filter -F MINIUPNPD
else
echo "Filter table clean..initalizing.."
$IPTABLES -t filter -N MINIUPNPD
$IPTABLES -t filter -I FORWARD 4 -i $EXTIF ! -o $EXTIF -j MINIUPNPD
fi

View File

@ -0,0 +1,13 @@
#! /bin/sh
# $Id: ip6tables_removeall.sh,v 1.1 2012/04/24 22:13:41 nanard Exp $
IPTABLES=/sbin/ip6tables
#change this parameters :
EXTIF=eth0
#removing the MINIUPNPD chain for filter
$IPTABLES -t filter -F MINIUPNPD
#adding the rule to MINIUPNPD
$IPTABLES -t filter -D FORWARD -i $EXTIF ! -o $EXTIF -j MINIUPNPD
$IPTABLES -t filter -X MINIUPNPD

View File

@ -1,4 +1,4 @@
/* $Id: iptcrdr.c,v 1.47 2012/02/04 23:34:41 nanard Exp $ */
/* $Id: iptcrdr.c,v 1.48 2012/03/05 20:36:19 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard

View File

@ -1,4 +1,4 @@
/* $Id: iptcrdr.h,v 1.17 2011/06/04 15:44:58 nanard Exp $ */
/* $Id: iptcrdr.h,v 1.18 2012/03/05 20:36:20 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard

View File

@ -0,0 +1,172 @@
/* $Id: iptpinhole.c,v 1.2 2012/04/26 14:01:17 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <arpa/inet.h>
#include "../config.h"
#include "iptpinhole.h"
#include "../upnpglobalvars.h"
#ifdef ENABLE_6FC_SERVICE
#include <xtables.h>
#include <libiptc/libip6tc.h>
#include "tiny_nf_nat.h"
#define IP6TC_HANDLE struct ip6tc_handle *
static int next_uid = 1;
static struct ip6t_entry_match *
new_match(int proto, unsigned short sport, unsigned short dport)
{
struct ip6t_entry_match *match;
struct ip6t_tcp *info;
size_t size;
const char * name;
size = XT_ALIGN(sizeof(struct ip6t_entry_match))
+ XT_ALIGN(sizeof(struct ip6t_tcp));
match = calloc(1, size);
match->u.user.match_size = size;
switch(proto) {
case IPPROTO_TCP:
name = "tcp";
break;
case IPPROTO_UDP:
name = "udp";
break;
case IPPROTO_UDPLITE:
name = "udplite";
break;
default:
name = NULL;
}
if(name)
strncpy(match->u.user.name, name, sizeof(match->u.user.name));
else
syslog(LOG_WARNING, "no name for protocol %d", proto);
info = (struct ip6t_tcp *)match->data;
if(sport) {
info->spts[0] = sport; /* specified source port */
info->spts[1] = sport;
} else {
info->spts[0] = 0; /* all source ports */
info->spts[1] = 0xFFFF;
}
info->dpts[0] = dport; /* specified destination port */
info->dpts[1] = dport;
return match;
}
static struct ip6t_entry_target *
get_accept_target(void)
{
struct ip6t_entry_target * target = NULL;
size_t size;
size = XT_ALIGN(sizeof(struct ip6t_entry_target))
+ XT_ALIGN(sizeof(int));
target = calloc(1, size);
target->u.user.target_size = size;
strncpy(target->u.user.name, "ACCEPT", sizeof(target->u.user.name));
return target;
}
static int
ip6tc_init_verify_append(const char * table,
const char * chain,
struct ip6t_entry * e)
{
IP6TC_HANDLE h;
h = ip6tc_init(table);
if(!h) {
syslog(LOG_ERR, "ip6tc_init error : %s", ip6tc_strerror(errno));
return -1;
}
if(!ip6tc_is_chain(chain, h)) {
syslog(LOG_ERR, "chain %s not found", chain);
goto error;
}
if(!ip6tc_append_entry(chain, e, h)) {
syslog(LOG_ERR, "ip6tc_append_entry() error : %s", ip6tc_strerror(errno));
goto error;
}
if(!ip6tc_commit(h)) {
syslog(LOG_ERR, "ip6tc_commit() error : %s", ip6tc_strerror(errno));
goto error;
}
return 0; /* ok */
error:
ip6tc_free(h);
return -1;
}
/*
ip6tables -I %s %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j ACCEPT
ip6tables -I %s %d -p %s -i %s --sport %hu -d %s --dport %hu -j ACCEPT
miniupnpd_forward_chain, line_number, proto, ext_if_name, raddr, rport, iaddr, iport
ip6tables -t raw -I PREROUTING %d -p %s -i %s -s %s --sport %hu -d %s --dport %hu -j TRACE
ip6tables -t raw -I PREROUTING %d -p %s -i %s --sport %hu -d %s --dport %hu -j TRACE
*/
int add_pinhole(const char * ifname,
const char * rem_host, unsigned short rem_port,
const char * int_client, unsigned short int_port,
int proto)
{
int uid;
struct ip6t_entry * e;
struct ip6t_entry_match *match = NULL;
struct ip6t_entry_target *target = NULL;
e = calloc(1, sizeof(struct ip6t_entry));
e->ipv6.proto = proto;
if(ifname)
strncpy(e->ipv6.iniface, ifname, IFNAMSIZ);
if(rem_host) {
inet_pton(AF_INET6, rem_host, &e->ipv6.src);
memset(&e->ipv6.smsk, 0xff, sizeof(e->ipv6.smsk));
}
inet_pton(AF_INET6, int_client, &e->ipv6.dst);
memset(&e->ipv6.dmsk, 0xff, sizeof(e->ipv6.dmsk));
/*e->nfcache = NFC_IP_DST_PT;*/
/*e->nfcache |= NFC_UNKNOWN;*/
match = new_match(proto, rem_port, int_port);
target = get_accept_target();
e = realloc(e, sizeof(struct ip6t_entry)
+ match->u.match_size
+ target->u.target_size);
memcpy(e->elems, match, match->u.match_size);
memcpy(e->elems + match->u.match_size, target, target->u.target_size);
e->target_offset = sizeof(struct ip6t_entry)
+ match->u.match_size;
e->next_offset = sizeof(struct ip6t_entry)
+ match->u.match_size
+ target->u.target_size;
free(match);
free(target);
if(ip6tc_init_verify_append("filter", miniupnpd_v6_filter_chain, e) < 0) {
free(e);
return -1;
}
free(e);
uid = next_uid;
next_uid++;
return uid;
}
#endif

View File

@ -0,0 +1,17 @@
/* $Id: iptpinhole.h,v 1.2 2012/04/26 14:01:17 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#ifndef __IPTPINHOLE_H__
#define __IPTPINHOLE_H__
#ifdef ENABLE_6FC_SERVICE
int add_pinhole(const char * ifname,
const char * rem_host, unsigned short rem_port,
const char * int_client, unsigned short int_port,
int proto);
#endif
#endif

View File

@ -1,7 +1,7 @@
/* $Id: testiptcrdr.c,v 1.16 2011/03/02 16:04:23 nanard Exp $ */
/* $Id: testiptcrdr.c,v 1.18 2012/04/24 22:41:53 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2011 Thomas Bernard
* (c) 2006-2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
@ -11,6 +11,7 @@
#include <syslog.h>
#include "iptcrdr.h"
#include "../commonrdr.h"
#ifndef PRIu64
#define PRIu64 "llu"
@ -29,21 +30,29 @@ main(int argc, char ** argv)
eport = (unsigned short)atoi(argv[1]);
iaddr = argv[2];
iport = (unsigned short)atoi(argv[3]);
#if 0
printf("trying to redirect port %hu to %s:%hu\n", eport, iaddr, iport);
if(addnatrule(IPPROTO_TCP, eport, iaddr, iport) < 0)
return -1;
if(add_filter_rule(IPPROTO_TCP, iaddr, iport) < 0)
return -1;
#endif
/* test */
{
unsigned short p1, p2;
char addr[16];
int proto2;
char desc[256];
char rhost[256];
unsigned int timestamp;
u_int64_t packets, bytes;
desc[0] = '\0';
if(get_redirect_rule_by_index(0, "", &p1, addr, sizeof(addr),
&p2, &proto2, desc, sizeof(desc),
if(get_redirect_rule_by_index(0, "", &p1,
addr, sizeof(addr), &p2,
&proto2, desc, sizeof(desc),
rhost, sizeof(rhost),
&timestamp,
&packets, &bytes) < 0)
{
printf("rule not found\n");

View File

@ -0,0 +1,27 @@
/* $Id: testiptpinhole.c,v 1.1 2012/04/26 13:50:48 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2012 Thomas Bernard
* This software is subject to the conditions detailed
* in the LICENCE file provided within the distribution */
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <syslog.h>
#include "../config.h"
#include "iptpinhole.h"
#include "../commonrdr.h"
int main(int argc, char * * argv)
{
int uid;
openlog("testiptpinhole", LOG_PERROR|LOG_CONS, LOG_LOCAL0);
uid = add_pinhole("eth0", NULL, 0, "ff::123", 54321, IPPROTO_TCP);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: upnpglobalvars.c,v 1.27 2012/02/04 23:05:21 nanard Exp $ */
/* $Id: upnpglobalvars.c,v 1.29 2012/04/26 14:01:16 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -75,6 +75,10 @@ const char * tag = 0;
* and the filter table */
const char * miniupnpd_nat_chain = "MINIUPNPD";
const char * miniupnpd_forward_chain = "MINIUPNPD";
#ifdef ENABLE_6FC_SERVICE
const char * miniupnpd_v6_filter_chain = "MINIUPNPD";
#endif
#endif
#ifdef ENABLE_NFQUEUE
int nfqueue = -1;

View File

@ -1,4 +1,4 @@
/* $Id: upnpglobalvars.h,v 1.31 2012/02/04 23:05:21 nanard Exp $ */
/* $Id: upnpglobalvars.h,v 1.33 2012/04/26 14:01:16 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -94,6 +94,9 @@ extern const char * tag;
#ifdef USE_NETFILTER
extern const char * miniupnpd_nat_chain;
extern const char * miniupnpd_forward_chain;
#ifdef ENABLE_6FC_SERVICE
extern const char * miniupnpd_v6_filter_chain;
#endif
#endif
#ifdef ENABLE_NFQUEUE

View File

@ -1,4 +1,4 @@
/* $Id: upnpredirect.c,v 1.75 2012/04/23 22:36:57 nanard Exp $ */
/* $Id: upnpredirect.c,v 1.76 2012/04/26 14:01:16 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2012 Thomas Bernard
@ -24,6 +24,7 @@
#include "upnpevents.h"
#if defined(USE_NETFILTER)
#include "netfilter/iptcrdr.h"
#include "netfilter/iptpinhole.h"
#endif
#if defined(USE_PF)
#include "pf/obsdrdr.h"
@ -667,6 +668,9 @@ upnp_add_inboundpinhole(const char * raddr,
#ifdef USE_PF
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto, timestamp);
return 1;
#elif USE_NETFILTER
*uid = add_pinhole (0/*ext_if_name*/, raddr, rport, iaddr, iport, proto);
return 1;
#else
return -42; /* not implemented */
#endif