Hi bish,
attached you have a new patch:
- this time against the CVS HEAD
- with config file option instead of parameter
- with compile switch; still TODO, but I would better let you do that,
move "#define ENABLE_NAT_HACK" out of vtun.h, into configuration.
Cheers,
-Dragos
bishop wrote:
Hi Dragos,
I think your patch has definite value, as it can help overcome a
potential problem when traversing firewalls. There is value in keeping
this code in the codebase, so that further development won't prevent you
from using this method to navigate this somewhat broken kind of NAT.
I worry about the occasional 'security researcher' the kind who finds a
copy of vtun, intentionally compiles it and enables all the risky code
possible, and then publishes an assessment of this build as if it were
common or default. Anything risky we put into vtun, I think, should
require a compiler flag to enable. That way we can protect the unwary
and remind others that by default there's no reduction in security.
I think the global variable is mostly okay. There's already various
switches for log level or whatnot.
The way the UDP connection is set up also worries me. I think that's
just a concern over the way it's already being done now, though, and
nothing to do with your patch. I'd feel a lot better if the delayed UDP
start was a per-profile option (like proto or persist) so that if we -D
NAT_HACK in the compilation, we can then say nat_hack=1 in the
vtund.conf and allow just one peer (client) to delay the UDP connection
set-up.
How do you feel about that?
- compile switch to enable the code
- vtund.conf option ; not a command-line option
- diff -u ;-)
What does everyone else think about this patch? Can we quiet the
security gibbons with a compile-time switch? has anyone else run into
this kind of a NAT setup, needed UDP and seen any other workarounds?
- bish
Dragos Vingarzan wrote:
Hi all,
first of all, thanx for the nice vtun!
Then I have a patch. I was using vtun over some UMTS connection and then
I hit a nasty NAT. Worked fine over TCP, of course, but the issue was
that the UDP stream was mapped by the NAT box to a different port. And I
really wanted to keep the UDP encapsulation (most of my packets would be
RTP and I do have packet-loss).
So vtun does the handshake but the the UDP socket is mapped to another
port on the NAT as the one that the client behind NAT indicated in the
handshake. The UDP connect happens with the parameters as the source of
the TCP packets and the indicated port in the handshake, which means
that the actual NATed UDP packets are dropped.
The idea, which seems to work, was to delay the connect until the first
packet is received and then use the real UDP from address. This of
course would not work if applied on both sides, so I added an extra
parameter ("-N" NAT hack) and a couple of global variables to
orchestrate the delayed connect of the UDP socket. I also disabled the
first Echo Request as there would be no destination port to send to
(this however could be worked around by using sendto() instead of write()).
Well, I hacked this quickly, so probably many things are not kosher with
the line of the project, but it should be enough to get the idea.
I am looking forward for feedback, even if you would completely reject
the patch.
Cheers,
-Dragos
------------------------------------------------------------------------
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
------------------------------------------------------------------------
_______________________________________________
VTun-devel mailing list
VTun-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vtun-devel
--
Best Regards,
Dragos Vingarzan
Index: linkfd.c
===================================================================
RCS file: /cvsroot/vtun/vtun/linkfd.c,v
retrieving revision 1.13
diff -u -r1.13 linkfd.c
--- linkfd.c 11 Dec 2006 07:55:06 -0000 1.13
+++ linkfd.c 18 Feb 2009 14:28:45 -0000
@@ -211,7 +211,9 @@
vtun_syslog(LOG_ERR,"Can't allocate buffer for the linker");
return 0;
}
-
+
+ /* because server can't send the first VTUN_ECHO_REQ as it would be probably disconnected */
+ if (!VTUN_USE_NAT_HACK(lfd_host))
proto_write(fd1, buf, VTUN_ECHO_REQ);
maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;
Index: vtund.conf
===================================================================
RCS file: /cvsroot/vtun/vtun/vtund.conf,v
retrieving revision 1.4
diff -u -r1.4 vtund.conf
--- vtund.conf 11 Dec 2006 07:55:06 -0000 1.4
+++ vtund.conf 18 Feb 2009 14:28:45 -0000
@@ -107,6 +107,22 @@
# This option is ignored by the client.
#
# -----------
+# nat_hack - tunnel side to delay the UDP socket connect.
+# 'client' - Enable the NAT hack on the client side.
+# 'server' - Enable the NAT hack on the server side.
+# 'no' - Disable the NAT hack on both sides (default).
+#
+# The side that the NAT hack is enabled on will have
+# delayed UDP socket connect. Enable only for the side
+# outside of the NAT (typically the server)!
+#
+# Setting 'client' on the server or 'server' on the
+# client is ignored.
+#
+# Please see the vtund.conf man page for more details
+# and security information.
+#
+# -----------
# persist - Persist mode.
# 'yes' - Reconnect to the server after connection
# termination.
Index: vtun.h
===================================================================
RCS file: /cvsroot/vtun/vtun/vtun.h,v
retrieving revision 1.12
diff -u -r1.12 vtun.h
--- vtun.h 11 Dec 2006 07:55:06 -0000 1.12
+++ vtun.h 18 Feb 2009 14:28:45 -0000
@@ -161,6 +161,19 @@
#define VTUN_STAT 0x1000
#define VTUN_PERSIST 0x2000
+/* Flags for the NAT hack with delayed UDP socket connect */
+#define VTUN_NAT_HACK_CLIENT 0x4000
+#define VTUN_NAT_HACK_SERVER 0x8000
+#define VTUN_NAT_HACK_MASK (VTUN_NAT_HACK_CLIENT | VTUN_NAT_HACK_SERVER)
+
+#define ENABLE_NAT_HACK
+
+#ifdef ENABLE_NAT_HACK
+ #define VTUN_USE_NAT_HACK(host) ((host)->flags & VTUN_NAT_HACK_MASK)
+#else
+ #define VTUN_USE_NAT_HACK(host) 0
+#endif
+
/* Constants and flags for VTun protocol */
#define VTUN_FRAME_SIZE 2048
#define VTUN_FRAME_OVERHEAD 100
Index: netlib.c
===================================================================
RCS file: /cvsroot/vtun/vtun/netlib.c,v
retrieving revision 1.11
diff -u -r1.11 netlib.c
--- netlib.c 11 Dec 2006 07:55:06 -0000 1.11
+++ netlib.c 18 Feb 2009 14:28:45 -0000
@@ -138,6 +138,7 @@
return addr.sin_addr.s_addr;
}
+int is_rmt_fd_connected=1;
/*
* Establish UDP session with host connected to fd(socket).
* Returns connected UDP socket or -1 on error.
@@ -190,10 +191,16 @@
}
saddr.sin_port = port;
+ if (VTUN_USE_NAT_HACK(host))
+ is_rmt_fd_connected=0;
+ else {
if( connect(s,(struct sockaddr *)&saddr,sizeof(saddr)) ){
vtun_syslog(LOG_ERR,"Can't connect socket");
return -1;
}
+ is_rmt_fd_connected=1;
+ }
+
host->sopt.rport = htons(port);
/* Close TCP socket and replace with UDP socket */
Index: main.c
===================================================================
RCS file: /cvsroot/vtun/vtun/main.c,v
retrieving revision 1.9
diff -u -r1.9 main.c
--- main.c 11 Dec 2006 07:55:06 -0000 1.9
+++ main.c 18 Feb 2009 14:28:45 -0000
@@ -133,6 +133,8 @@
openlog("vtund", LOG_PID|LOG_NDELAY|LOG_PERROR, vtun.syslog);
}
+ clear_nat_hack_flags(svr);
+
if(!svr){
if( argc - optind < 2 ){
usage();
Index: cfg_kwords.h
===================================================================
RCS file: /cvsroot/vtun/vtun/cfg_kwords.h,v
retrieving revision 1.6
diff -u -r1.6 cfg_kwords.h
--- cfg_kwords.h 11 Dec 2006 07:55:06 -0000 1.6
+++ cfg_kwords.h 18 Feb 2009 14:28:45 -0000
@@ -49,6 +49,7 @@
{ "encrypt", K_ENCRYPT },
{ "type", K_TYPE },
{ "proto", K_PROT },
+ { "nat_hack", K_NAT_HACK },
{ "device", K_DEVICE },
{ "ppp", K_PPP },
{ "ifconfig", K_IFCFG },
@@ -75,6 +76,8 @@
{ "tun", VTUN_TUN },
{ "tcp", VTUN_TCP },
{ "udp", VTUN_UDP },
+ { "client", VTUN_NAT_HACK_CLIENT },
+ { "server", VTUN_NAT_HACK_SERVER },
{ "lzo", VTUN_LZO },
{ "zlib", VTUN_ZLIB },
{ "wait", 1 },
Index: vtund.conf.5
===================================================================
RCS file: /cvsroot/vtun/vtun/vtund.conf.5,v
retrieving revision 1.4
diff -u -r1.4 vtund.conf.5
--- vtund.conf.5 11 Dec 2006 07:55:06 -0000 1.4
+++ vtund.conf.5 18 Feb 2009 14:28:45 -0000
@@ -145,6 +145,33 @@
UDP is recommended for \fBether\fR and \fBtun\fR tunnels only.
This option is ignored by the client.
+.IP \fBnat_hack\ \fBclient\fR|\fBserver\fR|\fBno\fR
+side to use nat_hack on. By default, \fBvtund\fR(8) uses a 'no' setting.
+The side that the NAT hack is enabled on will perform a delayed UDP socket
+connect. Should only be enabled for the side outside of the NAT (typically
+the server)! Setting 'client' on the server or 'server' on the client is
+ignored, as to make a single configuration file reusable on both sides.
+
+This is only relevant if you use \fBproto udp\fR. The NAT hack delays
+the UDP socket connect until the first UDP packet was received from the other
+side of the tunnel. Then the socket is connected to the actual source port of
+the packet (on the NAT box) and not to the one indicated in the handshake
+(which is behind NAT and probably unreachable).
+The first echo request is also disabled on the side with the NAT hack enabled.
+
+Currently the mechanism works only for one side, for a single NAT traversal.
+If you enable it for both sides, both will wait for a first packet and the
+tunnel will never transport any data.
+
+\fBSecurity warning!\fR Due to the nature of the delayed connection, the tunnel
+can be hijacked in theory by an attacker behind the same NAT, sending the first
+UDP packet to the server UDP port, before the real client does. If you do not
+understand this or just want to remain secure, use \fBproto tcp\fR as a NAT
+traversal solution.
+
+Because of the security issue mentioned above, this option might be disabled
+during compilation (without -DENABLE_NAT_HACK).
+
.IP \fBtimeout\ \fIsecounds\fR
Connect timeout.
Index: cfg_file.y
===================================================================
RCS file: /cvsroot/vtun/vtun/cfg_file.y,v
retrieving revision 1.8
diff -u -r1.8 cfg_file.y
--- cfg_file.y 11 Dec 2006 07:55:06 -0000 1.8
+++ cfg_file.y 18 Feb 2009 14:28:45 -0000
@@ -74,7 +74,7 @@
%token K_OPTIONS K_DEFAULT K_PORT K_BINDADDR K_PERSIST K_TIMEOUT
%token K_PASSWD K_PROG K_PPP K_SPEED K_IFCFG K_FWALL K_ROUTE K_DEVICE
%token K_MULTI K_SRCADDR K_IFACE K_ADDR
-%token K_TYPE K_PROT K_COMPRESS K_ENCRYPT K_KALIVE K_STAT
+%token K_TYPE K_PROT K_NAT_HACK K_COMPRESS K_ENCRYPT K_KALIVE K_STAT
%token K_UP K_DOWN K_SYSLOG K_IPROUTE
%token <str> K_HOST K_ERROR
@@ -320,6 +320,15 @@
parse_host->flags &= ~VTUN_PROT_MASK;
parse_host->flags |= $2;
}
+
+ | K_NAT_HACK NUM {
+ #ifdef ENABLE_NAT_HACK
+ parse_host->flags &= ~VTUN_NAT_HACK_MASK;
+ parse_host->flags |= $2;
+ #else
+ cfg_error("This vtund binary was built with the NAT hack disabled for security purposes.");
+ #endif
+ }
| K_SRCADDR '{' srcaddr_options '}'
@@ -581,6 +590,27 @@
return (struct vtun_host *)llist_free(&host_list, free_host, host);
}
+int clear_nat_hack_server(void *d, void *u)
+{
+ ((struct vtun_host*)d)->flags &= ~VTUN_NAT_HACK_CLIENT;
+ return 0;
+}
+
+int clear_nat_hack_client(void *d, void *u)
+{
+ ((struct vtun_host*)d)->flags &= ~VTUN_NAT_HACK_SERVER;
+ return 0;
+}
+
+/* Clear the VTUN_NAT_HACK flag which are not relevant to the current operation mode */
+inline void clear_nat_hack_flags(int svr)
+{
+ if (svr)
+ llist_trav(&host_list,clear_nat_hack_server,NULL);
+ else
+ llist_trav(&host_list,clear_nat_hack_client,NULL);
+}
+
inline void free_host_list(void)
{
llist_free(&host_list, free_host, NULL);
Index: generic/udp_proto.c
===================================================================
RCS file: /cvsroot/vtun/vtun/generic/udp_proto.c,v
retrieving revision 1.10
diff -u -r1.10 udp_proto.c
--- generic/udp_proto.c 11 Dec 2006 07:55:06 -0000 1.10
+++ generic/udp_proto.c 18 Feb 2009 14:28:45 -0000
@@ -56,12 +56,16 @@
#include "vtun.h"
#include "lib.h"
+extern int is_rmt_fd_connected;
+
/* Functions to read/write UDP frames. */
int udp_write(int fd, char *buf, int len)
{
register char *ptr;
register int wlen;
+ if (!is_rmt_fd_connected) return 0;
+
ptr = buf - sizeof(short);
*((unsigned short *)ptr) = htons(len);
@@ -86,7 +90,25 @@
unsigned short hdr, flen;
struct iovec iv[2];
register int rlen;
+ struct sockaddr_in from;
+ socklen_t fromlen = sizeof(struct sockaddr);
+ /* Late connect (NAT hack enabled) */
+ if (!is_rmt_fd_connected) {
+ while( 1 ){
+ if( (rlen = recvfrom(fd,buf,2,MSG_PEEK,(struct sockaddr *)&from,&fromlen)) < 0 ){
+ if( errno == EAGAIN || errno == EINTR ) continue;
+ else return rlen;
+ }
+ else break;
+ }
+ if( connect(fd,(struct sockaddr *)&from,fromlen) ){
+ vtun_syslog(LOG_ERR,"Can't connect socket");
+ return -1;
+ }
+ is_rmt_fd_connected = 1;
+ }
+
/* Read frame */
iv[0].iov_len = sizeof(short);
iv[0].iov_base = (char *) &hdr;
------------------------------------------------------------------------------
Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA
-OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise
-Strategies to boost innovation and cut costs with open source participation
-Receive a $600 discount off the registration fee with the source code: SFAD
http://p.sf.net/sfu/XcvMzF8H
_______________________________________________
VTun-devel mailing list
VTun-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vtun-devel