mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +02:00
Merge branch 'dev' into speck
This commit is contained in:
commit
3b0903785e
|
@ -106,10 +106,11 @@ n2n edge nodes use twofish encryption by default for compatibility reasons with
|
|||
of the edge nodes, their IP address and the community are sent in cleartext.
|
||||
|
||||
When encryption is enabled, the supernode will not be able to decrypt the traffic exchanged between
|
||||
two edge nodes, but it will now that edge A is talking with edge B.
|
||||
two edge nodes, but it will know that edge A is talking with edge B.
|
||||
|
||||
Recently AES encryption support has been implemented, which increases both security and performance,
|
||||
so it is recommended to enable it on all the edge nodes by specifying the `-A` option.
|
||||
so it is recommended to enable it on all the edge nodes that must have the -Ax value. When possible
|
||||
(i.e. when n2n is compiled with OpenSSL 1.1) we recommend to use -A4
|
||||
|
||||
A benchmark of the encryption methods is available when compiled from source with `tools/n2n-benchmark`.
|
||||
|
||||
|
|
|
@ -13,14 +13,24 @@ else
|
|||
GIT_RELEASE=${N2N_VERSION_SHORT}
|
||||
fi
|
||||
|
||||
N2N_LIBS=
|
||||
|
||||
AC_CHECK_LIB([zstd], [ZSTD_compress])
|
||||
|
||||
if test "x$ac_cv_lib_zstd_ZSTD_compress" != xyes; then
|
||||
AC_MSG_RESULT(Building n2n without ZSTD support)
|
||||
else
|
||||
AC_DEFINE([N2N_HAVE_ZSTD], [], [Have ZSTD support])
|
||||
N2N_LIBS="-lzstd ${N2N_LIBS}"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([crypto], [AES_cbc_encrypt])
|
||||
|
||||
N2N_LIBS=
|
||||
if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then
|
||||
AC_MSG_RESULT(Building n2n without AES support)
|
||||
else
|
||||
AC_DEFINE([N2N_HAVE_AES], [], [Have AES support])
|
||||
N2N_LIBS=-lcrypto
|
||||
N2N_LIBS="-lcrypto ${N2N_LIBS}"
|
||||
fi
|
||||
|
||||
OLD_CFLAGS="${CFLAGS}"
|
||||
|
|
138
edge.c
138
edge.c
|
@ -159,7 +159,7 @@ static void help() {
|
|||
#ifndef __APPLE__
|
||||
"[-D] "
|
||||
#endif
|
||||
"[-r] [-E] [-v] [-i <reg_interval>] [-L <reg_ttl>] [-t <mgmt port>] [-A[<cipher>]] [-h]\n\n");
|
||||
"[-r] [-E] [-v] [-i <reg_interval>] [-L <reg_ttl>] [-t <mgmt port>] [-A[<cipher>]] [-z[<compression algo>]] [-h]\n\n");
|
||||
|
||||
#if defined(N2N_CAN_NAME_IFACE)
|
||||
printf("-d <tun device> | tun device name\n");
|
||||
|
@ -189,16 +189,22 @@ static void help() {
|
|||
#endif
|
||||
printf("-r | Enable packet forwarding through n2n community.\n");
|
||||
printf("-A1 | Disable payload encryption. Do not use with -k.\n");
|
||||
printf("-A2 | Use Twofish for payload encryption (default). Requires a key.\n");
|
||||
printf("-A2 | Use Twofish for payload encryption (default). Requires a key (-k).\n");
|
||||
#ifdef N2N_HAVE_AES
|
||||
printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key.\n");
|
||||
printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key (-k).\n");
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_1_1
|
||||
printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n");
|
||||
printf("-A5 | Use Speck for payload encryption. Requires a key.\n");
|
||||
#endif
|
||||
printf("-z | Enable lzo1x compression for outgoing data packets\n");
|
||||
printf(" | (default=disabled).\n");
|
||||
#ifdef HAVE_OPENSSL_1_1
|
||||
printf("-A4 | Use ChaCha20 for payload encryption. Requires a key (-k).\n");
|
||||
#endif
|
||||
printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n");
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
printf("-z2 | Enable zstd compression for outgoing data packets\n");
|
||||
#endif
|
||||
printf(" | (default=compression disabled)\n");
|
||||
printf("-E | Accept multicast MAC addresses (default=drop).\n");
|
||||
printf("-S | Do not connect P2P. Always use the supernode.\n");
|
||||
#ifdef __linux__
|
||||
|
@ -221,6 +227,46 @@ static void help() {
|
|||
|
||||
/* *************************************************** */
|
||||
|
||||
static void setPayloadEncryption( n2n_edge_conf_t *conf, int cipher) {
|
||||
/* even though 'cipher' and 'conf->transop_id' share the same encoding scheme,
|
||||
* a switch-statement under conditional compilation is used to sort out the
|
||||
* unsupported ciphers */
|
||||
switch (cipher) {
|
||||
case 1:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_NULL;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
|
||||
break;
|
||||
}
|
||||
#ifdef N2N_HAVE_AES
|
||||
case 3:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_AESCBC;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_1_1
|
||||
case 4:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_CHACHA20;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_INVAL;
|
||||
traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version.", transop_str(cipher));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_edge_conf_t *conf) {
|
||||
/* traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, optargument ? optargument : ""); */
|
||||
|
||||
|
@ -309,59 +355,50 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
|
|||
|
||||
case 'A':
|
||||
{
|
||||
int cipher = N2N_TRANSFORM_ID_AESCBC; // default, if '-A' only
|
||||
int cipher;
|
||||
|
||||
if (optargument) {
|
||||
cipher = atoi(optargument);
|
||||
} else {
|
||||
traceEvent(TRACE_NORMAL, "the use of the solitary -A switch is deprecated and might not be supported in future versions. "
|
||||
"please use -A3 instead to choose a the AES-CBC cipher for payload encryption.");
|
||||
|
||||
cipher = N2N_TRANSFORM_ID_AESCBC; // default, if '-A' only
|
||||
}
|
||||
/* even though 'cipher' and 'conf->transop_id' share the same encoding scheme,
|
||||
* a switch-statement under conditional compilation is used to sort out the
|
||||
* unsupported ciphers */
|
||||
switch (cipher) {
|
||||
case 1:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_NULL;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
|
||||
break;
|
||||
}
|
||||
#ifdef N2N_HAVE_AES
|
||||
case 3:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_AESCBC;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_OPENSSL_1_1
|
||||
case 4:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_CHACHA20;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case 5:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_SPECK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
conf->transop_id = N2N_TRANSFORM_ID_INVAL;
|
||||
traceEvent(TRACE_NORMAL, "the %s cipher given by -A_ option is not supported in this version.", transop_str(cipher));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
setPayloadEncryption(conf, cipher);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z':
|
||||
{
|
||||
conf->compression = N2N_COMPRESSION_ID_LZO;
|
||||
int compression = N2N_COMPRESSION_ID_LZO; // default, if '-z' only
|
||||
if (optargument) {
|
||||
compression = atoi(optargument);
|
||||
}
|
||||
/* even though 'compression' and 'conf->compression' share the same encoding scheme,
|
||||
* a switch-statement under conditional compilation is used to sort out the
|
||||
* unsupported optarguments */
|
||||
switch (compression) {
|
||||
case 1:
|
||||
{
|
||||
conf->compression = N2N_COMPRESSION_ID_LZO;
|
||||
break;
|
||||
}
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
case 2:
|
||||
{
|
||||
conf->compression = N2N_COMPRESSION_ID_ZSTD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
conf->compression = N2N_COMPRESSION_ID_NONE;
|
||||
traceEvent(TRACE_NORMAL, "the %s compression given by -z_ option is not supported in this version.", compression_str(compression));
|
||||
exit(1); // to make the user aware
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -509,10 +546,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:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:z"
|
||||
|
||||
"A::"
|
||||
|
||||
"k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:zA:z::"
|
||||
#ifdef __linux__
|
||||
"T:n:"
|
||||
#endif
|
||||
|
@ -796,6 +830,8 @@ int main(int argc, char* argv[]) {
|
|||
#if defined(HAVE_OPENSSL_1_1)
|
||||
traceEvent(TRACE_NORMAL, "Using %s", OpenSSL_version(0));
|
||||
#endif
|
||||
|
||||
traceEvent(TRACE_NORMAL, "Using compression: %s.", compression_str(conf.compression));
|
||||
traceEvent(TRACE_NORMAL, "Using %s cipher.", transop_str(conf.transop_id));
|
||||
|
||||
/* Random seed */
|
||||
|
|
72
edge_utils.c
72
edge_utils.c
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "n2n.h"
|
||||
#include "lzoconf.h"
|
||||
#include <zstd.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
|
@ -158,6 +159,17 @@ const char* transop_str(enum n2n_transform tr) {
|
|||
|
||||
/* ************************************** */
|
||||
|
||||
const char* compression_str(uint8_t cmpr) {
|
||||
switch(cmpr) {
|
||||
case N2N_COMPRESSION_ID_NONE: return("none");
|
||||
case N2N_COMPRESSION_ID_LZO: return("lzo1x");
|
||||
case N2N_COMPRESSION_ID_ZSTD: return("zstd");
|
||||
default: return("invalid");
|
||||
};
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
/** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet.
|
||||
*/
|
||||
static int is_ethMulticast(const void * buf, size_t bufsize) {
|
||||
|
@ -237,6 +249,10 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
|
|||
goto edge_init_error;
|
||||
}
|
||||
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
// zstd does not require initialization. if it were required, this would be a good place
|
||||
#endif
|
||||
|
||||
for(i=0; i<conf->sn_num; ++i)
|
||||
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i]));
|
||||
|
||||
|
@ -261,7 +277,6 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
|
|||
case N2N_TRANSFORM_ID_SPECK:
|
||||
rc = n2n_transop_speck_init(&eee->conf, &eee->transop);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = n2n_transop_null_init(&eee->conf, &eee->transop);
|
||||
}
|
||||
|
@ -997,20 +1012,37 @@ static int handle_PACKET(n2n_edge_t * eee,
|
|||
|
||||
/* decompress if necessary */
|
||||
uint8_t * deflation_buffer = 0;
|
||||
uint32_t deflated_len;
|
||||
int32_t deflated_len;
|
||||
switch (rx_compression_id) {
|
||||
case N2N_COMPRESSION_ID_NONE:
|
||||
break; // continue afterwards
|
||||
|
||||
case N2N_COMPRESSION_ID_LZO:
|
||||
deflation_buffer = malloc (N2N_PKT_BUF_SIZE);
|
||||
deflation_buffer = malloc (N2N_PKT_BUF_SIZE);
|
||||
lzo1x_decompress (eth_payload, eth_size, deflation_buffer, (lzo_uint*)&deflated_len, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
case N2N_COMPRESSION_ID_ZSTD:
|
||||
deflated_len = N2N_PKT_BUF_SIZE;
|
||||
deflation_buffer = malloc (deflated_len);
|
||||
deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, eth_payload, eth_size);
|
||||
if (ZSTD_isError(deflated_len)) {
|
||||
traceEvent (TRACE_ERROR, "payload decompression failed with zstd error '%s'.",
|
||||
ZSTD_getErrorName(deflated_len));
|
||||
free (deflation_buffer);
|
||||
return (-1); // cannot help it
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
traceEvent (TRACE_ERROR, "payload decompression failed: received packet indicating unsupported %s compression.",
|
||||
compression_str(rx_compression_id));
|
||||
return (-1); // cannot handle it
|
||||
}
|
||||
|
||||
if (rx_compression_id) {
|
||||
traceEvent (TRACE_DEBUG, "payload decompression [id: %u]: deflated %u bytes to %u bytes",
|
||||
rx_compression_id, eth_size, (int)deflated_len);
|
||||
traceEvent (TRACE_DEBUG, "payload decompression [%s]: deflated %u bytes to %u bytes",
|
||||
compression_str(rx_compression_id), eth_size, (int)deflated_len);
|
||||
memcpy(eth_payload ,deflation_buffer, deflated_len );
|
||||
eth_size = deflated_len;
|
||||
free (deflation_buffer);
|
||||
|
@ -1375,9 +1407,11 @@ static void send_packet2net(n2n_edge_t * eee,
|
|||
|
||||
// compression needs to be tried before encode_PACKET is called for compression indication gets encoded there
|
||||
pkt.compression = N2N_COMPRESSION_ID_NONE;
|
||||
|
||||
if (eee->conf.compression) {
|
||||
uint8_t * compression_buffer;
|
||||
uint32_t compression_len;
|
||||
int32_t compression_len;
|
||||
|
||||
switch (eee->conf.compression) {
|
||||
case N2N_COMPRESSION_ID_LZO:
|
||||
compression_buffer = malloc (len + len / 16 + 64 + 3);
|
||||
|
@ -1387,14 +1421,30 @@ static void send_packet2net(n2n_edge_t * eee,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
case N2N_COMPRESSION_ID_ZSTD:
|
||||
compression_len = N2N_PKT_BUF_SIZE + 128;
|
||||
compression_buffer = malloc (compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower)
|
||||
compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL) ;
|
||||
if (!ZSTD_isError(compression_len)) {
|
||||
if (compression_len < len) {
|
||||
pkt.compression = N2N_COMPRESSION_ID_ZSTD;
|
||||
}
|
||||
} else {
|
||||
traceEvent (TRACE_ERROR, "payload compression failed with zstd error '%s'.",
|
||||
ZSTD_getErrorName(compression_len));
|
||||
free (compression_buffer);
|
||||
// continue with unset without pkt.compression --> will send uncompressed
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pkt.compression) {
|
||||
traceEvent (TRACE_DEBUG, "payload compression [id: %u]: compressed %u bytes to %u bytes\n",
|
||||
pkt.compression, len, compression_len);
|
||||
traceEvent (TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n",
|
||||
compression_str(pkt.compression), len, compression_len);
|
||||
|
||||
memcpy (tap_pkt, compression_buffer, compression_len);
|
||||
len = compression_len;
|
||||
|
|
12
n2n.h
12
n2n.h
|
@ -164,9 +164,15 @@ typedef struct tuntap_dev {
|
|||
/* N2N compression indicators. */
|
||||
/* Compression is disabled by default for outgoing packets if no cli
|
||||
* option is given. All edges are built with decompression support so
|
||||
* they are able to understand each other. */
|
||||
* they are able to understand each other (this applies to lzo only). */
|
||||
#define N2N_COMPRESSION_ID_NONE 0 /* default, see edge_init_conf_defaults(...) in edge_utils.c */
|
||||
#define N2N_COMPRESSION_ID_LZO 1 /* set if '-z' cli option is present, see setOption(...) in edge.c */
|
||||
#define N2N_COMPRESSION_ID_LZO 1 /* set if '-z1' or '-z' cli option is present, see setOption(...) in edge.c */
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
#define N2N_COMPRESSION_ID_ZSTD 2 /* set if '-z2' cli option is present, available only if compiled with zstd lib */
|
||||
#define ZSTD_COMPRESSION_LEVEL 7 /* 1 (faster) ... 22 (more compression) */
|
||||
#endif
|
||||
// with the next major packet structure update, make '0' = invalid, and '1' = no compression
|
||||
// '2' = LZO, '3' = ZSTD, ... REVISIT then (also: change all occurences in source).
|
||||
|
||||
#define N2N_COMPRESSION_ID_BITLEN 3 /* number of bits used for encoding compression id in the uppermost
|
||||
bits of transform_id; will be obsolete as soon as compression gets
|
||||
|
@ -200,7 +206,6 @@ struct peer_info {
|
|||
HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add)
|
||||
#define HASH_FIND_PEER(head,mac,out) \
|
||||
HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out)
|
||||
|
||||
#define N2N_EDGE_SN_HOST_SIZE 48
|
||||
#define N2N_EDGE_NUM_SUPERNODES 2
|
||||
#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */
|
||||
|
@ -369,6 +374,7 @@ int quick_edge_init(char *device_name, char *community_name,
|
|||
int sn_init(n2n_sn_t *sss);
|
||||
void sn_term(n2n_sn_t *sss);
|
||||
int run_sn_loop(n2n_sn_t *sss, int *keep_running);
|
||||
const char* compression_str(uint8_t cmpr);
|
||||
const char* transop_str(enum n2n_transform tr);
|
||||
|
||||
#endif /* _N2N_H_ */
|
||||
|
|
|
@ -100,6 +100,7 @@ int main(int argc, char * argv[]) {
|
|||
#ifdef HAVE_OPENSSL_1_1
|
||||
n2n_trans_op_t transop_cc20;
|
||||
#endif
|
||||
|
||||
n2n_trans_op_t transop_speck;
|
||||
n2n_edge_conf_t conf;
|
||||
|
||||
|
@ -120,7 +121,7 @@ int main(int argc, char * argv[]) {
|
|||
n2n_transop_cc20_init(&conf, &transop_cc20);
|
||||
#endif
|
||||
n2n_transop_speck_init(&conf, &transop_speck);
|
||||
|
||||
|
||||
/* Run the tests */
|
||||
run_transop_benchmark("transop_null", &transop_null, &conf, pktbuf);
|
||||
run_transop_benchmark("transop_twofish", &transop_twofish, &conf, pktbuf);
|
||||
|
|
|
@ -120,9 +120,6 @@ static int transop_encode_cc20(n2n_trans_op_t * arg,
|
|||
/* Generate and encode the IV. */
|
||||
set_cc20_iv(priv, enc_ivec);
|
||||
encode_buf(outbuf, &idx, &enc_ivec, N2N_CC20_IVEC_SIZE);
|
||||
traceEvent(TRACE_DEBUG, "encode_cc20 iv=%016llx:%016llx",
|
||||
htobe64(*(uint64_t*)&enc_ivec[0]),
|
||||
htobe64(*(uint64_t*)&enc_ivec[8]) );
|
||||
|
||||
/* Encrypt the assembly contents and write the ciphertext after the iv. */
|
||||
/* len is set to the length of the cipher plain text to be encrpyted
|
||||
|
@ -198,9 +195,6 @@ static int transop_decode_cc20(n2n_trans_op_t * arg,
|
|||
|
||||
/* Get the IV */
|
||||
decode_buf((uint8_t *)&dec_ivec, N2N_CC20_IVEC_SIZE, inbuf, &rem, &idx);
|
||||
traceEvent(TRACE_DEBUG, "decode_cc20 iv=%016llx:%016llx",
|
||||
htobe64(*(uint64_t*)&dec_ivec[0]),
|
||||
htobe64(*(uint64_t*)&dec_ivec[8]) );
|
||||
|
||||
EVP_CIPHER_CTX *ctx = priv->dec_ctx;
|
||||
int evp_len;
|
||||
|
|
Loading…
Reference in New Issue
Block a user