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