1*c43e99fdSEd Maste /* 2*c43e99fdSEd Maste This example code shows how to write an (optionally encrypting) SSL proxy 3*c43e99fdSEd Maste with Libevent's bufferevent layer. 4*c43e99fdSEd Maste 5*c43e99fdSEd Maste XXX It's a little ugly and should probably be cleaned up. 6*c43e99fdSEd Maste */ 7*c43e99fdSEd Maste 8*c43e99fdSEd Maste // Get rid of OSX 10.7 and greater deprecation warnings. 9*c43e99fdSEd Maste #if defined(__APPLE__) && defined(__clang__) 10*c43e99fdSEd Maste #pragma clang diagnostic ignored "-Wdeprecated-declarations" 11*c43e99fdSEd Maste #endif 12*c43e99fdSEd Maste 13*c43e99fdSEd Maste #include <stdio.h> 14*c43e99fdSEd Maste #include <assert.h> 15*c43e99fdSEd Maste #include <stdlib.h> 16*c43e99fdSEd Maste #include <string.h> 17*c43e99fdSEd Maste #include <errno.h> 18*c43e99fdSEd Maste 19*c43e99fdSEd Maste #ifdef _WIN32 20*c43e99fdSEd Maste #include <winsock2.h> 21*c43e99fdSEd Maste #include <ws2tcpip.h> 22*c43e99fdSEd Maste #else 23*c43e99fdSEd Maste #include <sys/socket.h> 24*c43e99fdSEd Maste #include <netinet/in.h> 25*c43e99fdSEd Maste #endif 26*c43e99fdSEd Maste 27*c43e99fdSEd Maste #include <event2/bufferevent_ssl.h> 28*c43e99fdSEd Maste #include <event2/bufferevent.h> 29*c43e99fdSEd Maste #include <event2/buffer.h> 30*c43e99fdSEd Maste #include <event2/listener.h> 31*c43e99fdSEd Maste #include <event2/util.h> 32*c43e99fdSEd Maste 33*c43e99fdSEd Maste #include <openssl/ssl.h> 34*c43e99fdSEd Maste #include <openssl/err.h> 35*c43e99fdSEd Maste #include <openssl/rand.h> 36*c43e99fdSEd Maste #include "openssl-compat.h" 37*c43e99fdSEd Maste 38*c43e99fdSEd Maste static struct event_base *base; 39*c43e99fdSEd Maste static struct sockaddr_storage listen_on_addr; 40*c43e99fdSEd Maste static struct sockaddr_storage connect_to_addr; 41*c43e99fdSEd Maste static int connect_to_addrlen; 42*c43e99fdSEd Maste static int use_wrapper = 1; 43*c43e99fdSEd Maste 44*c43e99fdSEd Maste static SSL_CTX *ssl_ctx = NULL; 45*c43e99fdSEd Maste 46*c43e99fdSEd Maste #define MAX_OUTPUT (512*1024) 47*c43e99fdSEd Maste 48*c43e99fdSEd Maste static void drained_writecb(struct bufferevent *bev, void *ctx); 49*c43e99fdSEd Maste static void eventcb(struct bufferevent *bev, short what, void *ctx); 50*c43e99fdSEd Maste 51*c43e99fdSEd Maste static void 52*c43e99fdSEd Maste readcb(struct bufferevent *bev, void *ctx) 53*c43e99fdSEd Maste { 54*c43e99fdSEd Maste struct bufferevent *partner = ctx; 55*c43e99fdSEd Maste struct evbuffer *src, *dst; 56*c43e99fdSEd Maste size_t len; 57*c43e99fdSEd Maste src = bufferevent_get_input(bev); 58*c43e99fdSEd Maste len = evbuffer_get_length(src); 59*c43e99fdSEd Maste if (!partner) { 60*c43e99fdSEd Maste evbuffer_drain(src, len); 61*c43e99fdSEd Maste return; 62*c43e99fdSEd Maste } 63*c43e99fdSEd Maste dst = bufferevent_get_output(partner); 64*c43e99fdSEd Maste evbuffer_add_buffer(dst, src); 65*c43e99fdSEd Maste 66*c43e99fdSEd Maste if (evbuffer_get_length(dst) >= MAX_OUTPUT) { 67*c43e99fdSEd Maste /* We're giving the other side data faster than it can 68*c43e99fdSEd Maste * pass it on. Stop reading here until we have drained the 69*c43e99fdSEd Maste * other side to MAX_OUTPUT/2 bytes. */ 70*c43e99fdSEd Maste bufferevent_setcb(partner, readcb, drained_writecb, 71*c43e99fdSEd Maste eventcb, bev); 72*c43e99fdSEd Maste bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2, 73*c43e99fdSEd Maste MAX_OUTPUT); 74*c43e99fdSEd Maste bufferevent_disable(bev, EV_READ); 75*c43e99fdSEd Maste } 76*c43e99fdSEd Maste } 77*c43e99fdSEd Maste 78*c43e99fdSEd Maste static void 79*c43e99fdSEd Maste drained_writecb(struct bufferevent *bev, void *ctx) 80*c43e99fdSEd Maste { 81*c43e99fdSEd Maste struct bufferevent *partner = ctx; 82*c43e99fdSEd Maste 83*c43e99fdSEd Maste /* We were choking the other side until we drained our outbuf a bit. 84*c43e99fdSEd Maste * Now it seems drained. */ 85*c43e99fdSEd Maste bufferevent_setcb(bev, readcb, NULL, eventcb, partner); 86*c43e99fdSEd Maste bufferevent_setwatermark(bev, EV_WRITE, 0, 0); 87*c43e99fdSEd Maste if (partner) 88*c43e99fdSEd Maste bufferevent_enable(partner, EV_READ); 89*c43e99fdSEd Maste } 90*c43e99fdSEd Maste 91*c43e99fdSEd Maste static void 92*c43e99fdSEd Maste close_on_finished_writecb(struct bufferevent *bev, void *ctx) 93*c43e99fdSEd Maste { 94*c43e99fdSEd Maste struct evbuffer *b = bufferevent_get_output(bev); 95*c43e99fdSEd Maste 96*c43e99fdSEd Maste if (evbuffer_get_length(b) == 0) { 97*c43e99fdSEd Maste bufferevent_free(bev); 98*c43e99fdSEd Maste } 99*c43e99fdSEd Maste } 100*c43e99fdSEd Maste 101*c43e99fdSEd Maste static void 102*c43e99fdSEd Maste eventcb(struct bufferevent *bev, short what, void *ctx) 103*c43e99fdSEd Maste { 104*c43e99fdSEd Maste struct bufferevent *partner = ctx; 105*c43e99fdSEd Maste 106*c43e99fdSEd Maste if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { 107*c43e99fdSEd Maste if (what & BEV_EVENT_ERROR) { 108*c43e99fdSEd Maste unsigned long err; 109*c43e99fdSEd Maste while ((err = (bufferevent_get_openssl_error(bev)))) { 110*c43e99fdSEd Maste const char *msg = (const char*) 111*c43e99fdSEd Maste ERR_reason_error_string(err); 112*c43e99fdSEd Maste const char *lib = (const char*) 113*c43e99fdSEd Maste ERR_lib_error_string(err); 114*c43e99fdSEd Maste const char *func = (const char*) 115*c43e99fdSEd Maste ERR_func_error_string(err); 116*c43e99fdSEd Maste fprintf(stderr, 117*c43e99fdSEd Maste "%s in %s %s\n", msg, lib, func); 118*c43e99fdSEd Maste } 119*c43e99fdSEd Maste if (errno) 120*c43e99fdSEd Maste perror("connection error"); 121*c43e99fdSEd Maste } 122*c43e99fdSEd Maste 123*c43e99fdSEd Maste if (partner) { 124*c43e99fdSEd Maste /* Flush all pending data */ 125*c43e99fdSEd Maste readcb(bev, ctx); 126*c43e99fdSEd Maste 127*c43e99fdSEd Maste if (evbuffer_get_length( 128*c43e99fdSEd Maste bufferevent_get_output(partner))) { 129*c43e99fdSEd Maste /* We still have to flush data from the other 130*c43e99fdSEd Maste * side, but when that's done, close the other 131*c43e99fdSEd Maste * side. */ 132*c43e99fdSEd Maste bufferevent_setcb(partner, 133*c43e99fdSEd Maste NULL, close_on_finished_writecb, 134*c43e99fdSEd Maste eventcb, NULL); 135*c43e99fdSEd Maste bufferevent_disable(partner, EV_READ); 136*c43e99fdSEd Maste } else { 137*c43e99fdSEd Maste /* We have nothing left to say to the other 138*c43e99fdSEd Maste * side; close it. */ 139*c43e99fdSEd Maste bufferevent_free(partner); 140*c43e99fdSEd Maste } 141*c43e99fdSEd Maste } 142*c43e99fdSEd Maste bufferevent_free(bev); 143*c43e99fdSEd Maste } 144*c43e99fdSEd Maste } 145*c43e99fdSEd Maste 146*c43e99fdSEd Maste static void 147*c43e99fdSEd Maste syntax(void) 148*c43e99fdSEd Maste { 149*c43e99fdSEd Maste fputs("Syntax:\n", stderr); 150*c43e99fdSEd Maste fputs(" le-proxy [-s] [-W] <listen-on-addr> <connect-to-addr>\n", stderr); 151*c43e99fdSEd Maste fputs("Example:\n", stderr); 152*c43e99fdSEd Maste fputs(" le-proxy 127.0.0.1:8888 1.2.3.4:80\n", stderr); 153*c43e99fdSEd Maste 154*c43e99fdSEd Maste exit(1); 155*c43e99fdSEd Maste } 156*c43e99fdSEd Maste 157*c43e99fdSEd Maste static void 158*c43e99fdSEd Maste accept_cb(struct evconnlistener *listener, evutil_socket_t fd, 159*c43e99fdSEd Maste struct sockaddr *a, int slen, void *p) 160*c43e99fdSEd Maste { 161*c43e99fdSEd Maste struct bufferevent *b_out, *b_in; 162*c43e99fdSEd Maste /* Create two linked bufferevent objects: one to connect, one for the 163*c43e99fdSEd Maste * new connection */ 164*c43e99fdSEd Maste b_in = bufferevent_socket_new(base, fd, 165*c43e99fdSEd Maste BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 166*c43e99fdSEd Maste 167*c43e99fdSEd Maste if (!ssl_ctx || use_wrapper) 168*c43e99fdSEd Maste b_out = bufferevent_socket_new(base, -1, 169*c43e99fdSEd Maste BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 170*c43e99fdSEd Maste else { 171*c43e99fdSEd Maste SSL *ssl = SSL_new(ssl_ctx); 172*c43e99fdSEd Maste b_out = bufferevent_openssl_socket_new(base, -1, ssl, 173*c43e99fdSEd Maste BUFFEREVENT_SSL_CONNECTING, 174*c43e99fdSEd Maste BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 175*c43e99fdSEd Maste } 176*c43e99fdSEd Maste 177*c43e99fdSEd Maste assert(b_in && b_out); 178*c43e99fdSEd Maste 179*c43e99fdSEd Maste if (bufferevent_socket_connect(b_out, 180*c43e99fdSEd Maste (struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) { 181*c43e99fdSEd Maste perror("bufferevent_socket_connect"); 182*c43e99fdSEd Maste bufferevent_free(b_out); 183*c43e99fdSEd Maste bufferevent_free(b_in); 184*c43e99fdSEd Maste return; 185*c43e99fdSEd Maste } 186*c43e99fdSEd Maste 187*c43e99fdSEd Maste if (ssl_ctx && use_wrapper) { 188*c43e99fdSEd Maste struct bufferevent *b_ssl; 189*c43e99fdSEd Maste SSL *ssl = SSL_new(ssl_ctx); 190*c43e99fdSEd Maste b_ssl = bufferevent_openssl_filter_new(base, 191*c43e99fdSEd Maste b_out, ssl, BUFFEREVENT_SSL_CONNECTING, 192*c43e99fdSEd Maste BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS); 193*c43e99fdSEd Maste if (!b_ssl) { 194*c43e99fdSEd Maste perror("Bufferevent_openssl_new"); 195*c43e99fdSEd Maste bufferevent_free(b_out); 196*c43e99fdSEd Maste bufferevent_free(b_in); 197*c43e99fdSEd Maste } 198*c43e99fdSEd Maste b_out = b_ssl; 199*c43e99fdSEd Maste } 200*c43e99fdSEd Maste 201*c43e99fdSEd Maste bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out); 202*c43e99fdSEd Maste bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in); 203*c43e99fdSEd Maste 204*c43e99fdSEd Maste bufferevent_enable(b_in, EV_READ|EV_WRITE); 205*c43e99fdSEd Maste bufferevent_enable(b_out, EV_READ|EV_WRITE); 206*c43e99fdSEd Maste } 207*c43e99fdSEd Maste 208*c43e99fdSEd Maste int 209*c43e99fdSEd Maste main(int argc, char **argv) 210*c43e99fdSEd Maste { 211*c43e99fdSEd Maste int i; 212*c43e99fdSEd Maste int socklen; 213*c43e99fdSEd Maste 214*c43e99fdSEd Maste int use_ssl = 0; 215*c43e99fdSEd Maste struct evconnlistener *listener; 216*c43e99fdSEd Maste 217*c43e99fdSEd Maste if (argc < 3) 218*c43e99fdSEd Maste syntax(); 219*c43e99fdSEd Maste 220*c43e99fdSEd Maste for (i=1; i < argc; ++i) { 221*c43e99fdSEd Maste if (!strcmp(argv[i], "-s")) { 222*c43e99fdSEd Maste use_ssl = 1; 223*c43e99fdSEd Maste } else if (!strcmp(argv[i], "-W")) { 224*c43e99fdSEd Maste use_wrapper = 0; 225*c43e99fdSEd Maste } else if (argv[i][0] == '-') { 226*c43e99fdSEd Maste syntax(); 227*c43e99fdSEd Maste } else 228*c43e99fdSEd Maste break; 229*c43e99fdSEd Maste } 230*c43e99fdSEd Maste 231*c43e99fdSEd Maste if (i+2 != argc) 232*c43e99fdSEd Maste syntax(); 233*c43e99fdSEd Maste 234*c43e99fdSEd Maste memset(&listen_on_addr, 0, sizeof(listen_on_addr)); 235*c43e99fdSEd Maste socklen = sizeof(listen_on_addr); 236*c43e99fdSEd Maste if (evutil_parse_sockaddr_port(argv[i], 237*c43e99fdSEd Maste (struct sockaddr*)&listen_on_addr, &socklen)<0) { 238*c43e99fdSEd Maste int p = atoi(argv[i]); 239*c43e99fdSEd Maste struct sockaddr_in *sin = (struct sockaddr_in*)&listen_on_addr; 240*c43e99fdSEd Maste if (p < 1 || p > 65535) 241*c43e99fdSEd Maste syntax(); 242*c43e99fdSEd Maste sin->sin_port = htons(p); 243*c43e99fdSEd Maste sin->sin_addr.s_addr = htonl(0x7f000001); 244*c43e99fdSEd Maste sin->sin_family = AF_INET; 245*c43e99fdSEd Maste socklen = sizeof(struct sockaddr_in); 246*c43e99fdSEd Maste } 247*c43e99fdSEd Maste 248*c43e99fdSEd Maste memset(&connect_to_addr, 0, sizeof(connect_to_addr)); 249*c43e99fdSEd Maste connect_to_addrlen = sizeof(connect_to_addr); 250*c43e99fdSEd Maste if (evutil_parse_sockaddr_port(argv[i+1], 251*c43e99fdSEd Maste (struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) 252*c43e99fdSEd Maste syntax(); 253*c43e99fdSEd Maste 254*c43e99fdSEd Maste base = event_base_new(); 255*c43e99fdSEd Maste if (!base) { 256*c43e99fdSEd Maste perror("event_base_new()"); 257*c43e99fdSEd Maste return 1; 258*c43e99fdSEd Maste } 259*c43e99fdSEd Maste 260*c43e99fdSEd Maste if (use_ssl) { 261*c43e99fdSEd Maste int r; 262*c43e99fdSEd Maste #if OPENSSL_VERSION_NUMBER < 0x10100000L 263*c43e99fdSEd Maste SSL_library_init(); 264*c43e99fdSEd Maste ERR_load_crypto_strings(); 265*c43e99fdSEd Maste SSL_load_error_strings(); 266*c43e99fdSEd Maste OpenSSL_add_all_algorithms(); 267*c43e99fdSEd Maste #endif 268*c43e99fdSEd Maste r = RAND_poll(); 269*c43e99fdSEd Maste if (r == 0) { 270*c43e99fdSEd Maste fprintf(stderr, "RAND_poll() failed.\n"); 271*c43e99fdSEd Maste return 1; 272*c43e99fdSEd Maste } 273*c43e99fdSEd Maste ssl_ctx = SSL_CTX_new(TLS_method()); 274*c43e99fdSEd Maste } 275*c43e99fdSEd Maste 276*c43e99fdSEd Maste listener = evconnlistener_new_bind(base, accept_cb, NULL, 277*c43e99fdSEd Maste LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE, 278*c43e99fdSEd Maste -1, (struct sockaddr*)&listen_on_addr, socklen); 279*c43e99fdSEd Maste 280*c43e99fdSEd Maste if (! listener) { 281*c43e99fdSEd Maste fprintf(stderr, "Couldn't open listener.\n"); 282*c43e99fdSEd Maste event_base_free(base); 283*c43e99fdSEd Maste return 1; 284*c43e99fdSEd Maste } 285*c43e99fdSEd Maste event_base_dispatch(base); 286*c43e99fdSEd Maste 287*c43e99fdSEd Maste evconnlistener_free(listener); 288*c43e99fdSEd Maste event_base_free(base); 289*c43e99fdSEd Maste 290*c43e99fdSEd Maste return 0; 291*c43e99fdSEd Maste } 292