rfe2636157 - Permit a delayed UDP connection to overcome unpredictable

NAT ports.
This commit is contained in:
mtbishop 2009-03-29 10:08:41 +00:00
parent cb03b8fa9a
commit 66658236a7
12 changed files with 7897 additions and 12 deletions

20
TODO Normal file
View File

@ -0,0 +1,20 @@
netlib.c:196 - set a timeout for waiting for the remote UDP start
NATHack
- unify the config as one (local) setting, and use a connection
cookie passed to coordinate which side goes passive. The server
wins in all ties. auth.c:195
- lose the global variable and move it into the vtun struct. For
now. main.c:54, vtun.h:111
---
Comments, suggestion, wishes and if possible patches are always welcome.
Send them to vtun-users@lists.sourceforge.net .
Bishop Clark <bishop@platypus.bc.ca>

View File

@ -17,7 +17,7 @@
*/
/*
* $Id: cfg_kwords.h,v 1.6.2.2 2008/01/07 22:35:26 mtbishop Exp $
* $Id: cfg_kwords.h,v 1.6.2.3 2009/03/29 10:08:41 mtbishop Exp $
*/
extern int lineno;
@ -49,6 +49,8 @@ struct kword cfg_keyword[] = {
{ "encrypt", K_ENCRYPT },
{ "type", K_TYPE },
{ "proto", K_PROT },
{ "nat_hack", K_NAT_HACK },
{ "delay_udp",K_NAT_HACK },
{ "device", K_DEVICE },
{ "ppp", K_PPP },
{ "ifconfig", K_IFCFG },
@ -75,6 +77,8 @@ struct kword cfg_param[] = {
{ "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 },

76
config.h.in Normal file
View File

@ -0,0 +1,76 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define to empty if the keyword does not work. */
#undef const
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define if you have the <netinet/ip.h> header file. */
#undef HAVE_NETINET_IP_H
/* Define if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
/* Define if you have the <netinet/in_systm.h> header file. */
#undef HAVE_NETINET_IN_SYSTM_H
/* Define if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define if you have the <sched.h> header file. */
#undef HAVE_SCHED_H
/* Define if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
/* Define if you have the <linux/if_tun.h> header file. */
#undef HAVE_LINUX_IF_TUN_H
/* Define if you have setproctitle. */
#undef HAVE_SETPROC_TITLE
#undef HAVE_LIBUTIL_H
/* Define if you have ZLIB */
#undef HAVE_ZLIB
/* Define if you have LZO */
#undef HAVE_LZO
/* Define if you have OpenSSL */
#undef HAVE_SSL
#undef HAVE_SSL_BLOWFISH
#undef HAVE_SSL_AES
#undef HAVE_SSL_EVP
#undef HAVE_SHAPER
#undef ENABLE_NAT_HACK
/* Release version and date */
#undef VTUN_VER

7680
configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ dnl
dnl VTun - Virtual Tunnel over TCP/IP network.
dnl Copyright (C) 1998-2006 Maxim Krasnyansky <max_mk@yahoo.com>
dnl
dnl $Id: configure.in,v 1.19.2.1 2007/06/29 05:26:01 mtbishop Exp $
dnl $Id: configure.in,v 1.19.2.2 2009/03/29 10:08:51 mtbishop Exp $
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
@ -41,6 +41,13 @@ AC_ARG_ENABLE(socks,
SOCKS=no
)
dnl Delayed UDP Start support
AC_ARG_ENABLE(nathack,
--disable-nathack Do not enable Nat Hack code,
NATHACK=$enableval,
NATHACK=yes
)
AC_ARG_WITH(ssl-headers,
--with-ssl-headers=DIR Crypto Include files location,
SSL_HDR_DIR="$withval"
@ -212,6 +219,10 @@ if test "$SSL" = "yes"; then
)
fi
if test "$NATHACK" = "yes"; then
AC_DEFINE(ENABLE_NAT_HACK)
fi
if test "$SOCKS" = "yes"; then
AC_MSG_RESULT()
AC_CHECKING( for SOCKS Library ... )

View File

@ -17,7 +17,7 @@
*/
/*
* $Id: udp_proto.c,v 1.10.2.2 2008/01/07 22:36:19 mtbishop Exp $
* $Id: udp_proto.c,v 1.10.2.3 2009/03/29 10:09:13 mtbishop Exp $
*/
#include "config.h"
@ -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 @@ int udp_read(int fd, char *buf)
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;

View File

@ -17,7 +17,7 @@
*/
/*
* $Id: linkfd.c,v 1.13.2.3 2008/01/07 22:35:43 mtbishop Exp $
* $Id: linkfd.c,v 1.13.2.4 2009/03/29 10:08:54 mtbishop Exp $
*/
#include "config.h"
@ -211,8 +211,12 @@ int lfd_linker(void)
vtun_syslog(LOG_ERR,"Can't allocate buffer for the linker");
return 0;
}
proto_write(fd1, buf, VTUN_ECHO_REQ);
/* Delay sending of first UDP packet over broken NAT routers
because we will probably be disconnected. Wait for the remote
end to send us something first, and use that connection. */
if (!VTUN_USE_NAT_HACK(lfd_host))
proto_write(fd1, buf, VTUN_ECHO_REQ);
maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;

9
main.c
View File

@ -17,7 +17,7 @@
*/
/*
* $Id: main.c,v 1.9.2.2 2008/01/07 22:35:53 mtbishop Exp $
* $Id: main.c,v 1.9.2.3 2009/03/29 10:08:57 mtbishop Exp $
*/
#include "config.h"
@ -50,9 +50,12 @@ void usage(void);
extern int optind,opterr,optopt;
extern char *optarg;
/* for the NATHack bit. Is our UDP session connected? */
int is_rmt_fd_connected=1;
int main(int argc, char *argv[], char *env[])
{
int svr, daemon, sock, dofork, fd, opt;
int svr, daemon, sock, dofork, fd, opt;
struct vtun_host *host = NULL;
struct sigaction sa;
char *hst;
@ -133,6 +136,8 @@ int main(int argc, char *argv[], char *env[])
openlog("vtund", LOG_PID|LOG_NDELAY|LOG_PERROR, vtun.syslog);
}
clear_nat_hack_flags(svr);
if(!svr){
if( argc - optind < 2 ){
usage();

View File

@ -17,7 +17,7 @@
*/
/*
* $Id: netlib.c,v 1.11.2.2 2008/01/07 22:35:56 mtbishop Exp $
* $Id: netlib.c,v 1.11.2.3 2009/03/29 10:08:59 mtbishop Exp $
*/
#include "config.h"
@ -190,10 +190,22 @@ int udp_session(struct vtun_host *host)
}
saddr.sin_port = port;
/* if the config says to delay the UDP connection, we wait for an
incoming packet and then force a connection back. We need to
put this here because we need to keep that incoming triggering
packet and pass it back up the chain. */
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 */

13
vtun.h
View File

@ -17,7 +17,7 @@
*/
/*
* $Id: vtun.h,v 1.12.2.3 2008/01/07 22:36:07 mtbishop Exp $
* $Id: vtun.h,v 1.12.2.4 2009/03/29 10:09:11 mtbishop Exp $
*/
#ifndef _VTUN_H
@ -163,6 +163,17 @@ extern llist host_list;
#define VTUN_STAT 0x1000
#define VTUN_PERSIST 0x2000
#ifdef ENABLE_NAT_HACK
/* 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 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

View File

@ -6,7 +6,7 @@
# Ted Rolle <ted@acacia.datacomm.com>
#
# Configuration file example
# $Id: vtund.conf,v 1.4.2.2 2008/01/07 22:36:05 mtbishop Exp $
# $Id: vtund.conf,v 1.4.2.3 2009/03/29 10:09:05 mtbishop Exp $
#
#
# Lines which begin with '#' are comments
@ -107,6 +107,19 @@
# This option is ignored by the client.
#
# -----------
# nat_hack - Delay UDP set-up connection until Server or Client sends
# a UDP packet, depending on setting. Useful to work around
# routers which use mismatched port numbers for UDP traffic.
#
# 'client' - Delay UDP set-up on the client side
# 'server' - Delay UDP set-up on the server side.
# 'no' - Disable the NAT hack on both sides (default).
#
# Setting 'nat_hack client' on the server or 'nat_hack 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.

View File

@ -1,5 +1,5 @@
.\" Manual page for vtund.conf
.\" $Id: vtund.conf.5,v 1.4.2.1 2007/06/29 05:26:47 mtbishop Exp $
.\" $Id: vtund.conf.5,v 1.4.2.2 2009/03/29 10:09:08 mtbishop Exp $
.TH VTUND.CONF 5
.SH NAME
@ -145,6 +145,33 @@ protocol to use. By default, \fBvtund\fR(8) will use TCP protocol.
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 is received from the other
side of the tunnel. The socket is then 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 the risks, or want to remain as secure as possible behind this kind
of NAT router, use \fBproto tcp\fR as a NAT traversal solution.
Because of the security issue mentioned above, this option might be disabled
during compilation (configure --disable-nathack).
.IP \fBtimeout\ \fIsecounds\fR
Connect timeout.