rfe2636157 - Permit a delayed UDP connection to overcome unpredictable
NAT ports.
This commit is contained in:
parent
cb03b8fa9a
commit
66658236a7
20
TODO
Normal file
20
TODO
Normal 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>
|
||||
|
@ -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
76
config.h.in
Normal 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
|
13
configure.in
13
configure.in
@ -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 ... )
|
||||
|
@ -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;
|
||||
|
10
linkfd.c
10
linkfd.c
@ -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
9
main.c
@ -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();
|
||||
|
14
netlib.c
14
netlib.c
@ -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
13
vtun.h
@ -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
|
||||
|
15
vtund.conf
15
vtund.conf
@ -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.
|
||||
|
29
vtund.conf.5
29
vtund.conf.5
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user