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>,
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>
33 #include "write_or_die.h"
50 struct worker_struct
{
54 struct parent_info parent
;
55 int (*handler
)(int fd
, const struct worker_struct
*ws
,
56 char *buff
, size_t len
);
59 static struct worker_struct
*threadpool
= NULL
;
61 extern sig_atomic_t sigint
;
63 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
64 char *buff
, size_t len
) __pure
;
65 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
66 char *buff
, size_t len
) __pure
;
67 static int handler_udp(int fd
, const struct worker_struct
*ws
,
68 char *buff
, size_t len
) __pure
;
69 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
70 char *buff
, size_t len
) __pure
;
71 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
72 char *buff
, size_t len
) __pure
;
73 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
74 char *buff
, size_t len
) __pure
;
75 static void *worker(void *self
) __pure
;
77 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
78 char *buff
, size_t len
)
80 int dfd
, state
, keep
= 1;
82 ssize_t rlen
, err
, plen
;
84 struct sockaddr_storage naddr
;
88 while ((rlen
= read(fd
, buff
+ sizeof(struct ct_proto
),
89 len
- sizeof(struct ct_proto
))) > 0) {
92 memset(&naddr
, 0, sizeof(naddr
));
94 hdr
= (struct ct_proto
*) buff
;
95 hdr
->canary
= htons(CANARY
);
98 trie_addr_lookup(buff
+ sizeof(struct ct_proto
),
99 rlen
- sizeof(struct ct_proto
),
100 ws
->parent
.ipv4
, &dfd
, &naddr
,
103 if (dfd
< 0 || nlen
== 0) {
104 syslog(LOG_INFO
, "CPU%u: UDP tunnel lookup failed: "
105 "unknown destination\n", ws
->cpu
);
109 plen
= z_deflate(buff
+ sizeof(struct ct_proto
),
110 rlen
- sizeof(struct ct_proto
), &pbuff
);
112 syslog(LOG_ERR
, "CPU%u: UDP tunnel deflate error: %s\n",
113 ws
->cpu
, strerror(errno
));
117 hdr
->payload
= htons((uint16_t) plen
);
120 setsockopt(dfd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
122 err
= sendto(dfd
, hdr
, sizeof(struct ct_proto
), 0,
123 (struct sockaddr
*) &naddr
, nlen
);
125 syslog(LOG_ERR
, "CPU%u: UDP tunnel write error: %s\n",
126 ws
->cpu
, strerror(errno
));
128 err
= sendto(dfd
, pbuff
, plen
, 0, (struct sockaddr
*) &naddr
,
131 syslog(LOG_ERR
, "CPU%u: UDP tunnel write error: %s\n",
132 ws
->cpu
, strerror(errno
));
135 setsockopt(dfd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
140 if (rlen
< 0 && errno
!= EAGAIN
)
141 syslog(LOG_ERR
, "CPU%u: UDP tunnel read error: %s\n",
142 ws
->cpu
, strerror(errno
));
147 static void handler_udp_notify_close(int fd
, struct sockaddr_storage
*addr
,
153 memset(&hdr
, 0, sizeof(hdr
));
154 hdr
.flags
|= PROTO_FLAG_EXIT
;
156 hdr
.canary
= htons(CANARY
);
158 err
= sendto(fd
, &hdr
, sizeof(hdr
), 0, (struct sockaddr
*) addr
, len
);
161 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
162 char *buff
, size_t len
)
166 ssize_t rlen
, err
, plen
;
167 struct ct_proto
*hdr
;
168 struct sockaddr_storage naddr
;
171 nlen
= sizeof(naddr
);
172 memset(&naddr
, 0, sizeof(naddr
));
175 while ((rlen
= recvfrom(fd
, buff
, len
, 0, (struct sockaddr
*) &naddr
,
177 hdr
= (struct ct_proto
*) buff
;
179 if (unlikely(rlen
< sizeof(struct ct_proto
)))
181 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
183 if (unlikely(ntohs(hdr
->canary
) != CANARY
))
185 if (unlikely(ntohs(hdr
->payload
) == 0))
187 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
189 trie_addr_remove_addr(&naddr
, nlen
);
190 handler_udp_notify_close(fd
, &naddr
, nlen
);
191 nlen
= sizeof(naddr
);
192 memset(&naddr
, 0, sizeof(naddr
));
196 plen
= z_inflate(buff
+ sizeof(struct ct_proto
),
197 rlen
- sizeof(struct ct_proto
), &pbuff
);
199 syslog(LOG_ERR
, "CPU%u: UDP net inflate error: %s\n",
200 ws
->cpu
, strerror(errno
));
204 err
= trie_addr_maybe_update(pbuff
, plen
, ws
->parent
.ipv4
,
207 syslog(LOG_INFO
, "CPU%u: Malicious packet dropped "
208 "from id %d\n", ws
->cpu
, fd
);
212 err
= write(ws
->parent
.tunfd
, pbuff
, plen
);
214 syslog(LOG_ERR
, "CPU%u: UDP net write error: %s\n",
215 ws
->cpu
, strerror(errno
));
218 nlen
= sizeof(naddr
);
219 memset(&naddr
, 0, sizeof(naddr
));
223 if (rlen
< 0 && errno
!= EAGAIN
)
224 syslog(LOG_ERR
, "CPU%u: UDP net read error: %s\n",
225 ws
->cpu
, strerror(errno
));
230 static int handler_udp(int fd
, const struct worker_struct
*ws
,
231 char *buff
, size_t len
)
234 if (fd
== ws
->parent
.tunfd
)
235 ret
= handler_udp_tun_to_net(fd
, ws
, buff
, len
);
237 ret
= handler_udp_net_to_tun(fd
, ws
, buff
, len
);
241 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
242 char *buff
, size_t len
)
244 int dfd
, state
, keep
= 1;
246 ssize_t rlen
, err
, plen
;
247 struct ct_proto
*hdr
;
251 while ((rlen
= read(fd
, buff
+ sizeof(struct ct_proto
),
252 len
- sizeof(struct ct_proto
))) > 0) {
255 hdr
= (struct ct_proto
*) buff
;
256 hdr
->canary
= htons(CANARY
);
259 trie_addr_lookup(buff
+ sizeof(struct ct_proto
),
260 rlen
- sizeof(struct ct_proto
),
261 ws
->parent
.ipv4
, &dfd
, NULL
,
265 syslog(LOG_INFO
, "CPU%u: TCP tunnel lookup failed: "
266 "unknown destination\n", ws
->cpu
);
270 plen
= z_deflate(buff
+ sizeof(struct ct_proto
),
271 rlen
- sizeof(struct ct_proto
), &pbuff
);
273 syslog(LOG_ERR
, "CPU%u: TCP tunnel deflate error: %s\n",
274 ws
->cpu
, strerror(errno
));
278 hdr
->payload
= htons((uint16_t) plen
);
281 setsockopt(dfd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
283 err
= write_exact(dfd
, hdr
, sizeof(struct ct_proto
), 0);
285 syslog(LOG_ERR
, "CPU%u: TCP tunnel write error: %s\n",
286 ws
->cpu
, strerror(errno
));
288 err
= write_exact(dfd
, pbuff
, plen
, 0);
290 syslog(LOG_ERR
, "CPU%u: TCP tunnel write error: %s\n",
291 ws
->cpu
, strerror(errno
));
294 setsockopt(dfd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
299 if (rlen
< 0 && errno
!= EAGAIN
)
300 syslog(LOG_ERR
, "CPU%u: TCP tunnel read error: %s\n",
301 ws
->cpu
, strerror(errno
));
306 ssize_t
handler_tcp_read(int fd
, char *buff
, size_t len
)
309 struct ct_proto
*hdr
= (struct ct_proto
*) buff
;
311 /* May exit on EAGAIN if 0 Byte read */
312 rlen
= read_exact(fd
, buff
, sizeof(struct ct_proto
), 1);
316 /* May not exit on EAGAIN if 0 Byte read */
317 rlen
= read_exact(fd
, buff
+ sizeof(struct ct_proto
),
318 ntohs(hdr
->payload
), 0);
322 return sizeof(struct ct_proto
) + rlen
;
325 static void handler_tcp_notify_close(int fd
)
330 memset(&hdr
, 0, sizeof(hdr
));
331 hdr
.flags
|= PROTO_FLAG_EXIT
;
333 hdr
.canary
= htons(CANARY
);
335 err
= write(fd
, &hdr
, sizeof(hdr
));
338 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
339 char *buff
, size_t len
)
341 int keep
= 1, count
= 0;
343 ssize_t rlen
, err
, plen
;
344 struct ct_proto
*hdr
;
348 while ((rlen
= handler_tcp_read(fd
, buff
, len
)) > 0) {
349 hdr
= (struct ct_proto
*) buff
;
351 if (unlikely(rlen
< sizeof(struct ct_proto
)))
353 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
355 if (unlikely(ntohs(hdr
->canary
) != CANARY
))
357 if (unlikely(ntohs(hdr
->payload
) == 0))
359 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
362 trie_addr_remove(fd
);
363 handler_tcp_notify_close(fd
);
364 rlen
= write(ws
->parent
.efd
, &fd64
, sizeof(fd64
));
365 if (rlen
!= sizeof(fd64
))
366 syslog(LOG_ERR
, "CPU%u: TCP event write error: %s\n",
367 ws
->cpu
, strerror(errno
));
372 plen
= z_inflate(buff
+ sizeof(struct ct_proto
),
373 rlen
- sizeof(struct ct_proto
), &pbuff
);
375 syslog(LOG_ERR
, "CPU%u: TCP net inflate error: %s\n",
376 ws
->cpu
, strerror(errno
));
380 err
= trie_addr_maybe_update(pbuff
, plen
, ws
->parent
.ipv4
,
383 syslog(LOG_INFO
, "CPU%u: Malicious packet dropped "
384 "from id %d\n", ws
->cpu
, fd
);
388 err
= write(ws
->parent
.tunfd
, pbuff
, plen
);
390 syslog(LOG_ERR
, "CPU%u: TCP net write error: %s\n",
391 ws
->cpu
, strerror(errno
));
395 err
= write_exact(ws
->efd
[1], &fd
, sizeof(fd
), 1);
396 if (err
!= sizeof(fd
))
397 syslog(LOG_ERR
, "CPU%u: TCP net put fd back in "
398 "pipe error: %s\n", ws
->cpu
, strerror(errno
));
405 if (rlen
< 0 && errno
!= EAGAIN
&& errno
!= EBADF
)
406 syslog(LOG_ERR
, "CPU%u: TCP net read error: %s\n",
407 ws
->cpu
, strerror(errno
));
412 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
413 char *buff
, size_t len
)
416 if (fd
== ws
->parent
.tunfd
)
417 ret
= handler_tcp_tun_to_net(fd
, ws
, buff
, len
);
419 ret
= handler_tcp_net_to_tun(fd
, ws
, buff
, len
);
423 static void *worker(void *self
)
427 size_t blen
= TUNBUFF_SIZ
; //FIXME
428 const struct worker_struct
*ws
= self
;
435 buff
= xmalloc(blen
);
436 syslog(LOG_INFO
, "curvetun thread on CPU%u up!\n", ws
->cpu
);
437 pthread_cleanup_push(xfree
, buff
);
439 while (likely(!sigint
)) {
441 if ((fds
.revents
& POLLIN
) != POLLIN
)
443 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &old_state
);
444 while ((ret
= read_exact(ws
->efd
[0], &fd
, sizeof(fd
), 1)) > 0) {
445 if (ret
!= sizeof(fd
)) {
446 syslog(LOG_ERR
, "CPU%u: Thread could not read "
447 "event descriptor!\n", ws
->cpu
);
452 ret
= ws
->handler(fd
, ws
, buff
, blen
);
454 ret
= write_exact(ws
->parent
.refd
, &fd
, sizeof(fd
), 1);
455 if (ret
!= sizeof(fd
))
456 syslog(LOG_ERR
, "CPU%u: Retriggering failed: "
457 "%s\n", ws
->cpu
, strerror(errno
));
460 pthread_setcancelstate(old_state
, NULL
);
463 syslog(LOG_INFO
, "curvetun thread on CPU%u down!\n", ws
->cpu
);
464 pthread_cleanup_pop(1);
465 pthread_exit((void *) ((long) ws
->cpu
));
468 static void thread_spawn_or_panic(unsigned int cpus
, int efd
, int refd
,
469 int tunfd
, int ipv4
, int udp
)
473 unsigned int threads
;
475 threads
= cpus
* THREADS_PER_CPU
;
476 for (i
= 0; i
< threads
; ++i
) {
478 threadpool
[i
].cpu
= i
% cpus
;
479 CPU_SET(threadpool
[i
].cpu
, &cpuset
);
481 ret
= pipe2(threadpool
[i
].efd
, O_NONBLOCK
);
483 panic("Cannot create event socket!\n");
485 threadpool
[i
].parent
.efd
= efd
;
486 threadpool
[i
].parent
.refd
= refd
;
487 threadpool
[i
].parent
.tunfd
= tunfd
;
488 threadpool
[i
].parent
.ipv4
= ipv4
;
489 threadpool
[i
].parent
.udp
= udp
;
490 threadpool
[i
].handler
= udp
? handler_udp
: handler_tcp
;
492 ret
= pthread_create(&threadpool
[i
].trid
, NULL
,
493 worker
, &threadpool
[i
]);
495 panic("Thread creation failed!\n");
497 ret
= pthread_setaffinity_np(threadpool
[i
].trid
,
498 sizeof(cpu_set_t
), &cpuset
);
500 panic("Thread CPU migration failed!\n");
502 pthread_detach(threadpool
[i
].trid
);
508 static void thread_finish(unsigned int cpus
)
511 unsigned int threads
;
513 threads
= cpus
* THREADS_PER_CPU
;
514 for (i
= 0; i
< threads
; ++i
) {
515 ret
= pthread_join(threadpool
[i
].trid
, NULL
);
518 close(threadpool
[i
].efd
[0]);
519 close(threadpool
[i
].efd
[1]);
523 int server_main(int port
, int udp
, int lnum
)
525 int lfd
= -1, kdpfd
, nfds
, nfd
, curfds
, efd
[2], refd
[2], tunfd
;
527 unsigned int cpus
= 0, threads
;
529 struct epoll_event ev
, *events
;
530 struct addrinfo hints
, *ahead
, *ai
;
532 openlog("curvetun", LOG_PID
| LOG_CONS
| LOG_NDELAY
, LOG_DAEMON
);
533 syslog(LOG_INFO
, "curvetun server booting!\n");
535 ret
= z_alloc_or_maybe_die(Z_DEFAULT_COMPRESSION
);
537 panic("Cannot init zLib!\n");
539 memset(&hints
, 0, sizeof(hints
));
540 hints
.ai_family
= PF_UNSPEC
;
541 hints
.ai_socktype
= udp
? SOCK_DGRAM
: SOCK_STREAM
;
542 hints
.ai_protocol
= udp
? IPPROTO_UDP
: IPPROTO_TCP
;
543 hints
.ai_flags
= AI_PASSIVE
;
545 ret
= getaddrinfo(NULL
, "6666", &hints
, &ahead
);
547 panic("Cannot get address info!\n");
549 for (ai
= ahead
; ai
!= NULL
&& lfd
< 0; ai
= ai
->ai_next
) {
550 lfd
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
553 if (ai
->ai_family
== AF_INET6
) {
556 ret
= setsockopt(lfd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
567 #endif /* IPV6_V6ONLY */
570 ret
= bind(lfd
, ai
->ai_addr
, ai
->ai_addrlen
);
577 ret
= listen(lfd
, 5);
584 ipv4
= (ai
->ai_family
== AF_INET6
? 0 :
585 (ai
->ai_family
== AF_INET
? 1 : -1));
586 syslog(LOG_INFO
, "curvetun on IPv%d via %s!\n",
587 ipv4
? 4 : 6, udp
? "UDP" : "TCP");
591 if (lfd
< 0 || ipv4
< 0)
592 panic("Cannot create socket!\n");
594 tunfd
= tun_open_or_die(DEVNAME_SERVER
);
596 ret
= pipe2(efd
, O_NONBLOCK
);
598 panic("Cannot create parent event fd!\n");
600 ret
= pipe2(refd
, O_NONBLOCK
);
602 panic("Cannot create parent (r)event fd!\n");
604 set_nonblocking(lfd
);
606 events
= xzmalloc(MAX_EPOLL_SIZE
* sizeof(*events
));
607 for (i
= 0; i
< MAX_EPOLL_SIZE
; ++i
)
608 events
[i
].data
.fd
= -1;
610 kdpfd
= epoll_create(MAX_EPOLL_SIZE
);
612 panic("Cannot create socket!\n");
614 memset(&ev
, 0, sizeof(ev
));
615 ev
.events
= udp
? EPOLLIN
| EPOLLET
| EPOLLONESHOT
: EPOLLIN
;
617 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, lfd
, &ev
);
619 panic("Cannot add socket for epoll!\n");
621 memset(&ev
, 0, sizeof(ev
));
624 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, efd
[0], &ev
);
626 panic("Cannot add socket for events!\n");
628 memset(&ev
, 0, sizeof(ev
));
630 ev
.data
.fd
= refd
[0];
631 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, refd
[0], &ev
);
633 panic("Cannot add socket for (r)events!\n");
635 memset(&ev
, 0, sizeof(ev
));
636 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
638 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, tunfd
, &ev
);
640 panic("Cannot add socket for tundev!\n");
646 cpus
= get_number_cpus_online();
647 threads
= cpus
* THREADS_PER_CPU
;
648 if (!((threads
!= 0) && ((threads
& (threads
- 1)) == 0)))
649 panic("thread number not power of two!\n");
650 threadpool
= xzmalloc(sizeof(*threadpool
) * threads
);
651 thread_spawn_or_panic(cpus
, efd
[1], refd
[1], tunfd
, ipv4
, udp
);
653 init_cpusched(threads
, MAX_EPOLL_SIZE
);
654 register_socket(tunfd
);
655 register_socket(lfd
);
657 syslog(LOG_INFO
, "tunnel id: %d, listener id: %d\n", tunfd
, lfd
);
658 syslog(LOG_INFO
, "curvetun up and running!\n");
660 while (likely(!sigint
)) {
661 nfds
= epoll_wait(kdpfd
, events
, curfds
, -1);
663 syslog(LOG_ERR
, "epoll_wait error: %s\n",
668 for (i
= 0; i
< nfds
; ++i
) {
669 if (unlikely(events
[i
].data
.fd
< 0))
671 if (events
[i
].data
.fd
== lfd
&& !udp
) {
673 char hbuff
[256], sbuff
[256];
674 struct sockaddr_storage taddr
;
677 tlen
= sizeof(taddr
);
678 nfd
= accept(lfd
, (struct sockaddr
*) &taddr
,
681 syslog(LOG_ERR
, "accept error: %s\n",
686 if (curfds
+ 1 > MAX_EPOLL_SIZE
) {
692 ncpu
= register_socket(nfd
);
694 memset(hbuff
, 0, sizeof(hbuff
));
695 memset(sbuff
, 0, sizeof(sbuff
));
697 getnameinfo((struct sockaddr
*) &taddr
, tlen
,
698 hbuff
, sizeof(hbuff
),
699 sbuff
, sizeof(sbuff
),
700 NI_NUMERICHOST
| NI_NUMERICSERV
);
702 syslog(LOG_INFO
, "New connection from %s:%s "
703 "with id %d on CPU%d, %d active!\n",
704 hbuff
, sbuff
, nfd
, ncpu
, curfds
);
706 set_nonblocking(nfd
);
709 setsockopt(nfd
, SOL_SOCKET
, SO_KEEPALIVE
,
712 setsockopt(nfd
, IPPROTO_TCP
, TCP_NODELAY
,
715 memset(&ev
, 0, sizeof(ev
));
716 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
718 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, nfd
, &ev
);
720 syslog(LOG_ERR
, "Epoll ctl add error"
721 "on id %d: %s\n", nfd
,
727 } else if (events
[i
].data
.fd
== refd
[0]) {
730 ret
= read_exact(refd
[0], &fd_one
, sizeof(fd_one
), 1);
731 if (ret
!= sizeof(fd_one
) || fd_one
<= 0)
734 memset(&ev
, 0, sizeof(ev
));
735 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
737 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_MOD
, fd_one
, &ev
);
739 syslog(LOG_ERR
, "Epoll ctl mod "
740 "error on id %d: %s\n",
741 fd_one
, strerror(errno
));
745 } else if (events
[i
].data
.fd
== efd
[0]) {
748 ret
= read_exact(efd
[0], &fd_del
, sizeof(fd_del
), 1);
749 if (ret
!= sizeof(fd_del
) || fd_del
<= 0)
752 ret
= read(fd_del
, &test
, sizeof(test
));
753 if (ret
< 0 && errno
== EBADF
)
756 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_DEL
, fd_del
, &ev
);
758 syslog(LOG_ERR
, "Epoll ctl del "
759 "error on id %d: %s\n",
760 fd_del
, strerror(errno
));
766 unregister_socket(fd_del
);
768 syslog(LOG_INFO
, "Closed connection with "
769 "id %d, %d active!\n",
772 int cpu
, fd_work
= events
[i
].data
.fd
;
773 cpu
= socket_to_cpu(fd_work
);
775 ret
= write_exact(threadpool
[cpu
].efd
[1],
776 &fd_work
, sizeof(fd_work
), 1);
777 if (ret
!= sizeof(fd_work
))
778 syslog(LOG_ERR
, "Write error on event "
779 "dispatch: %s\n", strerror(errno
));
784 syslog(LOG_INFO
, "curvetun prepare shut down!\n");
797 unregister_socket(lfd
);
798 unregister_socket(tunfd
);
803 syslog(LOG_INFO
, "curvetun shut down!\n");