/* * Called for every new connection on a certain ip/port. Which one is * configured in the TLS proxy its configuration file. */ void client_setup(struct connection *c) { int i, fd; struct connection *backend; /* Paranoia. */ if (c->ssl->session == NULL || c->ssl->session->tlsext_hostname == NULL) { kore_connection_disconnect(c); return; } /* Figure out what backend to use. */ for (i = 0; backends[i].name != NULL; i++) { if (!strcasecmp(backends[i].name, c->ssl->session->tlsext_hostname)) break; } /* If we don't have any backends, we just disconnect the client. */ if (backends[i].name == NULL) { kore_connection_disconnect(c); return; } /* Create new socket for the backend connection. */ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { kore_log(LOG_ERR, "socket(): %s", errno_s); kore_connection_disconnect(c); return; } /* Set it to non blocking as well. */ if (!kore_connection_nonblock(fd, 1)) { close(fd); kore_connection_disconnect(c); return; } /* Grab a new connection from Kore to hook backend into. */ backend = kore_connection_new(NULL); /* Prepare our connection. */ backend->addrtype = AF_INET; backend->addr.ipv4.sin_family = AF_INET; backend->addr.ipv4.sin_port = htons(backends[i].port); backend->addr.ipv4.sin_addr.s_addr = inet_addr(backends[i].ip); /* Set the file descriptor for the backend. */ backend->fd = fd; /* Default write/read callbacks for backend. */ backend->read = net_read; backend->write = net_write; /* Connection type (unknown to Kore). */ backend->proto = CONN_PROTO_UNKNOWN; backend->state = CONN_STATE_ESTABLISHED; /* The backend idle timer is set first to connection timeout. */ backend->idle_timer.length = PROXY_CONNECT_TIMEOUT; /* The client idle timer is set to default idle time. */ c->idle_timer.length = PROXY_TIMEOUT; /* Now link both the client and the backend connection together. */ c->hdlr_extra = backend; backend->hdlr_extra = c; /* * The handle function pointer for the backend is set to the * backend_handle_connect() while connecting. */ c->handle = client_handle; backend->handle = backend_handle_connect; /* Set the disconnect method for both connections. */ c->disconnect = disconnect; backend->disconnect = disconnect; /* Queue write events for the backend connection for now. */ kore_platform_schedule_write(backend->fd, backend); /* Start idle timer for the backend. */ kore_connection_start_idletimer(backend); /* Set our client connection to established. */ c->state = CONN_STATE_ESTABLISHED; /* Insert the backend into the list of Kore connections. */ TAILQ_INSERT_TAIL(&connections, backend, list); /* Kick off connecting. */ backend->flags |= CONN_WRITE_POSSIBLE; backend->handle(backend); }
/* * Connect to our target host:port and attach it to a struct connection that * Kore understands. We set the disconnect method so we get a callback * whenever either of the connections will go away so we can cleanup the * one it is attached to. */ static int ktunnel_pipe_create(struct connection *c, const char *host, const char *port) { struct sockaddr_in sin; struct connection *cpipe; u_int16_t nport; int fd, err; nport = kore_strtonum(port, 10, 1, SHRT_MAX, &err); if (err == KORE_RESULT_ERROR) { kore_log(LOG_ERR, "invalid port given %s", port); return (KORE_RESULT_ERROR); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { kore_log(LOG_ERR, "socket(): %s", errno_s); return (KORE_RESULT_ERROR); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(nport); sin.sin_addr.s_addr = inet_addr(host); kore_log(LOG_NOTICE, "Attempting to connect to %s:%s", host, port); if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { close(fd); kore_log(LOG_ERR, "connect(): %s", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(fd)) { close(fd); return (KORE_RESULT_ERROR); } cpipe = kore_connection_new(c); cpipe->fd = fd; cpipe->addr.ipv4 = sin; cpipe->read = net_read; cpipe->write = net_write; cpipe->addrtype = AF_INET; cpipe->proto = CONN_PROTO_UNKNOWN; cpipe->state = CONN_STATE_ESTABLISHED; /* Don't let these connections timeout any time soon. */ cpipe->idle_timer.length = 10000000000; c->idle_timer.length = 10000000000; c->hdlr_extra = cpipe; cpipe->hdlr_extra = c; c->disconnect = ktunnel_pipe_disconnect; cpipe->disconnect = ktunnel_pipe_disconnect; kore_worker_connection_add(cpipe); kore_connection_start_idletimer(cpipe); kore_platform_event_all(cpipe->fd, cpipe); net_recv_reset(c, NETBUF_SEND_PAYLOAD_MAX, ktunnel_pipe_data); net_recv_queue(cpipe, NETBUF_SEND_PAYLOAD_MAX, NETBUF_CALL_CB_ALWAYS, ktunnel_pipe_data); printf("connection started to %s (%p -> %p)\n", host, c, cpipe); return (KORE_RESULT_OK); }