Add the -i option to specify registration interval on edge nodes

Registration is bound to UDP NAT hole punching, so the edges should choose their own value.
This commit is contained in:
emanuele-f 2019-05-05 21:22:23 +02:00
parent 856dbae44c
commit d5387945b4
5 changed files with 41 additions and 23 deletions

View File

@ -35,10 +35,22 @@ socket to which the initiating UDP packets were sent. This means that when an
inside host sends UDP to some outside socket; other hosts cannot piggyback on
this opening in the firewall to send data to the inside host.
When two inside hosts are both behind symmetric NAT, peer-to-peer packet
exchange is not possible via n2n. These hosts will require the supernode to
relay packets.
For example, an asymmetric NAT would keep the mapping:
<UDP,ExtPort> -> <IntIP, IntPort>
and would redirect all the packets on external port ExtPort to the internal host
regardless of the remote IP.
Whereas a symmetric NAT would keep the mapping:
<UDP,RemoteIP,ExtPort> -> <IntIP, IntPort>
so only RemoteIP can send packets to the internal host. RemoteIP is the supernode
IP in case of n2n, to which the internal host has registered.
In n2n, P2P can work monodirecitonally if only one of the two peers is behind a symmetric
NAT. For example, if A is behind symmetric NAT and B is behind asymmetric NAT
- A->B packets are P2P (will have the B public IP as destination)
- B->A packets must go through the supernode
If both the peers are behind symmetric NAT, then no P2P communication is possible.
ARP CACHE
---------

6
edge.8
View File

@ -39,6 +39,12 @@ truncated to take the first 16 bytes.
\-h
write usage then exit.
.TP
\-i <register_interval>
Supernode registration interval. It specifies the interval in seconds
between consecutive REGISTER_SUPER packets and it's used to keep NAT hole
open via the UDP NAT hole punching technique. This only works for asymmetric
NATs and allows for P2P communication.
.TP
\-k <keystring>
sets the twofish encryption key from ASCII text (see also N2N_KEY in
ENVIRONMENT). All edges communicating must use the same key and community

11
edge.c
View File

@ -120,7 +120,7 @@ static void help() {
#endif /* #if defined(N2N_CAN_NAME_IFACE) */
"-a [static:|dhcp:]<tun IP address> "
"-c <community> "
"[-k <encrypt key> | -K <key file>]\n"
"[-k <encrypt key>]\n"
" "
"[-s <netmask>] "
#ifndef WIN32
@ -134,7 +134,7 @@ static void help() {
"-l <supernode host:port>\n"
" "
"[-p <local port>] [-M <mtu>] "
"[-r] [-E] [-v] [-t <mgmt port>] [-b] [-A] [-h]\n\n");
"[-r] [-E] [-v] [-i <reg_interval>] [-t <mgmt port>] [-b] [-A] [-h]\n\n");
#ifdef __linux__
printf("-d <tun device> | tun device name\n");
@ -145,6 +145,7 @@ static void help() {
printf("-k <encrypt key> | Encryption key (ASCII) - also N2N_KEY=<encrypt key>.\n");
printf("-s <netmask> | Edge interface netmask in dotted decimal notation (255.255.255.0).\n");
printf("-l <supernode host:port> | Supernode IP:port\n");
printf("-i <reg_interval> | Registration interval, for NAT hole punching (default 20 seconds)\n");
printf("-b | Periodically resolve supernode IP\n");
printf(" | (when supernodes are running on dynamic IPs)\n");
printf("-p <local port> | Fixed local UDP port.\n");
@ -265,6 +266,10 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
break;
}
case 'i': /* supernode registration interval */
conf->register_interval = atoi(optarg);
break;
#if defined(N2N_CAN_NAME_IFACE)
case 'd': /* TUNTAP name */
{
@ -341,7 +346,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c
u_char c;
while((c = getopt_long(argc, argv,
"K:k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:"
"K:k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:"
#ifdef N2N_HAVE_AES
"A"
#endif

View File

@ -28,16 +28,9 @@
#include <tun2tap/tun2tap.h>
#endif /* __ANDROID_NDK__ */
#if defined(DEBUG)
#define SOCKET_TIMEOUT_INTERVAL_SECS 5
#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec */
#else /* #if defined(DEBUG) */
#define SOCKET_TIMEOUT_INTERVAL_SECS 10
#define REGISTER_SUPER_INTERVAL_DFL 60 /* sec */
#endif /* #if defined(DEBUG) */
#define REGISTER_SUPER_INTERVAL_MIN 5 /* sec */
#define REGISTER_SUPER_INTERVAL_MAX 3600 /* sec */
#define SOCKET_TIMEOUT_INTERVAL_SECS 10
#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */
#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */
#define TRANSOP_TICK_INTERVAL (10) /* sec */
@ -75,6 +68,9 @@ int edge_verify_conf(const n2n_edge_conf_t *conf) {
if(conf->sn_num == 0)
return(-2);
if(conf->register_interval < 1)
return(-3);
return(0);
}
@ -104,7 +100,6 @@ struct n2n_edge {
/* Timers */
time_t last_register_req; /**< Check if time to re-register with super*/
size_t register_lifetime; /**< Time distance after last_register_req at which to re-register. */
time_t last_p2p; /**< Last time p2p traffic was received. */
time_t last_sup; /**< Last time a packet arrived from supernode. */
time_t start_time; /**< For calculating uptime */
@ -151,7 +146,6 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
eee->known_peers = NULL;
eee->pending_peers = NULL;
eee->register_lifetime = REGISTER_SUPER_INTERVAL_DFL;
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS;
#ifdef NOT_USED
@ -673,10 +667,10 @@ static void send_register_ack(n2n_edge_t * eee,
static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
u_int sn_idx;
if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->register_lifetime/10)))) {
if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->conf.register_interval/10)))) {
/* fall through */
traceEvent(TRACE_DEBUG, "update_supernode_reg: doing fast retry.");
} else if(nowTime < (eee->last_register_req + eee->register_lifetime))
} else if(nowTime < (eee->last_register_req + eee->conf.register_interval))
return; /* Too early */
if(0 == eee->sup_attempts) {
@ -1403,10 +1397,9 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
eee->sn_wait=0;
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */
/* REVISIT: store sn_back */
eee->register_lifetime = ra.lifetime;
eee->register_lifetime = MAX(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MIN);
eee->register_lifetime = MIN(eee->register_lifetime, REGISTER_SUPER_INTERVAL_MAX);
/* NOTE: the register_interval should be chosen by the edge node
* based on its NAT configuration. */
//eee->conf.register_interval = ra.lifetime;
}
else
{
@ -1639,6 +1632,7 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf) {
conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; /* use twofish for compatibility */
conf->drop_multicast = 1;
conf->register_interval = REGISTER_SUPER_INTERVAL_DFL;
if(getenv("N2N_KEY"))
conf->encrypt_key = strdup(getenv("N2N_KEY"));

1
n2n.h
View File

@ -193,6 +193,7 @@ typedef struct n2n_edge_conf {
uint8_t drop_multicast; /**< Multicast ethernet addresses. */
uint8_t sn_num; /**< Number of supernode addresses defined. */
char *encrypt_key;
int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */
int local_port;
int mgmt_port;
} n2n_edge_conf_t;