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>
182 #include "curvetun.h"
184 #include "ct_usermgmt.h"
185 #include "ct_servmgmt.h"
188 #include "crypto_verify_32.h"
189 #include "crypto_box_curve25519xsalsa20poly1305.h"
190 #include "crypto_scalarmult_curve25519.h"
191 #include "crypto_auth_hmacsha512256.h"
193 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
195 extern void print_stun_probe(char *server
, uint16_t sport
, uint16_t tunport
);
207 volatile sig_atomic_t sigint
= 0;
209 static const char *short_options
= "kxc::svhp:t:d:uCS46DN";
211 static struct option long_options
[] = {
212 {"client", optional_argument
, 0, 'c'},
213 {"dev", required_argument
, 0, 'd'},
214 {"port", required_argument
, 0, 'p'},
215 {"stun", required_argument
, 0, 't'},
216 {"keygen", no_argument
, 0, 'k'},
217 {"export", no_argument
, 0, 'x'},
218 {"dumpc", no_argument
, 0, 'C'},
219 {"dumps", no_argument
, 0, 'S'},
220 {"no-logging", no_argument
, 0, 'N'},
221 {"server", no_argument
, 0, 's'},
222 {"udp", no_argument
, 0, 'u'},
223 {"ipv4", no_argument
, 0, '4'},
224 {"ipv6", no_argument
, 0, '6'},
225 {"nofork", no_argument
, 0, 'D'},
226 {"version", no_argument
, 0, 'v'},
227 {"help", no_argument
, 0, 'h'},
231 static void signal_handler(int number
)
242 static void header(void)
244 printf("%s%s%s\n", colorize_start(bold
), "curvetun "
245 VERSION_STRING
, colorize_end());
248 static void help(void)
250 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
252 printf("http://www.netsniff-ng.org\n\n");
253 printf("Usage: curvetun [options]\n");
254 printf("Options, general:\n");
255 printf(" -k|--keygen Generate public/private keypair\n");
256 printf(" -x|--export Export your public data for remote servers\n");
257 printf(" -C|--dumpc Dump parsed clients\n");
258 printf(" -S|--dumps Dump parsed servers\n");
259 printf(" -D|--nofork Do not daemonize\n");
260 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
261 printf(" -v|--version Print version\n");
262 printf(" -h|--help Print this help\n");
263 printf("Options for client:\n");
264 printf(" -c|--client[=alias] Client mode, server alias optional\n");
265 printf("Options for servers:\n");
266 printf(" -s|--server Server mode\n");
267 printf(" -N|--no-logging Disable server logging (for better anonymity)\n");
268 printf(" -p|--port <num> Port number (mandatory)\n");
269 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
270 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
271 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
272 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
273 printf(" (default: same as carrier protocol)\n");
275 printf("Example:\n");
276 printf(" See Documentation/Curvetun for a configuration example.\n");
277 printf(" curvetun --keygen\n");
278 printf(" curvetun --export\n");
279 printf(" curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n");
280 printf(" curvetun --client=ethz\n");
283 printf(" There is no default port specified, so that you are forced\n");
284 printf(" to select your own! For client/server status messages see syslog!\n");
285 printf(" This software is an experimental prototype intended for researchers.\n");
287 printf("Secret ingredient: 7647-14-5\n");
289 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
290 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
291 printf("License: GNU GPL version 2\n");
292 printf("This is free software: you are free to change and redistribute it.\n");
293 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
297 static void version(void)
299 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
301 printf("Build: %s\n", BUILD_STRING
);
302 printf("http://www.netsniff-ng.org\n\n");
303 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
304 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
305 printf("License: GNU GPL version 2\n");
306 printf("This is free software: you are free to change and redistribute it.\n");
307 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
311 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
316 memset(path
, 0, sizeof(path
));
317 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
320 panic("No such file %s! Type --help for further information\n",
323 if (!S_ISREG(st
.st_mode
))
324 panic("%s is not a regular file!\n", path
);
326 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
327 panic("You have set too many permissions on %s (%o)!\n",
330 if (maybeempty
== 0 && st
.st_size
== 0)
331 panic("%s is empty!\n", path
);
334 static void check_config_exists_or_die(char *home
)
337 panic("No home dir specified!\n");
339 check_file_or_die(home
, FILE_CLIENTS
, 1);
340 check_file_or_die(home
, FILE_SERVERS
, 1);
341 check_file_or_die(home
, FILE_PRIVKEY
, 0);
342 check_file_or_die(home
, FILE_PUBKEY
, 0);
343 check_file_or_die(home
, FILE_USERNAM
, 0);
346 static char *fetch_home_dir(void)
348 char *home
= getenv("HOME");
350 panic("No HOME defined!\n");
354 static void write_username(char *home
)
357 char path
[PATH_MAX
], *eof
;
360 memset(path
, 0, sizeof(path
));
361 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
363 printf("Username: [%s] ", getenv("USER"));
366 memset(user
, 0, sizeof(user
));
367 eof
= fgets(user
, sizeof(user
), stdin
);
368 user
[sizeof(user
) - 1] = 0;
369 user
[strlen(user
) - 1] = 0; /* omit last \n */
370 if (strlen(user
) == 0)
371 strlcpy(user
, getenv("USER"), sizeof(user
));
373 fd
= open_or_die_m(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
375 ret
= write(fd
, user
, strlen(user
));
376 if (ret
!= strlen(user
))
377 panic("Could not write username!\n");
381 printf("Username written to %s!\n", path
);
384 static void create_curvedir(char *home
)
389 memset(path
, 0, sizeof(path
));
390 slprintf(path
, sizeof(path
), "%s/%s", home
, ".curvetun/");
394 ret
= mkdir(path
, S_IRWXU
);
395 if (ret
< 0 && errno
!= EEXIST
)
396 panic("Cannot create curvetun dir!\n");
398 printf("curvetun directory %s created!\n", path
);
399 /* We also create empty files for clients and servers! */
401 memset(path
, 0, sizeof(path
));
402 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CLIENTS
);
404 create_or_die(path
, S_IRUSR
| S_IWUSR
);
406 printf("Empty client file written to %s!\n", path
);
408 memset(path
, 0, sizeof(path
));
409 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SERVERS
);
411 create_or_die(path
, S_IRUSR
| S_IWUSR
);
413 printf("Empty server file written to %s!\n", path
);
416 static void create_keypair(char *home
)
420 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
421 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
423 const char * errstr
= NULL
;
425 printf("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE
);
427 fd
= open_or_die(CURVETUN_ENTROPY_SOURCE
, O_RDONLY
);
429 ret
= read_exact(fd
, secretkey
, sizeof(secretkey
), 0);
430 if (ret
!= sizeof(secretkey
)) {
432 errstr
= "Cannot read from "CURVETUN_ENTROPY_SOURCE
"!\n";
438 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
440 memset(path
, 0, sizeof(path
));
441 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
443 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
446 errstr
= "Cannot open pubkey file!\n";
450 ret
= write(fd
, publickey
, sizeof(publickey
));
451 if (ret
!= sizeof(publickey
)) {
453 errstr
= "Cannot write public key!\n";
459 printf("Public key written to %s!\n", path
);
461 memset(path
, 0, sizeof(path
));
462 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
464 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
467 errstr
= "Cannot open privkey file!\n";
471 ret
= write(fd
, secretkey
, sizeof(secretkey
));
472 if (ret
!= sizeof(secretkey
)) {
474 errstr
= "Cannot write private key!\n";
480 xmemset(publickey
, 0, sizeof(publickey
));
481 xmemset(secretkey
, 0, sizeof(secretkey
));
484 panic("%s: %s", errstr
, strerror(errno
));
486 printf("Private key written to %s!\n", path
);
489 static void check_config_keypair_or_die(char *home
)
493 const char * errstr
= NULL
;
494 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
495 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
496 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
499 memset(path
, 0, sizeof(path
));
500 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
502 fd
= open(path
, O_RDONLY
);
505 errstr
= "Cannot open privkey file!\n";
509 ret
= read(fd
, secretkey
, sizeof(secretkey
));
510 if (ret
!= sizeof(secretkey
)) {
512 errstr
= "Cannot read private key!\n";
518 memset(path
, 0, sizeof(path
));
519 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
521 fd
= open(path
, O_RDONLY
);
524 errstr
= "Cannot open pubkey file!\n";
528 ret
= read(fd
, publickey
, sizeof(publickey
));
529 if (ret
!= sizeof(publickey
)) {
531 errstr
= "Cannot read public key!\n";
535 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
537 err
= crypto_verify_32(publicres
, publickey
);
540 errstr
= "WARNING: your keypair is corrupted!!! You need to "
541 "generate new keys!!!\n";
547 xmemset(publickey
, 0, sizeof(publickey
));
548 xmemset(publicres
, 0, sizeof(publicres
));
549 xmemset(secretkey
, 0, sizeof(secretkey
));
552 panic("%s: %s\n", errstr
, strerror(errno
));
555 static int main_keygen(char *home
)
557 create_curvedir(home
);
558 write_username(home
);
559 create_keypair(home
);
560 check_config_keypair_or_die(home
);
565 static int main_export(char *home
)
569 char path
[PATH_MAX
], tmp
[64];
571 check_config_exists_or_die(home
);
572 check_config_keypair_or_die(home
);
574 printf("Your exported public information:\n\n");
576 memset(path
, 0, sizeof(path
));
577 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
579 fd
= open_or_die(path
, O_RDONLY
);
581 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
582 ret
= write(STDOUT_FILENO
, tmp
, ret
);
589 memset(path
, 0, sizeof(path
));
590 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
592 fd
= open_or_die(path
, O_RDONLY
);
594 ret
= read(fd
, tmp
, sizeof(tmp
));
595 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
596 panic("Cannot read public key!\n");
598 for (i
= 0; i
< ret
; ++i
)
600 printf("%02x\n\n", (unsigned char) tmp
[i
]);
602 printf("%02x:", (unsigned char) tmp
[i
]);
610 static int main_dumpc(char *home
)
612 check_config_exists_or_die(home
);
613 check_config_keypair_or_die(home
);
615 printf("Your clients:\n\n");
617 parse_userfile_and_generate_user_store_or_die(home
);
621 destroy_user_store();
628 static int main_dumps(char *home
)
630 check_config_exists_or_die(home
);
631 check_config_keypair_or_die(home
);
633 printf("Your servers:\n\n");
635 parse_userfile_and_generate_serv_store_or_die(home
);
639 destroy_serv_store();
646 static void daemonize(const char *lockfile
)
649 mode_t lperm
= S_IRWXU
| S_IRGRP
| S_IXGRP
; /* 0750 */
656 panic("Cannot daemonize: %s", strerror(errno
));
660 lfp
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
,
661 S_IRUSR
| S_IWUSR
| S_IRGRP
);
663 syslog_panic("Cannot create lockfile at %s! "
664 "curvetun server already running?\n",
667 slprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
668 if (write(lfp
, pidstr
, strlen(pidstr
)) <= 0)
669 syslog_panic("Could not write pid to pidfile %s",
676 static int main_client(char *home
, char *dev
, char *alias
, int daemon
)
681 check_config_exists_or_die(home
);
682 check_config_keypair_or_die(home
);
684 parse_userfile_and_generate_serv_store_or_die(home
);
686 get_serv_store_entry_by_alias(alias
, alias
? strlen(alias
) + 1 : 0,
688 if (!host
|| !port
|| udp
< 0)
689 panic("Did not find alias/entry in configuration!\n");
691 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
692 alias
? : "default", host
, port
, udp
? "udp" : "tcp");
696 ret
= client_main(home
, dev
, host
, port
, udp
);
698 destroy_serv_store();
703 static int main_server(char *home
, char *dev
, char *port
, int udp
,
704 int ipv4
, int daemon
, int log
)
708 check_config_exists_or_die(home
);
709 check_config_keypair_or_die(home
);
714 ret
= server_main(home
, dev
, port
, udp
, ipv4
, log
);
721 int main(int argc
, char **argv
)
723 int ret
= 0, c
, opt_index
, udp
= 0, ipv4
= -1, daemon
= 1, log
= 1;
724 char *port
= NULL
, *stun
= NULL
, *dev
= NULL
, *home
= NULL
, *alias
= NULL
;
725 enum working_mode wmode
= MODE_UNKNOW
;
727 if (getuid() != geteuid())
730 home
= fetch_home_dir();
732 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
733 &opt_index
)) != EOF
) {
758 alias
= xstrdup(optarg
);
762 dev
= xstrdup(optarg
);
783 stun
= xstrdup(optarg
);
786 port
= xstrdup(optarg
);
794 panic("Option -%c requires an argument!\n",
798 whine("Unknown option character "
799 "`0x%X\'!\n", optopt
);
810 register_signal(SIGINT
, signal_handler
);
811 register_signal(SIGHUP
, signal_handler
);
812 register_signal(SIGTERM
, signal_handler
);
813 register_signal(SIGPIPE
, signal_handler
);
817 curve25519_selftest();
821 ret
= main_keygen(home
);
824 ret
= main_export(home
);
827 ret
= main_dumpc(home
);
830 ret
= main_dumps(home
);
833 ret
= main_client(home
, dev
, alias
, daemon
);
837 panic("No port specified!\n");
839 print_stun_probe(stun
, 3478, strtoul(port
, NULL
, 10));
840 ret
= main_server(home
, dev
, port
, udp
, ipv4
, daemon
, log
);