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'.
43 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/ptrace.h>
47 #include <netinet/in.h>
61 #include "crypto_verify_32.h"
62 #include "crypto_box_curve25519xsalsa20poly1305.h"
63 #include "crypto_scalarmult_curve25519.h"
64 #include "crypto_auth_hmacsha512256.h"
66 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
78 sig_atomic_t sigint
= 0;
80 static const char *short_options
= "kxc::svhp:t:d:uCS46DN";
82 static struct option long_options
[] = {
83 {"client", optional_argument
, 0, 'c'},
84 {"dev", required_argument
, 0, 'd'},
85 {"port", required_argument
, 0, 'p'},
86 {"stun", required_argument
, 0, 't'},
87 {"keygen", no_argument
, 0, 'k'},
88 {"export", no_argument
, 0, 'x'},
89 {"dumpc", no_argument
, 0, 'C'},
90 {"dumps", no_argument
, 0, 'S'},
91 {"no-logging", no_argument
, 0, 'N'},
92 {"server", no_argument
, 0, 's'},
93 {"udp", no_argument
, 0, 'u'},
94 {"ipv4", no_argument
, 0, '4'},
95 {"ipv6", no_argument
, 0, '6'},
96 {"nofork", no_argument
, 0, 'D'},
97 {"version", no_argument
, 0, 'v'},
98 {"help", no_argument
, 0, 'h'},
102 static void signal_handler(int number
)
113 static void header(void)
115 printf("%s%s%s\n", colorize_start(bold
), "curvetun "
116 VERSION_STRING
, colorize_end());
119 static void help(void)
121 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
123 printf("http://www.netsniff-ng.org\n\n");
124 printf("Usage: curvetun [options]\n");
125 printf("Options:\n");
126 printf(" -k|--keygen Generate public/private keypair\n");
127 printf(" -x|--export Export your public data for remote servers\n");
128 printf(" -C|--dumpc Dump parsed clients\n");
129 printf(" -S|--dumps Dump parsed servers\n");
130 printf(" -D|--nofork Do not daemonize\n");
131 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
132 printf(" -v|--version Print version\n");
133 printf(" -h|--help Print this help\n");
134 printf(" additional options for client:\n");
135 printf(" -c|--client[=alias] Client mode, server alias optional\n");
136 printf(" additional options for servers:\n");
137 printf(" -s|--server Server mode\n");
138 printf(" -N|--no-logging Disable server logging (for better anonymity)\n");
139 printf(" -p|--port <num> Port number (mandatory)\n");
140 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
141 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
142 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
143 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
144 printf(" (default: same as carrier protocol)\n");
146 printf("Example:\n");
147 printf(" See README.curvetun for a configuration example.\n");
148 printf(" curvetun --keygen\n");
149 printf(" curvetun --export\n");
150 printf(" curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n");
151 printf(" curvetun --client=ethz\n");
154 printf(" There is no default port specified, so that you are forced\n");
155 printf(" to select your own! For client/server status messages see syslog!\n");
157 printf("Secret ingredient: 7647-14-5\n");
159 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
160 printf("Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
161 printf("License: GNU GPL version 2\n");
162 printf("This is free software: you are free to change and redistribute it.\n");
163 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
167 static void version(void)
169 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
171 printf("Build: %s\n", BUILD_STRING
);
172 printf("http://www.netsniff-ng.org\n\n");
173 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
174 printf("Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
175 printf("License: GNU GPL version 2\n");
176 printf("This is free software: you are free to change and redistribute it.\n");
177 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
181 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
186 memset(path
, 0, sizeof(path
));
187 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
190 panic("No such file %s! Type --help for further information\n",
193 if (!S_ISREG(st
.st_mode
))
194 panic("%s is not a regular file!\n", path
);
196 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
197 panic("You have set too many permissions on %s (%o)!\n",
200 if (maybeempty
== 0 && st
.st_size
== 0)
201 panic("%s is empty!\n", path
);
204 static void check_config_exists_or_die(char *home
)
207 panic("No home dir specified!\n");
208 check_file_or_die(home
, FILE_CLIENTS
, 1);
209 check_file_or_die(home
, FILE_SERVERS
, 1);
210 check_file_or_die(home
, FILE_PRIVKEY
, 0);
211 check_file_or_die(home
, FILE_PUBKEY
, 0);
212 check_file_or_die(home
, FILE_USERNAM
, 0);
215 static char *fetch_home_dir(void)
217 char *home
= getenv("HOME");
219 panic("No HOME defined!\n");
223 static void write_username(char *home
)
226 char path
[PATH_MAX
], *eof
;
229 memset(path
, 0, sizeof(path
));
230 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
232 printf("Username: [%s] ", getenv("USER"));
235 memset(user
, 0, sizeof(user
));
236 eof
= fgets(user
, sizeof(user
), stdin
);
237 user
[sizeof(user
) - 1] = 0;
238 user
[strlen(user
) - 1] = 0; /* omit last \n */
240 if (strlen(user
) == 0)
241 strlcpy(user
, getenv("USER"), sizeof(user
));
243 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
245 panic("Cannot open your username file!\n");
246 ret
= write(fd
, user
, strlen(user
));
247 if (ret
!= strlen(user
))
248 panic("Could not write username!\n");
251 info("Username written to %s!\n", path
);
254 static void create_curvedir(char *home
)
259 memset(path
, 0, sizeof(path
));
260 slprintf(path
, sizeof(path
), "%s/%s", home
, ".curvetun/");
263 ret
= mkdir(path
, S_IRWXU
);
264 if (ret
< 0 && errno
!= EEXIST
)
265 panic("Cannot create curvetun dir!\n");
267 info("curvetun directory %s created!\n", path
);
269 /* We also create empty files for clients and servers! */
270 memset(path
, 0, sizeof(path
));
271 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CLIENTS
);
273 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
275 panic("Cannot open clients file!\n");
278 info("Empty client file written to %s!\n", path
);
280 memset(path
, 0, sizeof(path
));
281 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SERVERS
);
283 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
285 panic("Cannot open servers file!\n");
288 info("Empty server file written to %s!\n", path
);
291 static void create_keypair(char *home
)
295 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
296 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
298 const char * errstr
= NULL
;
301 info("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE
);
303 fd
= open_or_die(CURVETUN_ENTROPY_SOURCE
, O_RDONLY
);
304 ret
= read_exact(fd
, secretkey
, sizeof(secretkey
), 0);
305 if (ret
!= sizeof(secretkey
)) {
307 errstr
= "Cannot read from "CURVETUN_ENTROPY_SOURCE
"!\n";
312 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
314 memset(path
, 0, sizeof(path
));
315 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
317 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
320 errstr
= "Cannot open pubkey file!\n";
323 ret
= write(fd
, publickey
, sizeof(publickey
));
324 if (ret
!= sizeof(publickey
)) {
326 errstr
= "Cannot write public key!\n";
331 info("Public key written to %s!\n", path
);
333 memset(path
, 0, sizeof(path
));
334 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
336 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
339 errstr
= "Cannot open privkey file!\n";
343 ret
= write(fd
, secretkey
, sizeof(secretkey
));
344 if (ret
!= sizeof(secretkey
)) {
346 errstr
= "Cannot write private key!\n";
352 memset(publickey
, 0, sizeof(publickey
));
353 memset(secretkey
, 0, sizeof(secretkey
));
355 panic("%s: %s", errstr
, strerror(errno
));
357 info("Private key written to %s!\n", path
);
360 static void check_config_keypair_or_die(char *home
)
365 const char * errstr
= NULL
;
366 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
367 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
368 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
371 memset(path
, 0, sizeof(path
));
372 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
374 fd
= open(path
, O_RDONLY
);
377 errstr
= "Cannot open privkey file!\n";
380 ret
= read(fd
, secretkey
, sizeof(secretkey
));
381 if (ret
!= sizeof(secretkey
)) {
383 errstr
= "Cannot read private key!\n";
388 memset(path
, 0, sizeof(path
));
389 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
391 fd
= open(path
, O_RDONLY
);
394 errstr
= "Cannot open pubkey file!\n";
397 ret
= read(fd
, publickey
, sizeof(publickey
));
398 if (ret
!= sizeof(publickey
)) {
400 errstr
= "Cannot read public key!\n";
404 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
405 err
= crypto_verify_32(publicres
, publickey
);
408 errstr
= "WARNING: your keypair is corrupted!!! You need to "
409 "generate new keys!!!\n";
414 memset(publickey
, 0, sizeof(publickey
));
415 memset(publicres
, 0, sizeof(publicres
));
416 memset(secretkey
, 0, sizeof(secretkey
));
418 panic("%s: %s\n", errstr
, strerror(errno
));
421 static int main_keygen(char *home
)
423 create_curvedir(home
);
424 write_username(home
);
425 create_keypair(home
);
426 check_config_keypair_or_die(home
);
430 static int main_export(char *home
)
434 char path
[PATH_MAX
], tmp
[64];
436 check_config_exists_or_die(home
);
437 check_config_keypair_or_die(home
);
439 printf("Your exported public information:\n\n");
441 memset(path
, 0, sizeof(path
));
442 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
444 fd
= open_or_die(path
, O_RDONLY
);
445 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
446 ret
= write(STDOUT_FILENO
, tmp
, ret
);
452 memset(path
, 0, sizeof(path
));
453 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
455 fd
= open_or_die(path
, O_RDONLY
);
456 ret
= read(fd
, tmp
, sizeof(tmp
));
457 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
458 panic("Cannot read public key!\n");
459 for (i
= 0; i
< ret
; ++i
)
461 printf("%02x\n\n", (unsigned char) tmp
[i
]);
463 printf("%02x:", (unsigned char) tmp
[i
]);
470 static int main_dumpc(char *home
)
472 check_config_exists_or_die(home
);
473 check_config_keypair_or_die(home
);
475 printf("Your clients:\n\n");
477 parse_userfile_and_generate_user_store_or_die(home
);
479 destroy_user_store();
486 static int main_dumps(char *home
)
488 check_config_exists_or_die(home
);
489 check_config_keypair_or_die(home
);
491 printf("Your servers:\n\n");
493 parse_userfile_and_generate_serv_store_or_die(home
);
495 destroy_serv_store();
502 static void daemonize(const char *lockfile
)
505 mode_t lperm
= S_IRWXU
| S_IRGRP
| S_IXGRP
; /* 0750 */
512 panic("Cannot daemonize: %s", strerror(errno
));
517 lfp
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
, 0640);
519 syslog_panic("Cannot create lockfile at %s! "
520 "curvetun server already running?\n",
523 slprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
524 if (write(lfp
, pidstr
, strlen(pidstr
)) <= 0)
525 syslog_panic("Could not write pid to pidfile %s",
531 static int main_client(char *home
, char *dev
, char *alias
, int daemon
)
536 check_config_exists_or_die(home
);
537 check_config_keypair_or_die(home
);
539 parse_userfile_and_generate_serv_store_or_die(home
);
540 get_serv_store_entry_by_alias(alias
, alias
? strlen(alias
) + 1 : 0,
542 if (!host
|| !port
|| udp
< 0)
543 panic("Did not find alias/entry in configuration!\n");
544 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
545 alias
? : "default", host
, port
, udp
? "udp" : "tcp");
549 ret
= client_main(home
, dev
, host
, port
, udp
);
550 destroy_serv_store();
555 static int main_server(char *home
, char *dev
, char *port
, int udp
,
556 int ipv4
, int daemon
, int log
)
560 check_config_exists_or_die(home
);
561 check_config_keypair_or_die(home
);
564 ret
= server_main(home
, dev
, port
, udp
, ipv4
, log
);
570 int main(int argc
, char **argv
)
572 int ret
= 0, c
, opt_index
, udp
= 0, ipv4
= -1, daemon
= 1, log
= 1;
573 char *port
= NULL
, *stun
= NULL
, *dev
= NULL
, *home
= NULL
, *alias
=NULL
;
574 enum working_mode wmode
= MODE_UNKNOW
;
576 if (getuid() != geteuid())
578 if (getenv("LD_PRELOAD"))
579 panic("curvetun cannot be preloaded!\n");
580 if (ptrace(PTRACE_TRACEME
, 0, 1, 0) < 0)
581 panic("curvetun cannot be ptraced!\n");
583 home
= fetch_home_dir();
585 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
586 &opt_index
)) != EOF
) {
611 alias
= xstrdup(optarg
);
615 dev
= xstrdup(optarg
);
636 stun
= xstrdup(optarg
);
639 port
= xstrdup(optarg
);
647 panic("Option -%c requires an argument!\n",
651 whine("Unknown option character "
652 "`0x%X\'!\n", optopt
);
663 register_signal(SIGINT
, signal_handler
);
664 register_signal(SIGHUP
, signal_handler
);
665 register_signal(SIGTERM
, signal_handler
);
666 register_signal(SIGPIPE
, signal_handler
);
669 curve25519_selftest();
673 ret
= main_keygen(home
);
676 ret
= main_export(home
);
679 ret
= main_dumpc(home
);
682 ret
= main_dumps(home
);
685 ret
= main_client(home
, dev
, alias
, daemon
);
689 panic("No port specified!\n");
691 print_stun_probe(stun
, 3478, strtoul(port
, NULL
, 10));
692 ret
= main_server(home
, dev
, port
, udp
, ipv4
, daemon
, log
);