2 * curvetun - the cipherspace wormhole creator
3 * Part of the netsniff-ng project
4 * By Daniel Borkmann <daniel@netsniff-ng.org>
5 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
6 * Copyright 2011 Emmanuel Roullit.
7 * Subject to the GPL, version 2.
9 * This is curvetun, a lightweight, high-speed ECDH multiuser IP tunnel for
10 * Linux that is based on epoll(2). curvetun uses the Linux TUN/TAP interface
11 * and supports {IPv4,IPv6} over {IPv4,IPv6} with UDP or TCP as carrier
12 * protocols. It has an integrated packet forwarding trie, thus multiple
13 * users with different IPs can be handled via a single tunnel device on the
14 * server side and flows are scheduled for processing in a CPU-local manner.
15 * For transmission, packets are being compressed and encrypted by both, the
16 * client and the server side. As an appropriate key management, public-key
17 * cryptography based on elliptic curves are being used and packets are
18 * encrypted by a symmetric stream cipher (Salsa20) and authenticated by a MAC
19 * (Poly1305), where keys have previously been computed with the ECDH key
20 * agreement protocol (Curve25519). Cryptography is based on Daniel J.
21 * Bernsteins Networking and Cryptography library (NaCl).
23 * He used often to say there was only one Road; that it was like a great
24 * river: it's springs were at every doorstep and every path was it's
25 * tributary. "It's a dangerous business, Frodo, going out of your door,"
26 * he used to say. "You step into the Road, and if you don't keep your
27 * feet, there is no telling where you might be swept off to."
29 * -- The Lord of the Rings, Frodo about his uncle Bilbo Baggins,
30 * Chapter 'Three is Company'.
37 curvetun - lightweight curve25519-based multiuser IP tunnel
41 curvetun [-d|--dev <tun>][-x|--export][-C|--dumpc][-S|--dumps]
42 [-k|--keygen][-c|--client [<alias>]][-s|--server][-N|--no-logging]
43 [-p|--port <num>][-t|--stun <server>][-4|--ipv4][-6|--ipv6]
44 [-v|--version][-h|--help]
48 curvetun embeds a client and a server to build and manage multiuser
49 IP tunnels using Elliptic Curve Cryptography (ECC)
55 =item curvetun --keygen
57 Generate public/private keypair. This needs to be done before
58 to get things started.
60 =item curvetun --export
62 Export public data to remote servers
64 =item curvetun --server -4 -u -N --port 6666 --stun stunserver.org
66 Start a UDP IPv4 curvetun server on port 6666.
67 Use stunserver.org as STUN server.
69 =item curvetun --client=ethz
71 Start curvetun client using the profile called 'ethz'
81 Generate public/private keypair.
85 Export your public data for remote servers.
101 Networking tunnel device, e.g. tun0.
103 =item -c|--client [<alias>]
105 Client mode, server alias optional.
111 =item -N|--no-logging
113 Disable server logging (for better anonymity).
115 =item -p|--port <num>
117 Port number (mandatory).
119 =item -t|--stun <server>
121 Show public IP/Port mapping via STUN.
125 Use UDP as carrier instead of TCP.
129 Tunnel devices are IPv4.
133 Tunnel devices are IPv6.
141 Print help text and lists all options.
147 Written by Daniel Borkmann <daniel@netsniff-ng.org> and Emmanuel Roullit <emmanuel@netsniff-ng.org>
151 Documentation by Emmanuel Roullit <emmanuel@netsniff-ng.org>
155 Please report bugs to <bugs@netsniff-ng.org>
171 #include <sys/types.h>
172 #include <sys/stat.h>
173 #include <sys/socket.h>
174 #include <sys/ptrace.h>
175 #include <netinet/in.h>
184 #include "curvetun.h"
186 #include "usermgmt.h"
187 #include "servmgmt.h"
189 #include "crypto_verify_32.h"
190 #include "crypto_box_curve25519xsalsa20poly1305.h"
191 #include "crypto_scalarmult_curve25519.h"
192 #include "crypto_auth_hmacsha512256.h"
194 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
206 volatile sig_atomic_t sigint
= 0;
208 static const char *short_options
= "kxc::svhp:t:d:uCS46DN";
210 static struct option long_options
[] = {
211 {"client", optional_argument
, 0, 'c'},
212 {"dev", required_argument
, 0, 'd'},
213 {"port", required_argument
, 0, 'p'},
214 {"stun", required_argument
, 0, 't'},
215 {"keygen", no_argument
, 0, 'k'},
216 {"export", no_argument
, 0, 'x'},
217 {"dumpc", no_argument
, 0, 'C'},
218 {"dumps", no_argument
, 0, 'S'},
219 {"no-logging", no_argument
, 0, 'N'},
220 {"server", no_argument
, 0, 's'},
221 {"udp", no_argument
, 0, 'u'},
222 {"ipv4", no_argument
, 0, '4'},
223 {"ipv6", no_argument
, 0, '6'},
224 {"nofork", no_argument
, 0, 'D'},
225 {"version", no_argument
, 0, 'v'},
226 {"help", no_argument
, 0, 'h'},
230 static void signal_handler(int number
)
241 static void header(void)
243 printf("%s%s%s\n", colorize_start(bold
), "curvetun "
244 VERSION_STRING
, colorize_end());
247 static void help(void)
249 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
251 printf("http://www.netsniff-ng.org\n\n");
252 printf("Usage: curvetun [options]\n");
253 printf("Options:\n");
254 printf(" -k|--keygen Generate public/private keypair\n");
255 printf(" -x|--export Export your public data for remote servers\n");
256 printf(" -C|--dumpc Dump parsed clients\n");
257 printf(" -S|--dumps Dump parsed servers\n");
258 printf(" -D|--nofork Do not daemonize\n");
259 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
260 printf(" -v|--version Print version\n");
261 printf(" -h|--help Print this help\n");
262 printf(" additional options for client:\n");
263 printf(" -c|--client[=alias] Client mode, server alias optional\n");
264 printf(" additional options for servers:\n");
265 printf(" -s|--server Server mode\n");
266 printf(" -N|--no-logging Disable server logging (for better anonymity)\n");
267 printf(" -p|--port <num> Port number (mandatory)\n");
268 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
269 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
270 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
271 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
272 printf(" (default: same as carrier protocol)\n");
274 printf("Example:\n");
275 printf(" See README.curvetun for a configuration example.\n");
276 printf(" curvetun --keygen\n");
277 printf(" curvetun --export\n");
278 printf(" curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n");
279 printf(" curvetun --client=ethz\n");
282 printf(" There is no default port specified, so that you are forced\n");
283 printf(" to select your own! For client/server status messages see syslog!\n");
284 printf(" This software is an experimental prototype intended for researchers.\n");
286 printf("Secret ingredient: 7647-14-5\n");
288 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
289 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
290 printf("License: GNU GPL version 2\n");
291 printf("This is free software: you are free to change and redistribute it.\n");
292 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
296 static void version(void)
298 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
300 printf("Build: %s\n", BUILD_STRING
);
301 printf("http://www.netsniff-ng.org\n\n");
302 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
303 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
304 printf("License: GNU GPL version 2\n");
305 printf("This is free software: you are free to change and redistribute it.\n");
306 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
310 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
314 memset(path
, 0, sizeof(path
));
315 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
317 panic("No such file %s! Type --help for further information\n",
319 if (!S_ISREG(st
.st_mode
))
320 panic("%s is not a regular file!\n", path
);
321 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
322 panic("You have set too many permissions on %s (%o)!\n",
324 if (maybeempty
== 0 && st
.st_size
== 0)
325 panic("%s is empty!\n", path
);
328 static void check_config_exists_or_die(char *home
)
331 panic("No home dir specified!\n");
332 check_file_or_die(home
, FILE_CLIENTS
, 1);
333 check_file_or_die(home
, FILE_SERVERS
, 1);
334 check_file_or_die(home
, FILE_PRIVKEY
, 0);
335 check_file_or_die(home
, FILE_PUBKEY
, 0);
336 check_file_or_die(home
, FILE_USERNAM
, 0);
339 static char *fetch_home_dir(void)
341 char *home
= getenv("HOME");
343 panic("No HOME defined!\n");
347 static void write_username(char *home
)
350 char path
[PATH_MAX
], *eof
;
352 memset(path
, 0, sizeof(path
));
353 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
354 printf("Username: [%s] ", getenv("USER"));
356 memset(user
, 0, sizeof(user
));
357 eof
= fgets(user
, sizeof(user
), stdin
);
358 user
[sizeof(user
) - 1] = 0;
359 user
[strlen(user
) - 1] = 0; /* omit last \n */
360 if (strlen(user
) == 0)
361 strlcpy(user
, getenv("USER"), sizeof(user
));
362 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
364 panic("Cannot open your username file!\n");
365 ret
= write(fd
, user
, strlen(user
));
366 if (ret
!= strlen(user
))
367 panic("Could not write username!\n");
369 printf("Username written to %s!\n", path
);
372 static void create_curvedir(char *home
)
376 memset(path
, 0, sizeof(path
));
377 slprintf(path
, sizeof(path
), "%s/%s", home
, ".curvetun/");
379 ret
= mkdir(path
, S_IRWXU
);
380 if (ret
< 0 && errno
!= EEXIST
)
381 panic("Cannot create curvetun dir!\n");
382 printf("curvetun directory %s created!\n", path
);
383 /* We also create empty files for clients and servers! */
384 memset(path
, 0, sizeof(path
));
385 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CLIENTS
);
386 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
388 panic("Cannot open clients file!\n");
390 printf("Empty client file written to %s!\n", path
);
391 memset(path
, 0, sizeof(path
));
392 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SERVERS
);
393 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
395 panic("Cannot open servers file!\n");
397 printf("Empty server file written to %s!\n", path
);
400 static void create_keypair(char *home
)
404 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
405 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
407 const char * errstr
= NULL
;
408 printf("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE
);
409 fd
= open_or_die(CURVETUN_ENTROPY_SOURCE
, O_RDONLY
);
410 ret
= read_exact(fd
, secretkey
, sizeof(secretkey
), 0);
411 if (ret
!= sizeof(secretkey
)) {
413 errstr
= "Cannot read from "CURVETUN_ENTROPY_SOURCE
"!\n";
417 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
418 memset(path
, 0, sizeof(path
));
419 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
420 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
423 errstr
= "Cannot open pubkey file!\n";
426 ret
= write(fd
, publickey
, sizeof(publickey
));
427 if (ret
!= sizeof(publickey
)) {
429 errstr
= "Cannot write public key!\n";
433 printf("Public key written to %s!\n", path
);
434 memset(path
, 0, sizeof(path
));
435 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
436 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
439 errstr
= "Cannot open privkey file!\n";
442 ret
= write(fd
, secretkey
, sizeof(secretkey
));
443 if (ret
!= sizeof(secretkey
)) {
445 errstr
= "Cannot write private key!\n";
450 xmemset(publickey
, 0, sizeof(publickey
));
451 xmemset(secretkey
, 0, sizeof(secretkey
));
453 panic("%s: %s", errstr
, strerror(errno
));
455 printf("Private key written to %s!\n", path
);
458 static void check_config_keypair_or_die(char *home
)
462 const char * errstr
= NULL
;
463 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
464 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
465 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
467 memset(path
, 0, sizeof(path
));
468 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
469 fd
= open(path
, O_RDONLY
);
472 errstr
= "Cannot open privkey file!\n";
475 ret
= read(fd
, secretkey
, sizeof(secretkey
));
476 if (ret
!= sizeof(secretkey
)) {
478 errstr
= "Cannot read private key!\n";
482 memset(path
, 0, sizeof(path
));
483 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
484 fd
= open(path
, O_RDONLY
);
487 errstr
= "Cannot open pubkey file!\n";
490 ret
= read(fd
, publickey
, sizeof(publickey
));
491 if (ret
!= sizeof(publickey
)) {
493 errstr
= "Cannot read public key!\n";
496 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
497 err
= crypto_verify_32(publicres
, publickey
);
500 errstr
= "WARNING: your keypair is corrupted!!! You need to "
501 "generate new keys!!!\n";
506 xmemset(publickey
, 0, sizeof(publickey
));
507 xmemset(publicres
, 0, sizeof(publicres
));
508 xmemset(secretkey
, 0, sizeof(secretkey
));
510 panic("%s: %s\n", errstr
, strerror(errno
));
513 static int main_keygen(char *home
)
515 create_curvedir(home
);
516 write_username(home
);
517 create_keypair(home
);
518 check_config_keypair_or_die(home
);
522 static int main_export(char *home
)
526 char path
[PATH_MAX
], tmp
[64];
528 check_config_exists_or_die(home
);
529 check_config_keypair_or_die(home
);
530 printf("Your exported public information:\n\n");
531 memset(path
, 0, sizeof(path
));
532 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
533 fd
= open_or_die(path
, O_RDONLY
);
534 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
535 ret
= write(STDOUT_FILENO
, tmp
, ret
);
539 memset(path
, 0, sizeof(path
));
540 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
541 fd
= open_or_die(path
, O_RDONLY
);
542 ret
= read(fd
, tmp
, sizeof(tmp
));
543 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
544 panic("Cannot read public key!\n");
545 for (i
= 0; i
< ret
; ++i
)
547 printf("%02x\n\n", (unsigned char) tmp
[i
]);
549 printf("%02x:", (unsigned char) tmp
[i
]);
555 static int main_dumpc(char *home
)
557 check_config_exists_or_die(home
);
558 check_config_keypair_or_die(home
);
559 printf("Your clients:\n\n");
560 parse_userfile_and_generate_user_store_or_die(home
);
562 destroy_user_store();
568 static int main_dumps(char *home
)
570 check_config_exists_or_die(home
);
571 check_config_keypair_or_die(home
);
572 printf("Your servers:\n\n");
573 parse_userfile_and_generate_serv_store_or_die(home
);
575 destroy_serv_store();
581 static void daemonize(const char *lockfile
)
584 mode_t lperm
= S_IRWXU
| S_IRGRP
| S_IXGRP
; /* 0750 */
589 panic("Cannot daemonize: %s", strerror(errno
));
592 lfp
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
, 0640);
594 syslog_panic("Cannot create lockfile at %s! "
595 "curvetun server already running?\n",
597 slprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
598 if (write(lfp
, pidstr
, strlen(pidstr
)) <= 0)
599 syslog_panic("Could not write pid to pidfile %s",
605 static int main_client(char *home
, char *dev
, char *alias
, int daemon
)
609 check_config_exists_or_die(home
);
610 check_config_keypair_or_die(home
);
611 parse_userfile_and_generate_serv_store_or_die(home
);
612 get_serv_store_entry_by_alias(alias
, alias
? strlen(alias
) + 1 : 0,
614 if (!host
|| !port
|| udp
< 0)
615 panic("Did not find alias/entry in configuration!\n");
616 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
617 alias
? : "default", host
, port
, udp
? "udp" : "tcp");
620 ret
= client_main(home
, dev
, host
, port
, udp
);
621 destroy_serv_store();
625 static int main_server(char *home
, char *dev
, char *port
, int udp
,
626 int ipv4
, int daemon
, int log
)
629 check_config_exists_or_die(home
);
630 check_config_keypair_or_die(home
);
633 ret
= server_main(home
, dev
, port
, udp
, ipv4
, log
);
638 int main(int argc
, char **argv
)
640 int ret
= 0, c
, opt_index
, udp
= 0, ipv4
= -1, daemon
= 1, log
= 1;
641 char *port
= NULL
, *stun
= NULL
, *dev
= NULL
, *home
= NULL
, *alias
=NULL
;
642 enum working_mode wmode
= MODE_UNKNOW
;
643 if (getuid() != geteuid())
645 if (getenv("LD_PRELOAD"))
646 panic("curvetun cannot be preloaded!\n");
647 if (ptrace(PTRACE_TRACEME
, 0, 1, 0) < 0)
648 panic("curvetun cannot be ptraced!\n");
649 home
= fetch_home_dir();
650 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
651 &opt_index
)) != EOF
) {
676 alias
= xstrdup(optarg
);
680 dev
= xstrdup(optarg
);
701 stun
= xstrdup(optarg
);
704 port
= xstrdup(optarg
);
712 panic("Option -%c requires an argument!\n",
716 whine("Unknown option character "
717 "`0x%X\'!\n", optopt
);
727 register_signal(SIGINT
, signal_handler
);
728 register_signal(SIGHUP
, signal_handler
);
729 register_signal(SIGTERM
, signal_handler
);
730 register_signal(SIGPIPE
, signal_handler
);
732 curve25519_selftest();
735 ret
= main_keygen(home
);
738 ret
= main_export(home
);
741 ret
= main_dumpc(home
);
744 ret
= main_dumps(home
);
747 ret
= main_client(home
, dev
, alias
, daemon
);
751 panic("No port specified!\n");
753 print_stun_probe(stun
, 3478, strtoul(port
, NULL
, 10));
754 ret
= main_server(home
, dev
, port
, udp
, ipv4
, daemon
, log
);