commit d02f9e549f05ecf677c95ead75271ef44826e80d
parent 961a2e36858fda1b51a32bb54f702e06b71c2e23
Author: Joris Vink <joris@coders.se>
Date: Wed, 2 Dec 2015 21:52:26 +0100
Add TLS proxy example.
Diffstat:
4 files changed, 186 insertions(+), 0 deletions(-)
diff --git a/examples/tls-proxy/.gitignore b/examples/tls-proxy/.gitignore
@@ -0,0 +1,5 @@
+*.o
+.objs
+tls-proxy.so
+assets.h
+cert
diff --git a/examples/tls-proxy/README.md b/examples/tls-proxy/README.md
@@ -0,0 +1,18 @@
+Kore as a TLS-proxy.
+
+Note that this example requires a Kore binary built with NOHTTP set to 1.
+
+Edit src/proxy.c and update PROXY_HOST and PROXY_PORT to match your needs.
+
+Run:
+```
+ $ kore run
+```
+
+Test:
+```
+ Connect to the server and notice that it proxies data between you
+ and your destination.
+
+ $ openssl s_client -connect 127.0.0.1:8888
+```
diff --git a/examples/tls-proxy/conf/tls-proxy.conf b/examples/tls-proxy/conf/tls-proxy.conf
@@ -0,0 +1,19 @@
+# Kore as a TLS proxy configuration.
+#
+# Be sure to update the host and port to proxy
+# towards in src/proxy.c and rebuild.
+#
+# I recommend using Kore built with NOHTTP=1 if
+# you want to use this.
+
+load ./tls-proxy.so
+tls_dhparam dh2048.pem
+
+# Keep the proxy_setup callback.
+bind 127.0.0.1 8888 proxy_setup
+
+# Setup domain for TLS usage.
+domain 127.0.0.1 {
+ certfile cert/server.pem
+ certkey cert/server.key
+}
diff --git a/examples/tls-proxy/src/proxy.c b/examples/tls-proxy/src/proxy.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015 Joris Vink <joris@coders.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <kore/kore.h>
+
+/*
+ * In this example Kore acts as a simple TLS proxy.
+ * Be sure to update PROXY_HOST and PROXY_PORT to reflect
+ * your endpoint.
+ *
+ * Note - right now the connect() call in proxy_setup() is still
+ * done synchronously, might change in the future in this example.
+ *
+ * Hint: enabling client certificates in Kore still works with this :-)
+ */
+
+#define PROXY_HOST "127.0.0.1"
+#define PROXY_PORT 80
+
+void proxy_setup(struct connection *);
+void proxy_disconnect(struct connection *);
+int proxy_data(struct netbuf *);
+int proxy_handle(struct connection *);
+
+void
+proxy_setup(struct connection *c)
+{
+ int fd;
+ struct sockaddr_in sin;
+ struct connection *proxy;
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ kore_log(LOG_ERR, "socket(): %s", errno_s);
+ kore_connection_disconnect(c);
+ return;
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(PROXY_PORT);
+ sin.sin_addr.s_addr = inet_addr(PROXY_HOST);
+
+ /* Blocking connect(), perhaps we can improve on that later. */
+ if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ kore_log(LOG_ERR, "connect(): %s", errno_s);
+ close(fd);
+ kore_connection_disconnect(c);
+ return;
+ }
+
+ if (!kore_connection_nonblock(fd, 1)) {
+ close(fd);
+ kore_connection_disconnect(c);
+ return;
+ }
+
+ proxy = kore_connection_new(NULL);
+
+ proxy->fd = fd;
+ proxy->addr.ipv4 = sin;
+ proxy->read = net_read;
+ proxy->write = net_write;
+ proxy->addrtype = AF_INET;
+ proxy->proto = CONN_PROTO_UNKNOWN;
+ proxy->state = CONN_STATE_ESTABLISHED;
+
+ proxy->idle_timer.length = 60000;
+ c->idle_timer.length = 60000;
+
+ c->hdlr_extra = proxy;
+ proxy->hdlr_extra = c;
+
+ c->handle = proxy_handle;
+ c->disconnect = proxy_disconnect;
+ proxy->handle = proxy_handle;
+ proxy->disconnect = proxy_disconnect;
+
+ kore_connection_start_idletimer(proxy);
+ kore_platform_event_all(proxy->fd, proxy);
+
+ net_recv_queue(c, NETBUF_SEND_PAYLOAD_MAX,
+ NETBUF_CALL_CB_ALWAYS, proxy_data);
+ net_recv_queue(proxy, NETBUF_SEND_PAYLOAD_MAX,
+ NETBUF_CALL_CB_ALWAYS, proxy_data);
+
+ kore_log(LOG_NOTICE, "new connection alright, us:%p proxy:%p", c, proxy);
+
+ /* We must set the state for this connection ourselves. */
+ c->state = CONN_STATE_ESTABLISHED;
+ TAILQ_INSERT_TAIL(&connections, proxy, list);
+}
+
+int
+proxy_handle(struct connection *c)
+{
+ kore_log(LOG_NOTICE, "connection activity on %p", c);
+ return (kore_connection_handle(c));
+}
+
+void
+proxy_disconnect(struct connection *c)
+{
+ struct connection *proxy = (struct connection *)c->hdlr_extra;
+
+ kore_log(LOG_NOTICE, "disconnecting %p (proxy: %p)", c, proxy);
+
+ c->hdlr_extra = NULL;
+
+ if (proxy != NULL) {
+ proxy->hdlr_extra = NULL;
+ kore_connection_disconnect(proxy);
+ }
+}
+
+int
+proxy_data(struct netbuf *nb)
+{
+ struct connection *src = nb->owner;
+ struct connection *proxy = src->hdlr_extra;
+
+ kore_log(LOG_NOTICE, "proxying %u bytes", nb->s_off);
+
+ net_send_queue(proxy, nb->buf, nb->s_off);
+ net_send_flush(proxy);
+ net_recv_reset(src, NETBUF_SEND_PAYLOAD_MAX, proxy_data);
+
+ return (KORE_RESULT_OK);
+}