Compare commits

..

15 Commits

Author SHA1 Message Date
Adrien Gallouët
8bd936929e Show bad behaviors with command show bad
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-15 14:15:21 +00:00
Adrien Gallouët
289d88f3a7 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-15 13:06:36 +00:00
Adrien Gallouët
1673110de1 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-08 08:53:38 +00:00
Adrien Gallouët
1ce919c1e5 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-08 07:31:11 +00:00
Adrien Gallouët
e19fcaa2b0 Show remote loss too
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-07 14:18:50 +00:00
Adrien Gallouët
104fb37075 Update submodules
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-05 15:21:40 +00:00
Adrien Gallouët
6787e90be7 Update .gitignore
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-05 15:17:48 +00:00
Adrien Gallouët
639853b665 Show loss in command path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-05 09:47:04 +00:00
Adrien Gallouët
57ea0d283d Bench with more time to improve accuracy
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-05 09:17:22 +00:00
Adrien Gallouët
0c82c06119 Show correct cipher
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-05 06:05:34 +00:00
Adrien Gallouët
65f636555b Do a simpler boring bench
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-04 17:10:10 +00:00
Adrien Gallouët
c93cef5491 Faster sigma
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-03 15:35:07 +00:00
Adrien Gallouët
1fed2813e5 Fix the unprobable s.v==1 case
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-03 15:10:37 +00:00
Adrien Gallouët
860651d02f Rework bench without using -lm
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-02 16:49:27 +00:00
Adrien Gallouët
fd7ddf7814 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-24 09:57:21 +00:00
13 changed files with 145 additions and 143 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
*.o
*.[ios]
*.log
*.scan
*.cache

View File

@@ -19,7 +19,7 @@ SRC := argz/argz.c mud/mud.c mud/aegis256/aegis256.c $(wildcard src/*.c)
.PHONY: $(NAME)
$(NAME):
@echo "Building $(NAME)"
@$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium -lm
@$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium
.PHONY: install
install: $(NAME)

View File

@@ -11,6 +11,7 @@ Linux is the platform of choice but the code is standard so it should be easily
It was successfully tested on OpenBSD, FreeBSD and MacOS.
IPv4 and IPv6 are supported.
On Linux you can have both at the same time by binding `::`.
## Features
@@ -18,17 +19,16 @@ The key features of Glorytun come directly from mud:
* **Fast and highly secure**
The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure
your communications without impacting performance.
Glorytun uses AEGIS-256 only if AES-NI is available otherwise ChaCha20Poly1305 is used.
If you are not cpu bounded, you can force the use of ChaCha20Poly1305 for higher security.
All messages are encrypted, authenticated and marked with a timestamp.
Perfect forward secrecy is also implemented with ECDH over Curve25519.
The use of UDP and libsodium allows you to secure your communications without impacting performance.
Glorytun uses AEGIS-256 (a new and very fast AEAD construction) only if AES-NI is available otherwise ChaCha20-Poly1305 is used.
Of course, you can force the use of ChaCha20-Poly1305 for higher security.
All messages are encrypted, authenticated and timestamped to mitigate a large set of attacks.
Perfect forward secrecy is also implemented with ECDH over Curve25519. Keys are rotated every hours.
* **Multipath and active failover**
This is the main feature of Glorytun that allows to build an SD-WAN like service.
This allows a TCP connection to explore and exploit multiple links without being disconnected.
Connectivity is now crucial, especially in the SD-WAN world.
This feature allows a TCP connection (and all other protocols) to explore and exploit all available links without being disconnected.
Aggregation should work on all conventional links, only very high latency (+500ms) links are not recommended for now.
* **Traffic shaping**
@@ -41,7 +41,7 @@ The key features of Glorytun come directly from mud:
Bad MTU configuration is a very common problem in the world of VPN.
As it is critical, Glorytun will try to setup it correctly by guessing its value.
It doesn't rely on ICMP Next-hop MTU to avoid black holes.
It doesn't rely on Next-hop MTU to avoid ICMP black holes.
In asymmetric situations the minimum MTU is selected.
## Caveats
@@ -71,19 +71,16 @@ The more classical autotools suite is also available.
Just run `glorytun` with no arguments to view the list of available commands:
```
$ glorytun
available commands:
$ glorytun
available commands:
show show tunnel info
bench start a crypto bench
bind start a new tunnel
set change tunnel properties
keygen generate a new secret key
path manage paths
version show version
```
show show tunnel info
bench start a crypto bench
bind start a new tunnel
set change tunnel properties
keygen generate a new secret key
path manage paths
version show version
Use the keyword `help` after a command to show its usage.

2
argz

Submodule argz updated: 47ad9daf43...ff7bc660e2

View File

@@ -14,7 +14,6 @@ AM_PROG_CC_C_O
AC_PROG_CC_C99
AC_USE_SYSTEM_EXTENSIONS
AC_SEARCH_LIBS([socket], [socket])
AC_SEARCH_LIBS([fmin], [m])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_FUNCS([clock_gettime])
PKG_CHECK_MODULES([libsodium], [libsodium >= 1.0.4])

View File

@@ -38,7 +38,6 @@ executable('glorytun', install: true,
],
dependencies: [
dependency('libsodium', version : '>=1.0.4'),
cc.find_library('m', required : false)
]
)

2
mud

Submodule mud updated: b59ab48407...d0dc6076c8

View File

@@ -1,74 +1,34 @@
#include "common.h"
#include <math.h>
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#if defined __APPLE__
#include <mach/mach_time.h>
#endif
#include <inttypes.h>
#include "../argz/argz.h"
#include "../mud/aegis256/aegis256.h"
#define STR_S(X) (((X) > 1) ? "s" : "")
#define NPUBBYTES 32
#define KEYBYTES 32
#define ABYTES 16
static unsigned long long
gt_now(void)
{
#if defined __APPLE__
static mach_timebase_info_data_t mtid;
if (!mtid.denom)
mach_timebase_info(&mtid);
return (mach_absolute_time() * mtid.numer / mtid.denom) / 1000ULL;
#elif defined CLOCK_MONOTONIC
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return (unsigned long long)tv.tv_sec * 1000000ULL
+ (unsigned long long)tv.tv_nsec / 1000ULL;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (unsigned long long)tv.tv_sec * 1000000ULL
+ (unsigned long long)tv.tv_usec;
#endif
}
int
gt_bench(int argc, char **argv)
{
unsigned long precision = 10;
size_t bufsize = 64 * 1024;
unsigned long duration = 1000;
struct argz bench_argz[] = {
{"aes|chacha", NULL, NULL, argz_option},
{"precision", "EXPONENT", &precision, argz_ulong},
{"bufsize", "BYTES", &bufsize, argz_bytes},
{"duration", "SECONDS", &duration, argz_time},
{NULL}};
if (argz(bench_argz, argc, argv))
return 1;
if (duration == 0 || bufsize == 0)
return 0;
if (sodium_init() == -1) {
gt_log("sodium init failed\n");
return 1;
}
duration /= 1000;
int term = isatty(1);
int aes = argz_is_set(bench_argz, "aes");
int chacha = argz_is_set(bench_argz, "chacha");
@@ -81,71 +41,65 @@ gt_bench(int argc, char **argv)
chacha = 1;
}
unsigned char *buf = calloc(1, bufsize + ABYTES);
if (!buf) {
perror("calloc");
return 1;
}
unsigned char buf[1450 + ABYTES];
unsigned char npub[NPUBBYTES];
unsigned char key[KEYBYTES];
memset(buf, 0, sizeof(buf));
randombytes_buf(npub, sizeof(npub));
randombytes_buf(key, sizeof(key));
if (term) {
printf("\n");
printf(" %-10s %s\n", "bench", chacha ? "chacha20poly1305" : "aegis256");
printf(" %-10s %s\n", "libsodium", sodium_version_string());
printf("\n");
printf(" %-10s 2^(-%lu)\n", "precision", precision);
printf(" %-10s %zu byte%s\n", "bufsize", bufsize, STR_S(bufsize));
printf(" %-10s %lu second%s\n", "duration", duration, STR_S(duration));
printf("\n");
printf("------------------------------------------------------------\n");
printf(" %3s %9s %14s %14s %14s\n", "2^n", "min", "avg", "max", "delta");
printf("------------------------------------------------------------\n");
printf("cipher: %s\n\n", GT_CIPHER(chacha));
printf(" size min mean max \n");
printf("----------------------------------------------------\n");
}
for (int i = 0; !gt_quit && bufsize >> i; i++) {
unsigned long long total_dt = 0ULL;
size_t total_bytes = 0;
double mbps = 0.0;
double mbps_min = INFINITY;
double mbps_max = 0.0;
double mbps_dlt = INFINITY;
int64_t size = 20;
while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) {
unsigned long long now = gt_now();
double mbps_old = mbps;
size_t bytes = 0;
for (int i = 0; !gt_quit && size <= 1450; i++) {
struct {
int64_t min, mean, max, n;
} mbps = { .n = 0 };
gt_alarm = 0;
alarm((unsigned int)duration);
int64_t bytes_max = (int64_t)1 << 24;
while (!gt_quit && !gt_alarm) {
while (!gt_quit && mbps.n < 10) {
int64_t bytes = 0;
int64_t base = (int64_t)clock();
while (!gt_quit && bytes <= bytes_max) {
if (chacha) {
crypto_aead_chacha20poly1305_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub, key);
buf, NULL, buf, size, NULL, 0, NULL, npub, key);
} else {
aegis256_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, npub, key);
aegis256_encrypt(buf, NULL, buf, size, NULL, 0, npub, key);
}
bytes += 1ULL << i;
bytes += size;
}
total_dt += gt_now() - now;
total_bytes += bytes;
int64_t dt = (int64_t)clock() - base;
bytes_max = (bytes * (CLOCKS_PER_SEC / 3)) / dt;
int64_t _mbps = (8 * bytes * CLOCKS_PER_SEC) / (dt * 1000 * 1000);
mbps = ((double)total_bytes * 8.0) / (double)total_dt;
mbps_min = fmin(mbps_min, mbps);
mbps_max = fmax(mbps_max, mbps);
mbps_dlt = fabs(mbps_old - mbps);
if (!mbps.n++) {
mbps.min = _mbps;
mbps.max = _mbps;
mbps.mean = _mbps;
continue;
}
if (mbps.min > _mbps)
mbps.min = _mbps;
if (mbps.max < _mbps)
mbps.max = _mbps;
mbps.mean += (_mbps - mbps.mean) / mbps.n;
if (term) {
printf("\r %3i %9.2f Mbps %9.2f Mbps %9.2f Mbps %9.2e",
i, mbps_min, mbps, mbps_max, mbps_dlt);
printf("\r %5"PRIi64" %9"PRIi64" Mbps %9"PRIi64" Mbps %9"PRIi64" Mbps",
size, mbps.min, mbps.mean, mbps.max);
fflush(stdout);
}
}
@@ -153,12 +107,12 @@ gt_bench(int argc, char **argv)
if (term) {
printf("\n");
} else {
printf("%i %.2f %.2f %.2f\n", i, mbps_min, mbps, mbps_max);
printf("bench %s %"PRIi64" %"PRIi64" %"PRIi64" %"PRIi64"\n",
GT_CIPHER(chacha), size, mbps.min, mbps.mean, mbps.max);
}
}
printf("\n");
free(buf);
size += 2 * 5 * 13;
}
return 0;
}

View File

@@ -370,6 +370,10 @@ gt_bind(int argc, char **argv)
res.status.bind = bind_addr;
res.status.peer = peer_addr;
break;
case CTL_BAD:
if (mud_get_bad(mud, &res.bad))
res.ret = errno;
break;
}
if (sendto(ctl_fd, &res, sizeof(res), 0,
(const struct sockaddr *)&ss, sl) == -1)

View File

@@ -54,6 +54,8 @@
#undef MIN
#define MIN(x,y) ({ __typeof__(x) X=(x); __typeof__(y) Y=(y); X < Y ? X : Y; })
#define GT_CIPHER(x) ((x) ? "chacha20poly1305" : "aegis256")
extern volatile sig_atomic_t gt_alarm;
extern volatile sig_atomic_t gt_reload;
extern volatile sig_atomic_t gt_quit;

View File

@@ -16,6 +16,7 @@ enum ctl_type {
CTL_KXTIMEOUT,
CTL_TIMETOLERANCE,
CTL_PATH_STATUS,
CTL_BAD,
};
struct ctl_msg {
@@ -37,6 +38,7 @@ struct ctl_msg {
struct sockaddr_storage bind;
struct sockaddr_storage peer;
} status;
struct mud_bad bad;
size_t mtu;
int tc;
unsigned long ms;

View File

@@ -34,27 +34,26 @@ gt_path_print_status(struct mud_path *path, int term)
const char *statusstr = path->ok ? "OK" : "DEGRADED";
printf(term ? "path %s\n"
" status: %s\n"
" bind: %s port %"PRIu16"\n"
" public: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu bytes\n"
" rtt: %.3f ms\n"
" rttvar: %.3f ms\n"
" rate tx: %"PRIu64" bytes/sec\n"
" rate rx: %"PRIu64" bytes/sec\n"
" total tx: %"PRIu64" packets\n"
" total rx: %"PRIu64" packets\n"
" status: %s\n"
" bind: %s port %"PRIu16"\n"
" public: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu bytes\n"
" rtt: %.3f ms\n"
" rttvar: %.3f ms\n"
" tx:\n"
" rate: %"PRIu64" bytes/sec\n"
" loss: %"PRIu64" percent\n"
" total: %"PRIu64" packets\n"
" rx:\n"
" rate: %"PRIu64" bytes/sec\n"
" loss: %"PRIu64" percent\n"
" total: %"PRIu64" packets\n"
: "path %s %s"
" %s %"PRIu16
" %s %"PRIu16
" %s %"PRIu16
" %zu"
" %.3f %.3f"
" %"PRIu64
" %"PRIu64
" %"PRIu64
" %"PRIu64
" %s %"PRIu16" %s %"PRIu16" %s %"PRIu16
" %zu %.3f %.3f"
" %"PRIu64" %"PRIu64" %"PRIu64
" %"PRIu64" %"PRIu64" %"PRIu64
"\n",
statestr,
statusstr,
@@ -67,10 +66,12 @@ gt_path_print_status(struct mud_path *path, int term)
path->mtu.ok,
(double)path->rtt.val / 1e3,
(double)path->rtt.var / 1e3,
path->rate_tx,
path->rate_rx,
path->send.total,
path->recv.total);
path->tx.rate,
path->tx.loss,
path->tx.total,
path->rx.rate,
path->rx.loss,
path->rx.total);
}
static int

View File

@@ -11,6 +11,47 @@
#include <arpa/inet.h>
#include <unistd.h>
static void
gt_show_bad_line(int term, char *name, uint64_t count,
struct sockaddr_storage *ss)
{
if (!count)
return;
char addr[INET6_ADDRSTRLEN];
gt_toaddr(addr, sizeof(addr), (struct sockaddr *)ss);
printf(term ? "%s:\n"
" count: %"PRIu64"\n"
" last: %s port %"PRIu16"\n"
: "%s"
" %"PRIu64
" %s %"PRIu16
"\n",
name, count, addr[0] ? addr : "-",
gt_get_port((struct sockaddr *)ss));
}
static int
gt_show_bad(int fd)
{
struct ctl_msg res, req = {.type = CTL_BAD};
if (ctl_reply(fd, &res, &req))
return -1;
int term = isatty(1);
gt_show_bad_line(term, "decrypt",
res.bad.decrypt.count, &res.bad.decrypt.addr);
gt_show_bad_line(term, "difftime",
res.bad.difftime.count, &res.bad.difftime.addr);
gt_show_bad_line(term, "keyx",
res.bad.keyx.count, &res.bad.keyx.addr);
return 0;
}
static int
gt_show_status(int fd)
{
@@ -47,7 +88,7 @@ gt_show_status(int fd)
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
GT_CIPHER(res.status.chacha));
} else {
printf(term ? "client %s:\n"
" pid: %li\n"
@@ -69,7 +110,7 @@ gt_show_status(int fd)
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&res.status.peer),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
GT_CIPHER(res.status.chacha));
}
return 0;
@@ -82,6 +123,7 @@ gt_show(int argc, char **argv)
struct argz showz[] = {
{"dev", "NAME", &dev, argz_str},
{"bad", NULL, NULL, argz_option},
{NULL}};
if (argz(showz, argc, argv))
@@ -106,7 +148,9 @@ gt_show(int argc, char **argv)
return 1;
}
int ret = gt_show_status(fd);
int ret = argz_is_set(showz, "bad")
? gt_show_bad(fd)
: gt_show_status(fd);
if (ret == -1)
perror("show");