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>
183 #include "curvetun.h"
185 #include "ct_usermgmt.h"
186 #include "ct_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"
196 extern void print_stun_probe(char *server
, uint16_t sport
, uint16_t tunport
);
208 volatile sig_atomic_t sigint
= 0;
210 static const char *short_options
= "kxc::svhp:t:d:uCS46DN";
212 static struct option long_options
[] = {
213 {"client", optional_argument
, 0, 'c'},
214 {"dev", required_argument
, 0, 'd'},
215 {"port", required_argument
, 0, 'p'},
216 {"stun", required_argument
, 0, 't'},
217 {"keygen", no_argument
, 0, 'k'},
218 {"export", no_argument
, 0, 'x'},
219 {"dumpc", no_argument
, 0, 'C'},
220 {"dumps", no_argument
, 0, 'S'},
221 {"no-logging", no_argument
, 0, 'N'},
222 {"server", no_argument
, 0, 's'},
223 {"udp", no_argument
, 0, 'u'},
224 {"ipv4", no_argument
, 0, '4'},
225 {"ipv6", no_argument
, 0, '6'},
226 {"nofork", no_argument
, 0, 'D'},
227 {"version", no_argument
, 0, 'v'},
228 {"help", no_argument
, 0, 'h'},
232 static void signal_handler(int number
)
243 static void header(void)
245 printf("%s%s%s\n", colorize_start(bold
), "curvetun "
246 VERSION_STRING
, colorize_end());
249 static void help(void)
251 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
253 printf("http://www.netsniff-ng.org\n\n");
254 printf("Usage: curvetun [options]\n");
255 printf("Options, general:\n");
256 printf(" -k|--keygen Generate public/private keypair\n");
257 printf(" -x|--export Export your public data for remote servers\n");
258 printf(" -C|--dumpc Dump parsed clients\n");
259 printf(" -S|--dumps Dump parsed servers\n");
260 printf(" -D|--nofork Do not daemonize\n");
261 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
262 printf(" -v|--version Print version\n");
263 printf(" -h|--help Print this help\n");
264 printf("Options for client:\n");
265 printf(" -c|--client[=alias] Client mode, server alias optional\n");
266 printf("Options for servers:\n");
267 printf(" -s|--server Server mode\n");
268 printf(" -N|--no-logging Disable server logging (for better anonymity)\n");
269 printf(" -p|--port <num> Port number (mandatory)\n");
270 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
271 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
272 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
273 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
274 printf(" (default: same as carrier protocol)\n");
276 printf("Example:\n");
277 printf(" See Documentation/Curvetun for a configuration example.\n");
278 printf(" curvetun --keygen\n");
279 printf(" curvetun --export\n");
280 printf(" curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n");
281 printf(" curvetun --client=ethz\n");
284 printf(" There is no default port specified, so that you are forced\n");
285 printf(" to select your own! For client/server status messages see syslog!\n");
286 printf(" This software is an experimental prototype intended for researchers.\n");
288 printf("Secret ingredient: 7647-14-5\n");
290 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
291 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
292 printf("License: GNU GPL version 2\n");
293 printf("This is free software: you are free to change and redistribute it.\n");
294 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
298 static void version(void)
300 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
302 printf("Build: %s\n", BUILD_STRING
);
303 printf("http://www.netsniff-ng.org\n\n");
304 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
305 printf("Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
306 printf("License: GNU GPL version 2\n");
307 printf("This is free software: you are free to change and redistribute it.\n");
308 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
312 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
317 memset(path
, 0, sizeof(path
));
318 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
321 panic("No such file %s! Type --help for further information\n",
324 if (!S_ISREG(st
.st_mode
))
325 panic("%s is not a regular file!\n", path
);
327 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
328 panic("You have set too many permissions on %s (%o)!\n",
331 if (maybeempty
== 0 && st
.st_size
== 0)
332 panic("%s is empty!\n", path
);
335 static void check_config_exists_or_die(char *home
)
338 panic("No home dir specified!\n");
340 check_file_or_die(home
, FILE_CLIENTS
, 1);
341 check_file_or_die(home
, FILE_SERVERS
, 1);
342 check_file_or_die(home
, FILE_PRIVKEY
, 0);
343 check_file_or_die(home
, FILE_PUBKEY
, 0);
344 check_file_or_die(home
, FILE_USERNAM
, 0);
347 static char *fetch_home_dir(void)
349 char *home
= getenv("HOME");
351 panic("No HOME defined!\n");
355 static void write_username(char *home
)
358 char path
[PATH_MAX
], *eof
;
361 memset(path
, 0, sizeof(path
));
362 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
364 printf("Username: [%s] ", getenv("USER"));
367 memset(user
, 0, sizeof(user
));
368 eof
= fgets(user
, sizeof(user
), stdin
);
369 user
[sizeof(user
) - 1] = 0;
370 user
[strlen(user
) - 1] = 0; /* omit last \n */
371 if (strlen(user
) == 0)
372 strlcpy(user
, getenv("USER"), sizeof(user
));
374 fd
= open_or_die_m(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
376 ret
= write(fd
, user
, strlen(user
));
377 if (ret
!= strlen(user
))
378 panic("Could not write username!\n");
382 printf("Username written to %s!\n", path
);
385 static void create_curvedir(char *home
)
390 memset(path
, 0, sizeof(path
));
391 slprintf(path
, sizeof(path
), "%s/%s", home
, ".curvetun/");
395 ret
= mkdir(path
, S_IRWXU
);
396 if (ret
< 0 && errno
!= EEXIST
)
397 panic("Cannot create curvetun dir!\n");
399 printf("curvetun directory %s created!\n", path
);
400 /* We also create empty files for clients and servers! */
402 memset(path
, 0, sizeof(path
));
403 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CLIENTS
);
405 create_or_die(path
, S_IRUSR
| S_IWUSR
);
407 printf("Empty client file written to %s!\n", path
);
409 memset(path
, 0, sizeof(path
));
410 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SERVERS
);
412 create_or_die(path
, S_IRUSR
| S_IWUSR
);
414 printf("Empty server file written to %s!\n", path
);
417 static void create_keypair(char *home
)
421 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
422 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
424 const char * errstr
= NULL
;
426 printf("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE
);
428 fd
= open_or_die(CURVETUN_ENTROPY_SOURCE
, O_RDONLY
);
430 ret
= read_exact(fd
, secretkey
, sizeof(secretkey
), 0);
431 if (ret
!= sizeof(secretkey
)) {
433 errstr
= "Cannot read from "CURVETUN_ENTROPY_SOURCE
"!\n";
439 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
441 memset(path
, 0, sizeof(path
));
442 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
444 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
447 errstr
= "Cannot open pubkey file!\n";
451 ret
= write(fd
, publickey
, sizeof(publickey
));
452 if (ret
!= sizeof(publickey
)) {
454 errstr
= "Cannot write public key!\n";
460 printf("Public key written to %s!\n", path
);
462 memset(path
, 0, sizeof(path
));
463 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
465 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
468 errstr
= "Cannot open privkey file!\n";
472 ret
= write(fd
, secretkey
, sizeof(secretkey
));
473 if (ret
!= sizeof(secretkey
)) {
475 errstr
= "Cannot write private key!\n";
481 xmemset(publickey
, 0, sizeof(publickey
));
482 xmemset(secretkey
, 0, sizeof(secretkey
));
485 panic("%s: %s", errstr
, strerror(errno
));
487 printf("Private key written to %s!\n", path
);
490 static void check_config_keypair_or_die(char *home
)
494 const char * errstr
= NULL
;
495 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
496 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
497 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
500 memset(path
, 0, sizeof(path
));
501 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
503 fd
= open(path
, O_RDONLY
);
506 errstr
= "Cannot open privkey file!\n";
510 ret
= read(fd
, secretkey
, sizeof(secretkey
));
511 if (ret
!= sizeof(secretkey
)) {
513 errstr
= "Cannot read private key!\n";
519 memset(path
, 0, sizeof(path
));
520 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
522 fd
= open(path
, O_RDONLY
);
525 errstr
= "Cannot open pubkey file!\n";
529 ret
= read(fd
, publickey
, sizeof(publickey
));
530 if (ret
!= sizeof(publickey
)) {
532 errstr
= "Cannot read public key!\n";
536 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
538 err
= crypto_verify_32(publicres
, publickey
);
541 errstr
= "WARNING: your keypair is corrupted!!! You need to "
542 "generate new keys!!!\n";
548 xmemset(publickey
, 0, sizeof(publickey
));
549 xmemset(publicres
, 0, sizeof(publicres
));
550 xmemset(secretkey
, 0, sizeof(secretkey
));
553 panic("%s: %s\n", errstr
, strerror(errno
));
556 static int main_keygen(char *home
)
558 create_curvedir(home
);
559 write_username(home
);
560 create_keypair(home
);
561 check_config_keypair_or_die(home
);
566 static int main_export(char *home
)
570 char path
[PATH_MAX
], tmp
[64];
572 check_config_exists_or_die(home
);
573 check_config_keypair_or_die(home
);
575 printf("Your exported public information:\n\n");
577 memset(path
, 0, sizeof(path
));
578 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
580 fd
= open_or_die(path
, O_RDONLY
);
582 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
583 ret
= write(STDOUT_FILENO
, tmp
, ret
);
590 memset(path
, 0, sizeof(path
));
591 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
593 fd
= open_or_die(path
, O_RDONLY
);
595 ret
= read(fd
, tmp
, sizeof(tmp
));
596 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
597 panic("Cannot read public key!\n");
599 for (i
= 0; i
< ret
; ++i
)
601 printf("%02x\n\n", (unsigned char) tmp
[i
]);
603 printf("%02x:", (unsigned char) tmp
[i
]);
611 static int main_dumpc(char *home
)
613 check_config_exists_or_die(home
);
614 check_config_keypair_or_die(home
);
616 printf("Your clients:\n\n");
618 parse_userfile_and_generate_user_store_or_die(home
);
622 destroy_user_store();
629 static int main_dumps(char *home
)
631 check_config_exists_or_die(home
);
632 check_config_keypair_or_die(home
);
634 printf("Your servers:\n\n");
636 parse_userfile_and_generate_serv_store_or_die(home
);
640 destroy_serv_store();
647 static void daemonize(const char *lockfile
)
650 mode_t lperm
= S_IRWXU
| S_IRGRP
| S_IXGRP
; /* 0750 */
657 panic("Cannot daemonize: %s", strerror(errno
));
661 lfp
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
,
662 S_IRUSR
| S_IWUSR
| S_IRGRP
);
664 syslog_panic("Cannot create lockfile at %s! "
665 "curvetun server already running?\n",
668 slprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
669 if (write(lfp
, pidstr
, strlen(pidstr
)) <= 0)
670 syslog_panic("Could not write pid to pidfile %s",
677 static int main_client(char *home
, char *dev
, char *alias
, int daemon
)
682 check_config_exists_or_die(home
);
683 check_config_keypair_or_die(home
);
685 parse_userfile_and_generate_serv_store_or_die(home
);
687 get_serv_store_entry_by_alias(alias
, alias
? strlen(alias
) + 1 : 0,
689 if (!host
|| !port
|| udp
< 0)
690 panic("Did not find alias/entry in configuration!\n");
692 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
693 alias
? : "default", host
, port
, udp
? "udp" : "tcp");
697 ret
= client_main(home
, dev
, host
, port
, udp
);
699 destroy_serv_store();
704 static int main_server(char *home
, char *dev
, char *port
, int udp
,
705 int ipv4
, int daemon
, int log
)
709 check_config_exists_or_die(home
);
710 check_config_keypair_or_die(home
);
715 ret
= server_main(home
, dev
, port
, udp
, ipv4
, log
);
722 int main(int argc
, char **argv
)
724 int ret
= 0, c
, opt_index
, udp
= 0, ipv4
= -1, daemon
= 1, log
= 1;
725 char *port
= NULL
, *stun
= NULL
, *dev
= NULL
, *home
= NULL
, *alias
= NULL
;
726 enum working_mode wmode
= MODE_UNKNOW
;
728 if (getuid() != geteuid())
731 home
= fetch_home_dir();
733 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
734 &opt_index
)) != EOF
) {
759 alias
= xstrdup(optarg
);
763 dev
= xstrdup(optarg
);
784 stun
= xstrdup(optarg
);
787 port
= xstrdup(optarg
);
795 panic("Option -%c requires an argument!\n",
799 whine("Unknown option character "
800 "`0x%X\'!\n", optopt
);
811 register_signal(SIGINT
, signal_handler
);
812 register_signal(SIGHUP
, signal_handler
);
813 register_signal(SIGTERM
, signal_handler
);
814 register_signal(SIGPIPE
, signal_handler
);
818 curve25519_selftest();
822 ret
= main_keygen(home
);
825 ret
= main_export(home
);
828 ret
= main_dumpc(home
);
831 ret
= main_dumps(home
);
834 ret
= main_client(home
, dev
, alias
, daemon
);
838 panic("No port specified!\n");
840 print_stun_probe(stun
, 3478, strtoul(port
, NULL
, 10));
841 ret
= main_server(home
, dev
, port
, udp
, ipv4
, daemon
, log
);