/*
* The HAVE_SETUP_TUNNEL variable is used to determine whether absense of
- * the -t option leads to an error, or to an attempt to setup the tunnel.
+ * the -d option leads to an error, or to an attempt to setup the tunnel.
* The setup_tunnel() function used for that is defined per platform, such
- * as for LINUX. Remember to maintain the manpage's optionality for -t.
+ * as for LINUX. Remember to maintain the manpage's optionality for -d.
*/
#undef HAVE_SETUP_TUNNEL
struct option long_opt [] = {
{ "v4server", 1, NULL, 's' },
- { "tundev", 1, NULL, 't' },
- { "default-route", 0, NULL, 'd' },
+ { "tundev", 1, NULL, 'd' },
+ { "default-route", 0, NULL, 'r' },
{ "listen", 1, NULL, 'l' },
{ "port", 1, NULL, 'p' },
- { "radius-multicast", 1, NULL, 'r' },
+ { "ttl", 1, NULL, 't' },
{ "foreground", 0, NULL, 'f' },
{ "fork-not", 0, NULL, 'f' },
{ "keepalive", 1, NULL, 'k' },
break;
}
break;
- case 't':
+ case 'd':
if (v6sox != -1) {
ok = 0;
- fprintf (stderr, "%s: Multiple -t arguments are not permitted\n", program);
+ fprintf (stderr, "%s: Multiple -d arguments are not permitted\n", program);
break;
}
v6sox = open (optarg, O_RDWR);
break;
}
break;
- case 'd':
+ case 'r':
if (default_route) {
fprintf (stderr, "%s: You can only request default route setup once\n", program);
exit (1);
}
log_to_stderr = true;
break;
- case 'r':
+ case 't':
if (v4ttl_mcast != -1) {
- fprintf (stderr, "%s: You can set the radius for multicast once\n", program);
+ fprintf (stderr, "%s: You can set the ttl for multicast once\n", program);
exit (1);
}
char *zero;
}
if (help) {
#ifdef HAVE_SETUP_TUNNEL
- fprintf (stderr, "Usage: %s [-d] [-t /dev/tunX]\n %s -h\n", program, program);
+ fprintf (stderr, "Usage: %s [-r] [-d /dev/tunX]\n %s -h\n", program, program);
#else
- fprintf (stderr, "Usage: %s [-d] -t /dev/tunX\n %s -h\n", program, program);
+ fprintf (stderr, "Usage: %s [-r] -d /dev/tunX\n %s -h\n", program, program);
#endif
return 0;
}
#ifdef HAVE_SETUP_TUNNEL
if (v6sox == -1) {
if (geteuid () != 0) {
- fprintf (stderr, "%s: You should be root, or use -t to specify an accessible tunnel device\n", program);
+ fprintf (stderr, "%s: You should be root, or use -d to specify an accessible tunnel device\n", program);
return false;
} else {
return setup_tunnel ();
}
#else /* ! HAVE_SETUP_TUNNEL */
if (v6sox == -1) {
- fprintf (stderr, "%s: You must specify a tunnel device with -t that is accessible to you\n", program);
+ fprintf (stderr, "%s: You must specify a tunnel device with -d that is accessible to you\n", program);
return 0;
}
#endif /* HAVE_SETUP_TUNNEL */
6bed4client \- client-side daemon for instant-on IPv6 service
.SH SYNOPSYS
.B 6bed4client
-[\fB\-t\fR \fI/dev/tunX\fR] [\fB\-d\fR] [\fB\-f\fR] [\fB\-l\fR \fIv4addr\fR] [\fB\-p\fR \fIport\fR] [\fB\-r\fR \fIhops\fR] [\fB-s \fIv4addr\fR]
+[\fB\-d\fR \fI/dev/tunX\fR] [\fB\-r\fR] [\fB\-f\fR] [\fB\-l\fR \fIv4addr\fR] [\fB\-p\fR \fIport\fR] [\fB\-t\fR \fIhops\fR] [\fB-s \fIv4addr\fR]
.PP
.B 6bed4client
[\fB\-h\fR]
forwarded port.
.SH OPTIONS
.TP
-\fB\-t\fR \fI/dev/tunX\fR
+\fB\-d\fR \fI/dev/tunX\fR
.TP
\fB\-\-tundev\fR \fI/dev/tunX\fR
Instead of creating a tunnel for the duration that \fB6bed4server\fR runs,
non-root users to run \fB6bed4server\fR. All that is required is acccess to
the tunnel device by the user that runs \fB6bed4server\fR. Optional on Linux.
.TP
-\fB\-d\fR
+\fB\-r\fR
.TP
\fB\-\-default\-route\fR
Create a default route through the 6bed4 interface. This means that the
the central infrastructure. The default is \fB\-\-keepalive 30,3\fR
and may be automatically determined in future versions.
.TP
-\fB\-r\fR \fIhops\fR
+\fB\-t\fR \fIhops\fR
.TP
-\fB\-\-radius\fR \fIhops\fR
+\fB\-\-ttl\fR \fIhops\fR
Set the multicast radius to the given number of hops, the default being 1.
This number is used as the TTL on multicast messages, thereby determining
whether routers are permitted to forward these packets. The value 0
Whenever possible, 6bed4 connections are connected directly over the locally
attached network. This optimises the traffic by not passing it through an
external router. But it also implies trust in the peers on a local network;
-for this reason, it is possible to set \fB\-\-radius 0\fR and thereby
+for this reason, it is possible to set \fB\-\-ttl 0\fR and thereby
disable the attempts to find peers locally.
.PP
The mechanism used to find peers locally is through multicast. It is
response through Neighbor Advertisement, in both cases encapsulated in
UDP and IPv4.
.PP
-The default setting \fB\-\-radius 1\fR works only on locally attached
+The default setting \fB\-\-ttl 1\fR works only on locally attached
subnets. This is generally safe, as this network is normally unfiltered.
In places where filtering is applied within a subnet, the administrative
staff should be prepared to stop confusion of network nodes; in case of
-6bed4, this means setting \fB\-\-radius 0\fR to avoid relying on an open
+6bed4, this means setting \fB\-\-ttl 0\fR to avoid relying on an open
locally attached subnet. This setting implies that the daemon does not
listen for incoming queries over multicast. The standards specify that
multicast support is optional, so this does not break any standards.
.PP
-Settings of \fB\-\-radius 2\fR and beyond are more dangerous; it could
+Settings of \fB\-\-ttl 2\fR and beyond are more dangerous; it could
lead to asymmetric routes if not properly configured on a network. The
problem of asymmetric routes being that one half might go through a
hole in NAT, which closes when traffic does not flow through bidirectionally.
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
+#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
+#ifndef BE_SO_LAME_TO_SUPPRESS_SCTP
+#include <linux/sctp.h>
+#endif
+
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_ether.h>
/*
* The HAVE_SETUP_TUNNEL variable is used to determine whether absense of
- * the -t option leads to an error, or to an attempt to setup the tunnel.
+ * the -d option leads to an error, or to an attempt to setup the tunnel.
* The setup_tunnel() function used for that is defined per platform, such
- * as for LINUX. Remember to maintain the manpage's optionality for -t.
+ * as for LINUX. Remember to maintain the manpage's optionality for -d.
*/
#undef HAVE_SETUP_TUNNEL
struct {
struct ip6_hdr v6hdr;
struct icmp6_hdr v6icmphdr;
+#ifndef BE_SO_LAME_TO_SUPPRESS_SCTP
+ struct sctphdr v6sctphdr;
+#endif
+ struct tcphdr v6tcphdr ;
+ struct udphdr v6udphdr ;
} ndata;
} udata;
} v4data6;
#define v4v6icmpcode ( v4data6.udata.ndata.v6icmphdr.icmp6_code)
#define v4v6icmpcksum ( v4data6.udata.ndata.v6icmphdr.icmp6_cksum)
+#define v4v6sctpsrcport ( v4data6.udata.ndata.v6sctphdr.source)
+#define v4v6sctpdstport ( v4data6.udata.ndata.v6sctphdr.dest)
+
+#define v4v6tcpsrcport ( v4data6.udata.ndata.v6tcphdr.source)
+#define v4v6tcpdstport ( v4data6.udata.ndata.v6tcphdr.dest)
+
+#define v4v6udpsrcport ( v4data6.udata.ndata.v6udphdr.source)
+#define v4v6udpdstport ( v4data6.udata.ndata.v6udphdr.dest)
+
#define v4ngbsoltarget (&v4data6.udata.ndata.v6icmphdr.icmp6_data8 [4])
};
+
+#ifndef MAXNUM_MASQHOST
+#define MAXNUM_MASQHOST 4
+#endif
+
+uint16_t num_masqhost = 0;
+uint8_t masqhost [MAXNUM_MASQHOST][16];
+
+// ports for 's', 't', 'u' -- SCTP, TCP, UDP have increasing numbers
+
+#ifndef MAXNUM_PORTPAIRS
+#define MAXNUM_PORTPAIRS 10
+#endif
+
+// masqportpairs holds triples <lowport,highport,masqhostnr>
+uint16_t num_masqportpairs [3] = { 0, 0, 0 };
+uint16_t masqportpairs [3][3*MAXNUM_PORTPAIRS];
+
+
+
/*
*
* Driver routines
#define is_local_override(_) false
#endif
+
/*
* Test if the provided IPv6 address matches the prefix used for 6bed4.
*TODO: This is oversimplistic, it only cares for the Hetzner /64
}
+
+/*
+ * Given a protocol and a port number, locate the masqhost that would match.
+ * The protocol is 0 for SCTP, 1 for TCP, 2 for UDP (alphabetic sequence).
+ * Returns a pointer to the address or NULL if not found.
+ */
+uint8_t *protoport2masqhost (uint8_t proto, uint16_t port) {
+ //NOTUSED// TODO:IMPLEMENT
+ return NULL;
+}
+
+
+
/*
* Major packet processing functions
*/
* checksum calculations.
*/
void handle_4to6_plain_unicast (ssize_t v4datalen) {
+ //
+ // Masquerade the 6bed4router when addressing a configured port (range)
+ // but only when the destination address is the client's 6bed4router
+ if ((v4dst6->s6_addr [15] == 0x00)
+ && (v4dst6->s6_addr [14] & 0x3f == 0x00)
+ && (memcmp (v4dst6, v4src6, 14) == 0)) {
+ uint16_t *portpairs = NULL;
+ uint16_t numpairs = 0;
+ uint16_t port;
+ switch (v4v6nexthdr) {
+#ifndef BE_SO_LAME_TO_SUPPRESS_SCTP
+ case IPPROTO_SCTP:
+ portpairs = masqportpairs [0]; // 's'
+ numpairs = num_masqportpairs [0];
+ port = ntohs (v4v6srcport);
+ break;
+#endif
+ case IPPROTO_TCP:
+ portpairs = masqportpairs [1]; // 't'
+ numpairs = num_masqportpairs [1];
+ port = v4v6tcpsrcport;
+ break;
+ case IPPROTO_UDP:
+ portpairs = masqportpairs [2]; // 'u'
+ numpairs = num_masqportpairs [2];
+ port = v4v6udpsrcport;
+ break;
+ default:
+ break;
+ }
+ while (numpairs-- > 0) {
+ if ((port >= portpairs [0]) && (port <= portpairs [1])) {
+ //
+ // Replace masqueraded address by 6bed4router's
+ memcpy (v4dst6, masqhost [portpairs [2]], 16);
+ //
+ // Stop further attempts to masquerade
+ }
+ portpairs += 2;
+ }
+ }
+ //
+ // Relay the message to an IPv6 recipient on the native IPv6 side
printf ("Writing IPv6, result = %zd\n",
write (v6sox, &v4data6, sizeof (struct tun_pi) + v4datalen));
}
* port, then package it as a tunnel message and forward it to IPv4:port.
*/
void handle_6to4 (void) {
+ uint16_t mqh;
//
// Receive the IPv6 package and ensure a consistent size
size_t rawlen = read (v6sox, &v6data6, sizeof (v6data6));
}
printf ("Received plain unicast IPv6 data, flags=0x%04x, proto=0x%04x\n", v6tuncmd.flags, v6tuncmd.proto);
//
+ // Replace masqueraded addresses configured with -m and its default ::1
+ //TODO// Better use the port number to find the find the masqhost
+ for (mqh=0; mqh<num_masqhost; mqh++) {
+ if (memcmp (v6src6, masqhost [mqh], 16) == 0) {
+printf ("Masqueraded sender address in 6to4 set to the client's 6bed4router address\n");
+ memcpy (v6src6, v6dst6, 15);
+ v6src6->s6_addr [15] &= 0xc0;
+ v6src6->s6_addr [16] = 0x00;
+ break;
+ }
+ }
+ //
// Ensure that the incoming IPv6 address is properly formatted
// Note that this avoids access to ::1/128, fe80::/10, fec0::/10
#ifndef TODO_PERMIT_BOUNCE_FOR_32BIT_PREFIX
/* Option descriptive data structures */
-char *short_opt = "l:L:t:h";
+char *short_opt = "l:L:d:ht:u:s:m:";
struct option long_opt [] = {
{ "v4listen", 1, NULL, 'l' },
{ "v6prefix", 1, NULL, 'L' },
- { "tundev", 1, NULL, 't' },
+ { "tundev", 1, NULL, 'd' },
{ "help", 0, NULL, 'h' },
+ { "tcp", 1, NULL, 't' },
+ { "udp", 1, NULL, 'u' },
+ { "sctp", 1, NULL, 's' },
+ { "masqhost", 1, NULL, 'm' },
+ // { "fallback4", 1 NULL, 'f' },
+ // { "fallback6", 1, NULL, 'F' },
{ NULL, 0, NULL, 0 } /* Array termination */
};
int ok = 1;
int help = (argc == 1);
int done = 0;
+ int opt;
while (!done) {
- switch (getopt_long (argc, argv, short_opt, long_opt, NULL)) {
+ switch (opt = getopt_long (argc, argv, short_opt, long_opt, NULL)) {
case -1:
done = 1;
if (optind != argc) {
break;
}
break;
- case 't':
+ case 'd':
if (v6sox != -1) {
ok = 0;
- fprintf (stderr, "%s: Multiple -t arguments are not permitted\n", program);
+ fprintf (stderr, "%s: Multiple -d arguments are not permitted\n", program);
break;
}
v6sox = open (optarg, O_RDWR);
break;
}
break;
+ case 's':
+ case 't':
+ case 'u':
+ // Masqueraded port (range) for SCTP, TCP, UDP
+ //TODO// Should we support ICMPv6 as well? [honeypots]
+ if (num_masqhost == 0) {
+ inet_pton (AF_INET6, "::1", masqhost [0]);
+ num_masqhost = 1;
+ }
+ // Temporary variables in local scope
+ {
+ unsigned long fromport, toport;
+ uint16_t *portpairs;
+ errno = 0;
+ if (*optarg != ':') {
+ fromport = strtoul (optarg, &optarg, 10);
+ } else {
+ fromport = 1;
+ }
+ if (*optarg != ':') {
+ toport = fromport;
+ } else if (*++optarg) {
+ toport = strtoul (optarg, &optarg, 10);
+ } else {
+ toport = 65535;
+ }
+ if (errno || *optarg) {
+ fprintf (stderr, "%s: Failed to parse port or port:port\n", program);
+ ok = 0;
+ break;
+ }
+ if ((fromport < 1) || (fromport > toport) || (toport > 65535)) {
+ fprintf (stderr, "%s: Invalid port or port range\n", program);
+ ok = 0;
+ break;
+ }
+ if (++num_masqportpairs [opt-'s'] >= MAXNUM_PORTPAIRS) {
+ fprintf (stderr, "%s: You cannot define so many ports / port pairs\n", program);
+ ok = 0;
+ break;
+ }
+ portpairs = &masqportpairs [opt-'s'][3*(num_masqportpairs [opt-'s']-1)];
+ portpairs [0] = fromport;
+ portpairs [1] = toport;
+ portpairs [2] = num_masqhost-1;
+ }
+ break;
+ case 'm':
+ // Masqueraded host for TCP, UDP, SCTP (default is ::1)
+ if (++num_masqhost >= MAXNUM_MASQHOST) {
+ fprintf (stderr, "%s: No more than %d masquering hosts can be specified\n", program, MAXNUM_MASQHOST);
+ ok = 0;
+ break;
+ }
+ if (inet_pton (AF_INET6, optarg, masqhost [num_masqhost]) != 1) {
+ fprintf (stderr, "%s: Unsupported masquerading host \"%s\"\n", program, optarg);
+ ok = 0;
+ break;
+ }
+ num_masqhost++;
+ ok = 0; //TODO:IMPLEMENT//
+ help = 1;
+ break;
+ // case 'f':
+ // case 'F':
+ // // Fallback addresses for IPv4, IPv6
+ // ok = 0; //TODO:IMPLEMENT//
+ // help = 1;
+ // break;
default:
ok = 0;
- help = 1;
/* continue into 'h' to produce usage information */
case 'h':
help = 1;
}
if (help) {
#ifdef HAVE_SETUP_TUNNEL
- fprintf (stderr, "Usage: %s [-t /dev/tunX] -l <v4server> -L <v6prefix>/64\n %s -h\n", program, program);
+ fprintf (stderr, "Usage: %s [-d /dev/tunX] -l <v4server> -L <v6prefix>/64\n %s -h\n", program, program);
+ fprintf (stderr, "\tUse -s|-t|-u to masquerade a port (range) to last -m host or ::1\n");
#else
- fprintf (stderr, "Usage: %s -t /dev/tunX -l <v4server> -L <v6prefix>/64\n %s -h\n", program, program);
+ fprintf (stderr, "Usage: %s -d /dev/tunX -l <v4server> -L <v6prefix>/64\n %s -h\n", program, program);
+ fprintf (stderr, "\tUse -s|-t|-u to masquerade a port (range) to last -m host of ::1\n");
#endif
return ok;
}
#ifdef HAVE_SETUP_TUNNEL
if (v6sox == -1) {
if (geteuid () != 0) {
- fprintf (stderr, "%s: You should be root, or use -t to specify an accessible tunnel device\n", program);
+ fprintf (stderr, "%s: You should be root, or use -d to specify an accessible tunnel device\n", program);
return 0;
}
ok = setup_tunnel ();
}
#else /* ! HAVE_SETUP_TUNNEL */
if (v6sox == -1) {
- fprintf (stderr, "%s: You must specify a tunnel device with -t that is accessible to you\n", program);
+ fprintf (stderr, "%s: You must specify a tunnel device with -d that is accessible to you\n", program);
return 0;
}
#endif /* HAVE_SETUP_TUNNEL */
6bed4router \- server-side daemon for 6bed4 service
.SH SYNOPSYS
.B 6bed4router
-[\fB\-t\fR \fI/dev/tunX\fR] \fB\-l\fR \fIv4addr\fR \fB\-L\fR \fIv6prefix/64\fR
+[\fB\-d\fR \fI/dev/tunX\fR] \fB\-l\fR \fIv4addr\fR \fB\-L\fR \fIv6prefix/64\fR [\fB\-m\fR/\fBs\fR/\fBt\fR/\fBu\fR \fI...\fR]
.PP
.B 6bed4router
[\fB\-h\fR]
.SH DESCRIPTION
.PP
Through a \fB6bed4router\fR daemon, it is possible to make a small range of IPv6
-addresses available to IPv4-only users. This means that even an IPv4-only
+addresses available to a potentially large number of IPv4-only users. This means that even an IPv4-only
network can host IPv6-only applications, as long as they can fall back on
a tunnel based on this profile.
.PP
-These tunnels are primarily intended for embedded devices, to assist them
-in instant changeover from being IPv4-only to being IPv6-only. Given the
+Use the \fB6bed4router\fR on nodes that support \fB6bed4peer\fR clients
+anywhere; instead, use the \fB6bed4node\fR on nodes that want to provide
+native IPv6 on a local network.
+.PP
+These tunnels are intended for mobile and embedded devices, to assist them
+in instant changeover from being IPv4-only to eventually being IPv6-only.
+Given the
restricted resources in embedded applications, this is likely to improve
the speed of transitioning to IPv6. To avoid cluttered access, these
tunnels should be reserved for resource-hampered devices. For routers,
on what is tossed at it.
.SH OPTIONS
.TP
-\fB\-t\fR \fI/dev/tunX\fR
+\fB\-d\fR \fI/dev/tunX\fR
.TP
\fB\-\-tundev\fR \fI/dev/tunX\fR
Instead of creating a tunnel for the duration that \fB6bed4router\fR runs,
See ADDRESS FORMAT below for an explanation of the lower half of
the IPv6 addresses. Required.
.IP
-If no \fB\-t\fR option is given, a tunnel will be created for the time that
+If no \fB\-d\fR option is given, a tunnel will be created for the time that
\fB6bed4router\fR is running, and the \fIv6prefix/64\fR is used as a router address
on that interface. Routing table entries will not be setup by \fB6bed4router\fR,
nor will the general ablity to forward IPv6 traffic.
.TP
+\fB\-m\fR \fIv6addr\fR
+.TP
+\fB\-\-masqhost\fR \fIv6addr\fR
+Use the given IPv6 address as the target for masqueraded operation. This
+means that any ports setup with \fB\-\-sctp\fR, \fB\-\-tcp\fR or \fB\-\-udp\fR
+are forwarded
+to this address when addressed on the client's idea of the 6bed4 router
+address. Note that the router only uses a few ICMPv6 messages, so the use
+of these additional ports can benefit various applications, ranging from
+authentication services to honeypots.
+.TP
+\fB\-s\fR \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB\-t\fR \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB\-u\fR \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB\-sctp\fR \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB\-tcp\fR \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB\-udp\fR \fIport\fR[\fB:\fIport\fR]
+Apply the masquerading port or port range for SCTP, TCP or UDP to the
+masquerading host set by the last preceding \fB\-\-masqhost\fR option,
+or use \fB::1\fR
+if none was set yet. Ports that have been previously bound will not make it,
+so it is possible to first relay a port with \fB\-t 22\fR to a service and
+then pass the rest to a honeypot with \fB\-t 1:65535\fR.
+.TP
\fB\-h\fR
.TP
\fB\-\-help\fR