int main() { make_encryptor(NULL, &crypto, METHOD_SHADOWCRYPT, (uint8_t*)PASSWORD); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PROXY_PORT); inet_pton(AF_INET, PROXY_IP_ADDR, &(addr.sin_addr)); server_core((struct sockaddr*)&addr, sizeof(addr)); return 0; }
static void connect_cb(uv_stream_t* listener, int status) { int n; if (status) { SHOW_UV_ERROR(listener->loop); return; } server_ctx *ctx = calloc(1, sizeof(server_ctx)); ctx->handshake_buffer = calloc(1, HANDSHAKE_BUFFER_SIZE); if (!ctx || !ctx->handshake_buffer) FATAL("malloc() failed!"); ctx->client.data = ctx; ctx->remote.data = ctx; make_encryptor(&crypto, &ctx->encoder, 0, NULL); n = uv_tcp_init(listener->loop, &ctx->client); if (n) SHOW_UV_ERROR_AND_EXIT(listener->loop); n = uv_accept(listener, (uv_stream_t *)(void *)&ctx->client); if (n) SHOW_UV_ERROR_AND_EXIT(listener->loop); n = uv_tcp_nodelay(&ctx->client, 1); if (n) SHOW_UV_ERROR_AND_EXIT(listener->loop); #ifdef KEEPALIVE_TIMEOUT n = uv_tcp_keepalive(&ctx->client, 1, KEEPALIVE_TIMEOUT); if (n) SHOW_UV_ERROR_AND_EXIT(listener->loop); #endif /* KEEPALIVE_TIMEOUT */ n = uv_read_start((uv_stream_t *)(void *)&ctx->client, client_handshake_alloc_cb, client_handshake_read_cb); if (n) SHOW_UV_ERROR_AND_EXIT(listener->loop); LOGCONN(&ctx->client, "Accepted connection from %s"); }
int main(int argc, char *argv[]) { char **newargv = uv_setup_args(argc, argv); char *server_listen = SERVER_LISTEN; int server_port = SERVER_PORT; uint8_t *password = (uint8_t *)PASSWORD; uint8_t crypt_method = CRYPTO_METHOD; char *pid_path = PID_FILE; char opt; while((opt = getopt(argc, newargv, "l:p:k:f:m:")) != -1) { // not portable to windows switch(opt) { case 'l': server_listen = optarg; break; case 'p': server_port = atoi(optarg); break; case 'k': password = (uint8_t *)optarg; break; case 'f': pid_path = optarg; break; case 'm': if (!strcmp("rc4", optarg)) crypt_method = METHOD_RC4; else if (!strcmp("shadow", optarg)) crypt_method = METHOD_SHADOWCRYPT; break; default: fprintf(stderr, USAGE, newargv[0]); abort(); } } FILE *pid_file = fopen(pid_path, "wb"); if (!pid_file) FATAL("fopen failed, %s", strerror(errno)); fprintf(pid_file, "%d", getpid()); fclose(pid_file); char *process_title = malloc(PROCESS_TITLE_LENGTH); // we do not like waste memory if (!process_title) FATAL("malloc() failed!"); snprintf(process_title, PROCESS_TITLE_LENGTH, PROCESS_TITLE, server_port); uv_set_process_title(process_title); free(process_title); LOGI(WELCOME_MESSAGE); if (crypt_method == METHOD_SHADOWCRYPT) LOGI("Using shadowcrypt crypto"); else if (crypt_method == METHOD_RC4) LOGI("Using RC4 crypto"); else FATAL("Crypto unknown!"); make_encryptor(NULL, &crypto, crypt_method, password); LOGI("Crypto ready"); int n; uv_loop_t *loop = uv_default_loop(); uv_tcp_t listener; struct sockaddr_in6 addr = uv_ip6_addr(server_listen, server_port); n = uv_tcp_init(loop, &listener); if (n) SHOW_UV_ERROR_AND_EXIT(loop); n = uv_tcp_bind6(&listener, addr); if (n) SHOW_UV_ERROR_AND_EXIT(loop); n = uv_listen((uv_stream_t*)(void *)&listener, 5, connect_cb); if (n) SHOW_UV_ERROR_AND_EXIT(loop); LOGI("Listening on %s:%d", server_listen, server_port); #ifndef NDEBUG setup_signal_handler(loop); #endif /* !NDEBUG */ return uv_run(loop); }
void child_core(int fd) { /* make child encryptor*/ make_encryptor(&crypto, &chd_crypto, 0, NULL); uint8_t buf[BUF_SIZE]; size_t remote_addr_len; struct sockaddr *remote_addr; if (read_addr(fd, buf, &remote_addr, &remote_addr_len) != 0) { clean_exit(errno, "get remote addr error", 1, fd); } int remote_fd; if ((remote_fd = socket(remote_addr->sa_family, SOCK_STREAM, 0)) < 0) { clean_exit(errno, "cannot open socket", 1, fd); } int optval = 1; if (setsockopt(remote_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)) == -1) { clean_exit(errno, "set socket option error", 1, fd); } if (connect(remote_fd, remote_addr, remote_addr_len) < 0 ) { clean_exit(errno, "cannnot connect remote", 1, fd); } free(remote_addr); remote_addr = NULL; remote_addr_len = 0; /* use poll */ struct pollfd fds[2]; fds[0].fd = fd; fds[1].fd = remote_fd; fds[0].events = POLLIN | POLLERR | POLLHUP; fds[1].events = POLLIN | POLLERR | POLLHUP; size_t read_size; int rc; while (poll(fds, 2, -1) > 0) { if (fds[0].revents & (POLLIN | POLLHUP)) { rc = crypt_recv(fd, buf, BUF_SIZE); if (rc > 0) { read_size = (size_t)rc; if (sendall(remote_fd, buf, read_size, 0) < read_size) break; } else if (rc == 0) { fds[0].fd = -1; shutdown(fd, SHUT_RD); shutdown(remote_fd, SHUT_WR); } else { break; } } if (fds[1].revents & (POLLIN | POLLHUP)) { rc = recv(remote_fd, buf, BUF_SIZE, 0); if (read_size > 0) { read_size = (size_t)rc; if (crypt_sendall(fd, buf, read_size) < read_size) break; } else if (read_size == 0) { fds[1].fd = -1; shutdown(fd, SHUT_WR); shutdown(remote_fd, SHUT_RD); } else { break; } } if (fds[0].fd == fds[1].fd) clean_exit(0, "close all sock", 0); if ((fds[0].revents & POLLERR) || (fds[1].revents & POLLERR)) break; } clean_exit(errno, "socket pair error exit", 0); }