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 <daniel@netsniff-ng.org>,
6 * Subject to the GPL, version 2.
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <netinet/udp.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/epoll.h>
29 #include <arpa/inet.h>
30 #include <linux/if_tun.h>
39 #include "ct_usermgmt.h"
40 #include "ct_cpusched.h"
51 struct worker_struct
{
55 struct parent_info parent
;
56 int (*handler
)(int fd
, const struct worker_struct
*ws
,
57 char *buff
, size_t len
);
58 struct curve25519_struct
*c
;
61 static struct worker_struct
*threadpool
= NULL
;
63 static int auth_log
= 1;
65 extern volatile sig_atomic_t sigint
;
67 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
68 char *buff
, size_t len
) __pure
;
69 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
70 char *buff
, size_t len
) __pure
;
71 static int handler_udp(int fd
, const struct worker_struct
*ws
,
72 char *buff
, size_t len
) __pure
;
73 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
74 char *buff
, size_t len
) __pure
;
75 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
76 char *buff
, size_t len
) __pure
;
77 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
78 char *buff
, size_t len
) __pure
;
79 ssize_t
handler_tcp_read(int fd
, char *buff
, size_t len
);
80 static void *worker(void *self
) __pure
;
82 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
83 char *buff
, size_t len
)
87 ssize_t rlen
, err
, clen
;
89 struct curve25519_proto
*p
;
90 struct sockaddr_storage naddr
;
92 size_t off
= sizeof(struct ct_proto
) + crypto_box_zerobytes
;
94 if (!buff
|| len
<= off
)
98 while ((rlen
= read(fd
, buff
+ off
, len
- off
)) > 0) {
99 dfd
= -1; nlen
= 0; p
= NULL
;
101 memset(&naddr
, 0, sizeof(naddr
));
103 hdr
= (struct ct_proto
*) buff
;
104 memset(hdr
, 0, sizeof(*hdr
));
107 trie_addr_lookup(buff
+ off
, rlen
, ws
->parent
.ipv4
, &dfd
, &naddr
,
109 if (unlikely(dfd
< 0 || nlen
== 0)) {
110 memset(buff
, 0, len
);
114 err
= get_user_by_sockaddr(&naddr
, nlen
, &p
);
115 if (unlikely(err
|| !p
)) {
116 memset(buff
, 0, len
);
120 clen
= curve25519_encode(ws
->c
, p
, (unsigned char *) (buff
+ off
-
121 crypto_box_zerobytes
), (rlen
+
122 crypto_box_zerobytes
), (unsigned char **)
124 if (unlikely(clen
<= 0)) {
125 memset(buff
, 0, len
);
129 hdr
->payload
= htons((uint16_t) clen
);
133 sendto(dfd
, hdr
, sizeof(struct ct_proto
), 0, (struct sockaddr
*)
135 sendto(dfd
, cbuff
, clen
, 0, (struct sockaddr
*) &naddr
, nlen
);
139 memset(buff
, 0, len
);
145 static void handler_udp_notify_close(int fd
, struct sockaddr_storage
*addr
)
149 memset(&hdr
, 0, sizeof(hdr
));
150 hdr
.flags
|= PROTO_FLAG_EXIT
;
153 sendto(fd
, &hdr
, sizeof(hdr
), 0, (struct sockaddr
*) addr
,
157 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
158 char *buff
, size_t len
)
162 ssize_t rlen
, err
, clen
;
163 struct ct_proto
*hdr
;
164 struct curve25519_proto
*p
;
165 struct sockaddr_storage naddr
;
166 socklen_t nlen
= sizeof(naddr
);
171 memset(&naddr
, 0, sizeof(naddr
));
172 while ((rlen
= recvfrom(fd
, buff
, len
, 0, (struct sockaddr
*) &naddr
,
176 hdr
= (struct ct_proto
*) buff
;
178 if (unlikely(rlen
< sizeof(struct ct_proto
)))
180 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
182 if (unlikely(ntohs(hdr
->payload
) == 0))
184 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
186 remove_user_by_sockaddr(&naddr
, nlen
);
187 trie_addr_remove_addr(&naddr
, nlen
);
188 handler_udp_notify_close(fd
, &naddr
);
192 if (hdr
->flags
& PROTO_FLAG_INIT
) {
193 syslog_maybe(auth_log
, LOG_INFO
, "Got initial userhash "
194 "from remote end!\n");
196 if (unlikely(rlen
- sizeof(*hdr
) <
197 sizeof(struct username_struct
)))
200 err
= try_register_user_by_sockaddr(ws
->c
,
201 buff
+ sizeof(struct ct_proto
),
202 rlen
- sizeof(struct ct_proto
),
203 &naddr
, nlen
, auth_log
);
210 err
= get_user_by_sockaddr(&naddr
, nlen
, &p
);
211 if (unlikely(err
|| !p
))
214 clen
= curve25519_decode(ws
->c
, p
, (unsigned char *) buff
+
215 sizeof(struct ct_proto
),
216 rlen
- sizeof(struct ct_proto
),
217 (unsigned char **) &cbuff
, NULL
);
218 if (unlikely(clen
<= 0))
221 cbuff
+= crypto_box_zerobytes
;
222 clen
-= crypto_box_zerobytes
;
224 err
= trie_addr_maybe_update(cbuff
, clen
, ws
->parent
.ipv4
,
229 err
= write(ws
->parent
.tunfd
, cbuff
, clen
);
231 nlen
= sizeof(naddr
);
232 memset(&naddr
, 0, sizeof(naddr
));
238 static int handler_udp(int fd
, const struct worker_struct
*ws
,
239 char *buff
, size_t len
)
243 if (fd
== ws
->parent
.tunfd
)
244 ret
= handler_udp_tun_to_net(fd
, ws
, buff
, len
);
246 ret
= handler_udp_net_to_tun(fd
, ws
, buff
, len
);
251 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
252 char *buff
, size_t len
)
256 ssize_t rlen
, err
, clen
;
257 struct ct_proto
*hdr
;
258 struct curve25519_proto
*p
;
260 size_t off
= sizeof(struct ct_proto
) + crypto_box_zerobytes
;
262 if (!buff
|| len
<= off
)
265 memset(buff
, 0, len
);
266 while ((rlen
= read(fd
, buff
+ off
, len
- off
)) > 0) {
269 hdr
= (struct ct_proto
*) buff
;
270 memset(hdr
, 0, sizeof(*hdr
));
273 trie_addr_lookup(buff
+ off
, rlen
, ws
->parent
.ipv4
, &dfd
, NULL
,
275 if (unlikely(dfd
< 0)) {
276 memset(buff
, 0, len
);
280 err
= get_user_by_socket(dfd
, &p
);
281 if (unlikely(err
|| !p
)) {
282 memset(buff
, 0, len
);
286 clen
= curve25519_encode(ws
->c
, p
, (unsigned char *) (buff
+ off
-
287 crypto_box_zerobytes
), (rlen
+
288 crypto_box_zerobytes
), (unsigned char **)
290 if (unlikely(clen
<= 0)) {
291 memset(buff
, 0, len
);
295 hdr
->payload
= htons((uint16_t) clen
);
299 write_exact(dfd
, hdr
, sizeof(struct ct_proto
), 0);
300 write_exact(dfd
, cbuff
, clen
, 0);
304 memset(buff
, 0, len
);
310 ssize_t
handler_tcp_read(int fd
, char *buff
, size_t len
)
313 struct ct_proto
*hdr
= (struct ct_proto
*) buff
;
318 /* May exit on EAGAIN if 0 Byte read */
319 rlen
= read_exact(fd
, buff
, sizeof(struct ct_proto
), 1);
322 if (unlikely(ntohs(hdr
->payload
) > len
- sizeof(struct ct_proto
))) {
324 return 1; /* Force server to close connection */
327 /* May not exit on EAGAIN if 0 Byte read */
328 rlen
= read_exact(fd
, buff
+ sizeof(struct ct_proto
),
329 ntohs(hdr
->payload
), 0);
333 return sizeof(struct ct_proto
) + rlen
;
336 static void handler_tcp_notify_close(int fd
)
341 memset(&hdr
, 0, sizeof(hdr
));
342 hdr
.flags
|= PROTO_FLAG_EXIT
;
345 err
= write(fd
, &hdr
, sizeof(hdr
));
348 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
349 char *buff
, size_t len
)
351 int keep
= 1, count
= 0;
353 ssize_t rlen
, err
, clen
;
354 struct ct_proto
*hdr
;
355 struct curve25519_proto
*p
;
360 while ((rlen
= handler_tcp_read(fd
, buff
, len
)) > 0) {
363 hdr
= (struct ct_proto
*) buff
;
365 if (unlikely(rlen
< sizeof(struct ct_proto
)))
367 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
369 if (unlikely(ntohs(hdr
->payload
) == 0))
371 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
373 remove_user_by_socket(fd
);
374 trie_addr_remove(fd
);
375 handler_tcp_notify_close(fd
);
376 rlen
= write(ws
->parent
.efd
, &fd
, sizeof(fd
));
381 if (hdr
->flags
& PROTO_FLAG_INIT
) {
382 syslog_maybe(auth_log
, LOG_INFO
, "Got initial userhash "
383 "from remote end!\n");
385 if (unlikely(rlen
- sizeof(*hdr
) <
386 sizeof(struct username_struct
)))
389 err
= try_register_user_by_socket(ws
->c
,
390 buff
+ sizeof(struct ct_proto
),
391 rlen
- sizeof(struct ct_proto
),
399 err
= get_user_by_socket(fd
, &p
);
400 if (unlikely(err
|| !p
))
403 clen
= curve25519_decode(ws
->c
, p
, (unsigned char *) buff
+
404 sizeof(struct ct_proto
),
405 rlen
- sizeof(struct ct_proto
),
406 (unsigned char **) &cbuff
, NULL
);
407 if (unlikely(clen
<= 0))
410 cbuff
+= crypto_box_zerobytes
;
411 clen
-= crypto_box_zerobytes
;
413 err
= trie_addr_maybe_update(cbuff
, clen
, ws
->parent
.ipv4
,
418 err
= write(ws
->parent
.tunfd
, cbuff
, clen
);
422 write_exact(ws
->efd
[1], &fd
, sizeof(fd
), 1);
423 /* Read later next data and let others process */
431 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
432 char *buff
, size_t len
)
436 if (fd
== ws
->parent
.tunfd
)
437 ret
= handler_tcp_tun_to_net(fd
, ws
, buff
, len
);
439 ret
= handler_tcp_net_to_tun(fd
, ws
, buff
, len
);
444 static void *worker(void *self
)
448 size_t blen
= TUNBUFF_SIZ
; //FIXME
449 const struct worker_struct
*ws
= self
;
456 ret
= curve25519_alloc_or_maybe_die(ws
->c
);
458 syslog_panic("Cannot init curve25519!\n");
460 buff
= xmalloc_aligned(blen
, 64);
462 syslog(LOG_INFO
, "curvetun thread on CPU%u up!\n", ws
->cpu
);
464 pthread_cleanup_push(xfree_func
, ws
->c
);
465 pthread_cleanup_push(curve25519_free
, ws
->c
);
466 pthread_cleanup_push(xfree_func
, buff
);
468 while (likely(!sigint
)) {
470 if ((fds
.revents
& POLLIN
) != POLLIN
)
473 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &old_state
);
475 while ((ret
= read_exact(ws
->efd
[0], &fd
, sizeof(fd
), 1)) > 0) {
476 if (ret
!= sizeof(fd
)) {
481 ret
= ws
->handler(fd
, ws
, buff
, blen
);
483 write_exact(ws
->parent
.refd
, &fd
, sizeof(fd
), 1);
486 pthread_setcancelstate(old_state
, NULL
);
489 syslog(LOG_INFO
, "curvetun thread on CPU%u down!\n", ws
->cpu
);
491 pthread_cleanup_pop(1);
492 pthread_cleanup_pop(1);
493 pthread_cleanup_pop(1);
495 pthread_exit((void *) ((long) ws
->cpu
));
498 static void thread_spawn_or_panic(unsigned int cpus
, int efd
, int refd
,
499 int tunfd
, int ipv4
, int udp
)
503 unsigned int threads
;
505 threads
= cpus
* THREADS_PER_CPU
;
507 for (i
= 0; i
< threads
; ++i
) {
509 threadpool
[i
].cpu
= i
% cpus
;
510 CPU_SET(threadpool
[i
].cpu
, &cpuset
);
512 ret
= pipe2(threadpool
[i
].efd
, O_NONBLOCK
);
514 syslog_panic("Cannot create event socket!\n");
516 threadpool
[i
].c
= xmalloc_aligned(sizeof(*threadpool
[i
].c
), 64);
517 threadpool
[i
].parent
.efd
= efd
;
518 threadpool
[i
].parent
.refd
= refd
;
519 threadpool
[i
].parent
.tunfd
= tunfd
;
520 threadpool
[i
].parent
.ipv4
= ipv4
;
521 threadpool
[i
].parent
.udp
= udp
;
522 threadpool
[i
].handler
= udp
? handler_udp
: handler_tcp
;
524 ret
= pthread_create(&threadpool
[i
].trid
, NULL
,
525 worker
, &threadpool
[i
]);
527 syslog_panic("Thread creation failed!\n");
529 ret
= pthread_setaffinity_np(threadpool
[i
].trid
,
530 sizeof(cpuset
), &cpuset
);
532 syslog_panic("Thread CPU migration failed!\n");
534 pthread_detach(threadpool
[i
].trid
);
540 static void thread_finish(unsigned int cpus
)
543 unsigned int threads
;
545 threads
= cpus
* THREADS_PER_CPU
;
547 for (i
= 0; i
< threads
; ++i
) {
548 while (pthread_join(threadpool
[i
].trid
, NULL
) < 0)
551 close(threadpool
[i
].efd
[0]);
552 close(threadpool
[i
].efd
[1]);
556 int server_main(char *home
, char *dev
, char *port
, int udp
, int ipv4
, int log
)
558 int lfd
= -1, kdpfd
, nfds
, nfd
, curfds
, efd
[2], refd
[2], tunfd
, i
;
559 unsigned int cpus
= 0, threads
, udp_cpu
= 0;
561 struct epoll_event
*events
;
562 struct addrinfo hints
, *ahead
, *ai
;
565 openlog("curvetun", LOG_PID
| LOG_CONS
| LOG_NDELAY
, LOG_DAEMON
);
567 syslog(LOG_INFO
, "curvetun server booting!\n");
568 syslog_maybe(!auth_log
, LOG_INFO
, "curvetun user logging disabled!\n");
570 parse_userfile_and_generate_user_store_or_die(home
);
572 memset(&hints
, 0, sizeof(hints
));
573 hints
.ai_family
= PF_UNSPEC
;
574 hints
.ai_socktype
= udp
? SOCK_DGRAM
: SOCK_STREAM
;
575 hints
.ai_protocol
= udp
? IPPROTO_UDP
: IPPROTO_TCP
;
576 hints
.ai_flags
= AI_PASSIVE
;
578 ret
= getaddrinfo(NULL
, port
, &hints
, &ahead
);
580 syslog_panic("Cannot get address info!\n");
582 for (ai
= ahead
; ai
!= NULL
&& lfd
< 0; ai
= ai
->ai_next
) {
583 lfd
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
586 if (ai
->ai_family
== AF_INET6
) {
588 ret
= set_ipv6_only(lfd
);
598 #endif /* IPV6_V6ONLY */
602 set_mtu_disc_dont(lfd
);
604 ret
= bind(lfd
, ai
->ai_addr
, ai
->ai_addrlen
);
612 ret
= listen(lfd
, 5);
621 ipv4
= (ai
->ai_family
== AF_INET6
? 0 :
622 (ai
->ai_family
== AF_INET
? 1 : -1));
625 syslog_maybe(auth_log
, LOG_INFO
, "curvetun on IPv%d via %s "
626 "on port %s!\n", ai
->ai_family
== AF_INET
? 4 : 6,
627 udp
? "UDP" : "TCP", port
);
628 syslog_maybe(auth_log
, LOG_INFO
, "Allowed overlay proto is "
629 "IPv%d!\n", ipv4
? 4 : 6);
634 if (lfd
< 0 || ipv4
< 0)
635 syslog_panic("Cannot create socket!\n");
637 tunfd
= tun_open_or_die(dev
? dev
: DEVNAME_SERVER
, IFF_TUN
| IFF_NO_PI
);
639 pipe_or_die(efd
, O_NONBLOCK
);
640 pipe_or_die(refd
, O_NONBLOCK
);
642 set_nonblocking(lfd
);
644 events
= xzmalloc(MAX_EPOLL_SIZE
* sizeof(*events
));
645 for (i
= 0; i
< MAX_EPOLL_SIZE
; ++i
)
646 events
[i
].data
.fd
= -1;
648 kdpfd
= epoll_create(MAX_EPOLL_SIZE
);
650 syslog_panic("Cannot create socket!\n");
652 set_epoll_descriptor(kdpfd
, EPOLL_CTL_ADD
, lfd
,
653 udp
? EPOLLIN
| EPOLLET
| EPOLLONESHOT
: EPOLLIN
);
654 set_epoll_descriptor(kdpfd
, EPOLL_CTL_ADD
, efd
[0], EPOLLIN
);
655 set_epoll_descriptor(kdpfd
, EPOLL_CTL_ADD
, refd
[0], EPOLLIN
);
656 set_epoll_descriptor(kdpfd
, EPOLL_CTL_ADD
, tunfd
,
657 EPOLLIN
| EPOLLET
| EPOLLONESHOT
);
662 cpus
= get_number_cpus_online();
663 threads
= cpus
* THREADS_PER_CPU
;
664 if (!ispow2(threads
))
665 syslog_panic("Thread number not power of two!\n");
667 threadpool
= xzmalloc(sizeof(*threadpool
) * threads
);
668 thread_spawn_or_panic(cpus
, efd
[1], refd
[1], tunfd
, ipv4
, udp
);
670 init_cpusched(threads
);
672 register_socket(tunfd
);
673 register_socket(lfd
);
675 syslog(LOG_INFO
, "curvetun up and running!\n");
677 while (likely(!sigint
)) {
678 nfds
= epoll_wait(kdpfd
, events
, curfds
, -1);
680 syslog(LOG_ERR
, "epoll_wait error: %s\n",
685 for (i
= 0; i
< nfds
; ++i
) {
686 if (unlikely(events
[i
].data
.fd
< 0))
689 if (events
[i
].data
.fd
== lfd
&& !udp
) {
691 char hbuff
[256], sbuff
[256];
692 struct sockaddr_storage taddr
;
695 tlen
= sizeof(taddr
);
696 nfd
= accept(lfd
, (struct sockaddr
*) &taddr
,
699 syslog(LOG_ERR
, "accept error: %s\n",
704 if (curfds
+ 1 > MAX_EPOLL_SIZE
) {
711 ncpu
= register_socket(nfd
);
713 memset(hbuff
, 0, sizeof(hbuff
));
714 memset(sbuff
, 0, sizeof(sbuff
));
715 getnameinfo((struct sockaddr
*) &taddr
, tlen
,
716 hbuff
, sizeof(hbuff
),
717 sbuff
, sizeof(sbuff
),
718 NI_NUMERICHOST
| NI_NUMERICSERV
);
720 syslog_maybe(auth_log
, LOG_INFO
, "New connection "
721 "from %s:%s with id %d on CPU%d, %d "
722 "active!\n", hbuff
, sbuff
, nfd
, ncpu
,
725 set_nonblocking(nfd
);
726 set_socket_keepalive(nfd
);
727 set_tcp_nodelay(nfd
);
728 ret
= set_epoll_descriptor2(kdpfd
, EPOLL_CTL_ADD
,
729 nfd
, EPOLLIN
| EPOLLET
| EPOLLONESHOT
);
735 } else if (events
[i
].data
.fd
== refd
[0]) {
738 ret
= read_exact(refd
[0], &fd_one
,
740 if (ret
!= sizeof(fd_one
) || fd_one
<= 0)
743 ret
= set_epoll_descriptor2(kdpfd
, EPOLL_CTL_MOD
,
744 fd_one
, EPOLLIN
| EPOLLET
| EPOLLONESHOT
);
749 } else if (events
[i
].data
.fd
== efd
[0]) {
752 ret
= read_exact(efd
[0], &fd_del
,
754 if (ret
!= sizeof(fd_del
) || fd_del
<= 0)
757 ret
= read(fd_del
, &test
, sizeof(test
));
758 if (ret
< 0 && errno
== EBADF
)
761 ret
= set_epoll_descriptor2(kdpfd
, EPOLL_CTL_DEL
,
770 unregister_socket(fd_del
);
772 syslog_maybe(auth_log
, LOG_INFO
, "Closed connection "
773 "with id %d, %d active!\n", fd_del
,
776 int cpu
, fd_work
= events
[i
].data
.fd
;
779 cpu
= socket_to_cpu(fd_work
);
781 udp_cpu
= (udp_cpu
+ 1) & (threads
- 1);
783 write_exact(threadpool
[udp
? udp_cpu
: cpu
].efd
[1],
784 &fd_work
, sizeof(fd_work
), 1);
789 syslog(LOG_INFO
, "curvetun prepare shut down!\n");
803 unregister_socket(lfd
);
804 unregister_socket(tunfd
);
810 destroy_user_store();
812 syslog(LOG_INFO
, "curvetun shut down!\n");