int udp_start(struct tundev_context *ctx, uv_loop_t *loop) { int rc; ctx->network_buffer = malloc(ctx->tun->mtu + PRIMITIVE_BYTES); uv_udp_init(loop, &ctx->inet_udp); ctx->inet_udp_fd = create_socket(SOCK_DGRAM, mode == xTUN_SERVER ? 1 : 0); if ((rc = uv_udp_open(&ctx->inet_udp, ctx->inet_udp_fd))) { logger_log(LOG_ERR, "udp open error: %s", uv_strerror(rc)); exit(1); } #ifdef ANDROID rc = protect_socket(ctx->inet_udp_fd); logger_log(rc ? LOG_INFO : LOG_ERR, "Protect socket %s", rc ? "successful" : "failed"); #endif if (mode == xTUN_SERVER) { rc = uv_udp_bind(&ctx->inet_udp, &ctx->tun->addr, UV_UDP_REUSEADDR); if (rc) { logger_stderr("udp bind error: %s", uv_strerror(rc)); exit(1); } } return uv_udp_recv_start(&ctx->inet_udp, inet_alloc_cb, inet_recv_cb); }
static void accept_cb(EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif int index = rand() % listener->remote_num; struct sockaddr *remote_addr = listener->remote_addr[index]; int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd < 0) { ERROR("socket"); return; } #ifdef ANDROID if (vpn) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); return; } } #endif setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif // Setup setnonblocking(remotefd); #ifdef SET_INTERFACE if (listener->iface) { setinterface(remotefd, listener->iface); } #endif struct server *server = new_server(serverfd, listener->method); struct remote *remote = new_remote(remotefd, listener->timeout); server->destaddr = listener->tunnel_addr; server->remote = remote; remote->server = server; connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { server_ctx_t *server_ctx = (server_ctx_t *)w; struct sockaddr_storage src_addr; memset(&src_addr, 0, sizeof(struct sockaddr_storage)); buffer_t *buf = ss_malloc(sizeof(buffer_t)); balloc(buf, buf_size); socklen_t src_addr_len = sizeof(struct sockaddr_storage); unsigned int offset = 0; #ifdef MODULE_REDIR char control_buffer[64] = { 0 }; struct msghdr msg; memset(&msg, 0, sizeof(struct msghdr)); struct iovec iov[1]; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); msg.msg_name = &src_addr; msg.msg_namelen = src_addr_len; msg.msg_control = control_buffer; msg.msg_controllen = sizeof(control_buffer); iov[0].iov_base = buf->data; iov[0].iov_len = buf_size; msg.msg_iov = iov; msg.msg_iovlen = 1; buf->len = recvmsg(server_ctx->fd, &msg, 0); if (buf->len == -1) { ERROR("[udp] server_recvmsg"); goto CLEAN_UP; } else if (buf->len > packet_size) { if (verbose) { LOGI("[udp] UDP server_recv_recvmsg fragmentation"); } } if (get_dstaddr(&msg, &dst_addr)) { LOGE("[udp] unable to get dest addr"); goto CLEAN_UP; } src_addr_len = msg.msg_namelen; #else ssize_t r; r = recvfrom(server_ctx->fd, buf->data, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len); if (r == -1) { // error on recv // simply drop that packet ERROR("[udp] server_recv_recvfrom"); goto CLEAN_UP; } else if (r > packet_size) { if (verbose) { LOGI("[udp] server_recv_recvfrom fragmentation"); } } buf->len = r; #endif if (verbose) { LOGI("[udp] server receive a packet"); } #ifdef MODULE_REMOTE tx += buf->len; int err = server_ctx->crypto->decrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } #endif #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) #ifdef __ANDROID__ tx += buf->len; #endif uint8_t frag = *(uint8_t *)(buf->data + 2); offset += 3; #endif #endif /* * * SOCKS5 UDP Request * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * SOCKS5 UDP Response * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * shadowsocks UDP Request (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Response (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Request and Response (after encrypted) * +-------+--------------+ * | IV | PAYLOAD | * +-------+--------------+ * | Fixed | Variable | * +-------+--------------+ * */ #ifdef MODULE_REDIR char addr_header[512] = { 0 }; int addr_header_len = construct_udprelay_header(&dst_addr, addr_header); if (addr_header_len == 0) { LOGE("[udp] failed to parse tproxy addr"); goto CLEAN_UP; } // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #elif MODULE_TUNNEL char addr_header[512] = { 0 }; char *host = server_ctx->tunnel_addr.host; char *port = server_ctx->tunnel_addr.port; uint16_t port_num = (uint16_t)atoi(port); uint16_t port_net_num = htons(port_num); int addr_header_len = 0; struct cork_ip ip; if (cork_ip_init(&ip, host) != -1) { if (ip.version == 4) { // send as IPv4 struct in_addr host_addr; memset(&host_addr, 0, sizeof(struct in_addr)); int host_len = sizeof(struct in_addr); if (dns_pton(AF_INET, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 1; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else if (ip.version == 6) { // send as IPv6 struct in6_addr host_addr; memset(&host_addr, 0, sizeof(struct in6_addr)); int host_len = sizeof(struct in6_addr); if (dns_pton(AF_INET6, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 4; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else { FATAL("IP parser error"); } } else { // send as domain int host_len = strlen(host); addr_header[addr_header_len++] = 3; addr_header[addr_header_len++] = host_len; memcpy(addr_header + addr_header_len, host, host_len); addr_header_len += host_len; } memcpy(addr_header + addr_header_len, &port_net_num, 2); addr_header_len += 2; // reconstruct the buffer brealloc(buf, buf->len + addr_header_len, buf_size); memmove(buf->data + addr_header_len, buf->data, buf->len); memcpy(buf->data, addr_header, addr_header_len); buf->len += addr_header_len; #else char host[257] = { 0 }; char port[64] = { 0 }; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); int addr_header_len = parse_udprelay_header(buf->data + offset, buf->len - offset, host, port, &dst_addr); if (addr_header_len == 0) { // error in parse header goto CLEAN_UP; } char *addr_header = buf->data + offset; #endif #ifdef MODULE_LOCAL char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr); #else char *key = hash_key(dst_addr.ss_family, &src_addr); #endif struct cache *conn_cache = server_ctx->conn_cache; remote_ctx_t *remote_ctx = NULL; cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); if (remote_ctx != NULL) { if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { remote_ctx = NULL; } } // reset the timer if (remote_ctx != NULL) { ev_timer_again(EV_A_ & remote_ctx->watcher); } if (remote_ctx == NULL) { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache miss: %s <-> %s", dst, src); #else LOGI("[udp] cache miss: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } else { if (verbose) { #ifdef MODULE_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache hit: %s <-> %s", dst, src); #else LOGI("[udp] cache hit: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } #ifdef MODULE_LOCAL #if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) if (frag) { LOGE("[udp] drop a message since frag is not 0, but %d", frag); goto CLEAN_UP; } #endif const struct sockaddr *remote_addr = server_ctx->remote_addr; const int remote_addr_len = server_ctx->remote_addr_len; if (remote_ctx == NULL) { // Bind to any port int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); if (remotefd < 0) { ERROR("[udp] udprelay bind() error"); goto CLEAN_UP; } setnonblocking(remotefd); #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif #ifdef __ANDROID__ if (vpn) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); goto CLEAN_UP; } } #endif // Init remote_ctx remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->af = remote_addr->sa_family; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); // Add to conn cache cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); // Start remote io ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } if (offset > 0) { buf->len -= offset; memmove(buf->data, buf->data + offset, buf->len); } int err = server_ctx->crypto->encrypt_all(buf, server_ctx->crypto->cipher, buf_size); if (err) { // drop the packet silently goto CLEAN_UP; } if (buf->len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } int s = sendto(remote_ctx->fd, buf->data, buf->len, 0, remote_addr, remote_addr_len); if (s == -1) { ERROR("[udp] server_recv_sendto"); } #else int cache_hit = 0; int need_query = 0; if (buf->len - addr_header_len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation"); } } if (remote_ctx != NULL) { cache_hit = 1; // detect destination mismatch if (remote_ctx->addr_header_len != addr_header_len || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { need_query = 1; } } else { memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage)); } } else { if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); if (remotefd != -1) { setnonblocking(remotefd); #ifdef SO_BROADCAST set_broadcast(remotefd); #endif #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef IP_TOS // Set QoS flag int tos = 46; setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { if (setinterface(remotefd, server_ctx->iface) == -1) ERROR("setinterface"); } #endif remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->server_ctx = server_ctx; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); } else { ERROR("[udp] bind() error"); goto CLEAN_UP; } } } if (remote_ctx != NULL && !need_query) { size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); int s = sendto(remote_ctx->fd, buf->data + addr_header_len, buf->len - addr_header_len, 0, (struct sockaddr *)&dst_addr, addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); if (!cache_hit) { close_and_free_remote(EV_A_ remote_ctx); } } else { if (!cache_hit) { // Add to conn cache remote_ctx->af = dst_addr.ss_family; char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } } } else { struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; struct query_ctx *query_ctx = new_query_ctx(buf->data + addr_header_len, buf->len - addr_header_len); query_ctx->server_ctx = server_ctx; query_ctx->addr_header_len = addr_header_len; query_ctx->src_addr = src_addr; memcpy(query_ctx->addr_header, addr_header, addr_header_len); if (need_query) { query_ctx->remote_ctx = remote_ctx; } struct ResolvQuery *query = resolv_query(host, query_resolve_cb, NULL, query_ctx, htons(atoi(port))); if (query == NULL) { ERROR("[udp] unable to create DNS query"); close_and_free_query(EV_A_ query_ctx); goto CLEAN_UP; } query_ctx->query = query; } #endif CLEAN_UP: bfree(buf); ss_free(buf); }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { struct server_ctx *server_recv_ctx = (struct server_ctx *)w; struct server *server = server_recv_ctx->server; struct remote *remote = server->remote; char *buf; if (remote == NULL) { buf = server->buf; } else { buf = remote->buf; } ssize_t r; r = recv(server->fd, buf, BUF_SIZE, 0); if (r == 0) { // connection closed close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data // continue to wait for recv return; } else { ERROR("server_recv_cb_recv"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } while (1) { // local socks5 server if (server->stage == 5) { if (remote == NULL) { LOGE("invalid remote"); close_and_free_server(EV_A_ server); return; } if (!remote->direct && remote->send_ctx->connected && auth) { remote->buf = ss_gen_hash(remote->buf, &r, &remote->counter, server->e_ctx, BUF_SIZE); } // insert shadowsocks header if (!remote->direct) { remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx); if (remote->buf == NULL) { LOGE("invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } if (!remote->send_ctx->connected) { #ifdef ANDROID if (vpn) { if (protect_socket(remote->fd) == -1) { ERROR("protect_socket"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } #endif remote->buf_idx = 0; remote->buf_len = r; if (!fast_open || remote->direct) { // connecting, wait until connected connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len); // wait on remote connected event ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); } else { #ifdef TCP_FASTOPEN int s = sendto(remote->fd, remote->buf, r, MSG_FASTOPEN, (struct sockaddr *)&(remote->addr), remote->addr_len); if (s == -1) { if (errno == EINPROGRESS) { // in progress, wait until connected remote->buf_idx = 0; remote->buf_len = r; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("sendto"); if (errno == ENOTCONN) { LOGE( "fast open is not supported on this platform"); // just turn it off fast_open = 0; } close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < r) { remote->buf_len = r - s; remote->buf_idx = s; } // Just connected remote->send_ctx->connected = 1; ev_timer_stop(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & remote->recv_ctx->io); #else // if TCP_FASTOPEN is not defined, fast_open will always be 0 LOGE("can't come here"); exit(1); #endif } } else { int s = send(remote->fd, remote->buf, r, 0); if (s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data, wait for send remote->buf_idx = 0; remote->buf_len = r; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("server_recv_cb_send"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < r) { remote->buf_len = r - s; remote->buf_idx = s; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } } // all processed return; } else if (server->stage == 0) { struct method_select_response response; response.ver = SVERSION; response.method = 0; char *send_buf = (char *)&response; send(server->fd, send_buf, sizeof(response), 0); server->stage = 1; return; } else if (server->stage == 1) { struct socks5_request *request = (struct socks5_request *)buf; struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); int udp_assc = 0; if (mode != TCP_ONLY && request->cmd == 3) { udp_assc = 1; socklen_t addr_len = sizeof(sock_addr); getsockname(server->fd, (struct sockaddr *)&sock_addr, &addr_len); if (verbose) { LOGI("udp assc request accepted"); } } else if (request->cmd != 1) { LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; response.ver = SVERSION; response.rep = CMD_NOT_SUPPORTED; response.rsv = 0; response.atyp = 1; char *send_buf = (char *)&response; send(server->fd, send_buf, 4, 0); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { char host[256], port[16]; char ss_addr_to_send[320]; ssize_t addr_len = 0; ss_addr_to_send[addr_len++] = request->atyp; // get remote addr and port if (request->atyp == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); memcpy(ss_addr_to_send + addr_len, buf + 4, in_addr_len + 2); addr_len += in_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + in_addr_len)); dns_ntop(AF_INET, (const void *)(buf + 4), host, INET_ADDRSTRLEN); sprintf(port, "%d", p); } } else if (request->atyp == 3) { // Domain name uint8_t name_len = *(uint8_t *)(buf + 4); ss_addr_to_send[addr_len++] = name_len; memcpy(ss_addr_to_send + addr_len, buf + 4 + 1, name_len + 2); addr_len += name_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + 1 + name_len)); memcpy(host, buf + 4 + 1, name_len); host[name_len] = '\0'; sprintf(port, "%d", p); } } else if (request->atyp == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); memcpy(ss_addr_to_send + addr_len, buf + 4, in6_addr_len + 2); addr_len += in6_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf + 4 + in6_addr_len)); dns_ntop(AF_INET6, (const void *)(buf + 4), host, INET6_ADDRSTRLEN); sprintf(port, "%d", p); } } else { LOGE("unsupported addrtype: %d", request->atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } server->stage = 5; r -= (3 + addr_len); buf += (3 + addr_len); if (verbose) { LOGI("connect to %s:%s", host, port); } if ((acl && (request->atyp == 1 || request->atyp == 4) && acl_contains_ip(host))) { if (verbose) { LOGI("bypass %s:%s", host, port); } struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); if (get_sockaddr(host, port, &storage, 0) != -1) { remote = create_remote(server->listener, (struct sockaddr *)&storage); remote->direct = 1; } } else { remote = create_remote(server->listener, NULL); } if (remote == NULL) { LOGE("invalid remote addr"); close_and_free_server(EV_A_ server); return; } if (!remote->direct) { if (auth) { ss_addr_to_send[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len, server->e_ctx); addr_len += ONETIMEAUTH_BYTES; } memcpy(remote->buf, ss_addr_to_send, addr_len); if (r > 0) { if (auth) { buf = ss_gen_hash(buf, &r, &remote->counter, server->e_ctx, BUF_SIZE); } memcpy(remote->buf + addr_len, buf, r); } r += addr_len; } else { if (r > 0) { memcpy(remote->buf, buf, r); } } server->remote = remote; remote->server = server; } // Fake reply struct socks5_response response; response.ver = SVERSION; response.rep = 0; response.rsv = 0; response.atyp = 1; memcpy(server->buf, &response, sizeof(struct socks5_response)); memcpy(server->buf + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); memcpy(server->buf + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr), &sock_addr.sin_port, sizeof(sock_addr.sin_port)); int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); int s = send(server->fd, server->buf, reply_size, 0); if (s < reply_size) { LOGE("failed to send fake reply"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (udp_assc) { close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } } }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { server_ctx_t *server_recv_ctx = (server_ctx_t *)w; server_t *server = server_recv_ctx->server; remote_t *remote = server->remote; buffer_t *buf; if (remote == NULL) { buf = server->buf; } else { buf = remote->buf; } ssize_t r; r = recv(server->fd, buf->array, BUF_SIZE, 0); if (r == 0) { // connection closed close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else if (r < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data // continue to wait for recv return; } else { ERROR("server_recv_cb_recv"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } buf->len = r; while (1) { // local socks5 server if (server->stage == 5) { if (remote == NULL) { LOGE("invalid remote"); close_and_free_server(EV_A_ server); return; } if (!remote->direct && remote->send_ctx->connected && auth) { ss_gen_hash(remote->buf, &remote->counter, server->e_ctx); } // insert shadowsocks header if (!remote->direct) { // SSR beg if (server->protocol_plugin) { obfs_class *protocol_plugin = server->protocol_plugin; if (protocol_plugin->client_pre_encrypt) { remote->buf->len = protocol_plugin->client_pre_encrypt(server->protocol, &remote->buf->array, remote->buf->len, &remote->buf->capacity); } } int err = ss_encrypt(remote->buf, server->e_ctx); if (err) { LOGE("server invalid password or cipher"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (server->obfs_plugin) { obfs_class *obfs_plugin = server->obfs_plugin; if (obfs_plugin->client_encode) { remote->buf->len = obfs_plugin->client_encode(server->obfs, &remote->buf->array, remote->buf->len, &remote->buf->capacity); } } // SSR end #ifdef ANDROID tx += r; #endif } if (!remote->send_ctx->connected) { #ifdef ANDROID if (vpn) { if (protect_socket(remote->fd) == -1) { ERROR("protect_socket"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } #endif remote->buf->idx = 0; if (!fast_open || remote->direct) { // connecting, wait until connected connect(remote->fd, (struct sockaddr *)&(remote->addr), remote->addr_len); // wait on remote connected event ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); } else { #ifdef TCP_FASTOPEN #ifdef __APPLE__ ((struct sockaddr_in*)&(remote->addr))->sin_len = sizeof(struct sockaddr_in); sa_endpoints_t endpoints; bzero((char*)&endpoints, sizeof(endpoints)); endpoints.sae_dstaddr = (struct sockaddr*)&(remote->addr); endpoints.sae_dstaddrlen = remote->addr_len; int s = connectx(remote->fd, &endpoints, SAE_ASSOCID_ANY, CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT, NULL, 0, NULL, NULL); if (s == 0) { s = send(remote->fd, remote->buf->array, remote->buf->len, 0); } #else int s = sendto(remote->fd, remote->buf->array, remote->buf->len, MSG_FASTOPEN, (struct sockaddr *)&(remote->addr), remote->addr_len); #endif if (s == -1) { if (errno == EINPROGRESS) { // in progress, wait until connected remote->buf->idx = 0; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("sendto"); if (errno == ENOTCONN) { LOGE( "fast open is not supported on this platform"); // just turn it off fast_open = 0; } close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s <= remote->buf->len) { remote->buf->len -= s; remote->buf->idx = s; } // Just connected remote->send_ctx->connected = 1; ev_timer_stop(EV_A_ & remote->send_ctx->watcher); ev_io_start(EV_A_ & remote->recv_ctx->io); #else // if TCP_FASTOPEN is not defined, fast_open will always be 0 LOGE("can't come here"); exit(1); #endif } } else { int s = send(remote->fd, remote->buf->array, remote->buf->len, 0); if (s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no data, wait for send remote->buf->idx = 0; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } else { ERROR("server_recv_cb_send"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } else if (s < remote->buf->len) { remote->buf->len -= s; remote->buf->idx = s; ev_io_stop(EV_A_ & server_recv_ctx->io); ev_io_start(EV_A_ & remote->send_ctx->io); return; } } // all processed return; } else if (server->stage == 0) { struct method_select_response response; response.ver = SVERSION; response.method = 0; char *send_buf = (char *)&response; send(server->fd, send_buf, sizeof(response), 0); server->stage = 1; int off = (buf->array[1] & 0xff) + 2; if (buf->array[0] == 0x05 && off < buf->len) { memmove(buf->array, buf->array + off, buf->len - off); buf->len -= off; continue; } return; } else if (server->stage == 1) { struct socks5_request *request = (struct socks5_request *)buf->array; struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); int udp_assc = 0; if (mode != TCP_ONLY && request->cmd == 3) { udp_assc = 1; socklen_t addr_len = sizeof(sock_addr); getsockname(server->fd, (struct sockaddr *)&sock_addr, &addr_len); if (verbose) { LOGI("udp assc request accepted"); } } else if (request->cmd != 1) { LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; response.ver = SVERSION; response.rep = CMD_NOT_SUPPORTED; response.rsv = 0; response.atyp = 1; char *send_buf = (char *)&response; send(server->fd, send_buf, 4, 0); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } else { char host[256], port[16]; buffer_t ss_addr_to_send; buffer_t *abuf = &ss_addr_to_send; balloc(abuf, BUF_SIZE); abuf->array[abuf->len++] = request->atyp; // get remote addr and port if (request->atyp == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); memcpy(abuf->array + abuf->len, buf->array + 4, in_addr_len + 2); abuf->len += in_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); dns_ntop(AF_INET, (const void *)(buf->array + 4), host, INET_ADDRSTRLEN); sprintf(port, "%d", p); } } else if (request->atyp == 3) { // Domain name uint8_t name_len = *(uint8_t *)(buf->array + 4); abuf->array[abuf->len++] = name_len; memcpy(abuf->array + abuf->len, buf->array + 4 + 1, name_len + 2); abuf->len += name_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + 1 + name_len)); memcpy(host, buf->array + 4 + 1, name_len); host[name_len] = '\0'; sprintf(port, "%d", p); } } else if (request->atyp == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); memcpy(abuf->array + abuf->len, buf->array + 4, in6_addr_len + 2); abuf->len += in6_addr_len + 2; if (acl || verbose) { uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len)); dns_ntop(AF_INET6, (const void *)(buf->array + 4), host, INET6_ADDRSTRLEN); sprintf(port, "%d", p); } } else { bfree(abuf); LOGE("unsupported addrtype: %d", request->atyp); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } server->stage = 5; buf->len -= (3 + abuf->len); if (buf->len > 0) { memmove(buf->array, buf->array + 3 + abuf->len, buf->len); } if (verbose) { LOGI("connect to %s:%s", host, port); } if ((acl && (request->atyp == 1 || request->atyp == 4) && acl_match_ip(host))) { if (verbose) { LOGI("bypass %s:%s", host, port); } struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); if (get_sockaddr(host, port, &storage, 0) != -1) { remote = create_remote(server->listener, (struct sockaddr *)&storage); remote->direct = 1; } } else { remote = create_remote(server->listener, NULL); } if (remote == NULL) { bfree(abuf); LOGE("invalid remote addr"); close_and_free_server(EV_A_ server); return; } // SSR beg if (server->listener->list_obfs_global[remote->remote_index] == NULL && server->obfs_plugin) { server->listener->list_obfs_global[remote->remote_index] = server->obfs_plugin->init_data(); } if (server->listener->list_protocol_global[remote->remote_index] == NULL && server->protocol_plugin) { server->listener->list_protocol_global[remote->remote_index] = server->protocol_plugin->init_data(); } server_info _server_info; memset(&_server_info, 0, sizeof(server_info)); strcpy(_server_info.host, inet_ntoa(((struct sockaddr_in*)&remote->addr)->sin_addr)); _server_info.port = ((struct sockaddr_in*)&remote->addr)->sin_port; _server_info.port = _server_info.port >> 8 | _server_info.port << 8; _server_info.param = server->listener->obfs_param; _server_info.g_data = server->listener->list_obfs_global[remote->remote_index]; _server_info.head_len = get_head_size(ss_addr_to_send.array, 320, 30); _server_info.iv = server->e_ctx->evp.iv; _server_info.iv_len = enc_get_iv_len(); _server_info.key = enc_get_key(); _server_info.key_len = enc_get_key_len(); _server_info.tcp_mss = 1440; if (server->obfs_plugin) server->obfs_plugin->set_server_info(server->obfs, &_server_info); _server_info.param = NULL; _server_info.g_data = server->listener->list_protocol_global[remote->remote_index]; if (server->protocol_plugin) server->protocol_plugin->set_server_info(server->protocol, &_server_info); // SSR end if (!remote->direct) { if (auth) { abuf->array[0] |= ONETIMEAUTH_FLAG; ss_onetimeauth(abuf, server->e_ctx->evp.iv); } brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE); memcpy(remote->buf->array, abuf->array, abuf->len); remote->buf->len = buf->len + abuf->len; if (buf->len > 0) { if (auth) { ss_gen_hash(buf, &remote->counter, server->e_ctx); } memcpy(remote->buf->array + abuf->len, buf->array, buf->len); } } else { if (buf->len > 0) { memcpy(remote->buf->array, buf->array, buf->len); remote->buf->len = buf->len; } } server->remote = remote; remote->server = server; bfree(abuf); } // Fake reply struct socks5_response response; response.ver = SVERSION; response.rep = 0; response.rsv = 0; response.atyp = 1; memcpy(server->buf->array, &response, sizeof(struct socks5_response)); memcpy(server->buf->array + sizeof(struct socks5_response), &sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); memcpy(server->buf->array + sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr), &sock_addr.sin_port, sizeof(sock_addr.sin_port)); int reply_size = sizeof(struct socks5_response) + sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); int s = send(server->fd, server->buf->array, reply_size, 0); if (s < reply_size) { LOGE("failed to send fake reply"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } if (udp_assc) { close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } } } }
static void accept_cb(EV_P_ ev_io *w, int revents) { struct listen_ctx *listener = (struct listen_ctx *)w; int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; } setnonblocking(serverfd); int opt = 1; setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif int index = rand() % listener->remote_num; struct sockaddr *remote_addr = listener->remote_addr[index]; int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd == -1) { ERROR("socket"); return; } #ifdef ANDROID if (vpn) { int not_protect = 0; if (remote_addr->sa_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *)remote_addr; if (s->sin_addr.s_addr == inet_addr("127.0.0.1")) not_protect = 1; } if (!not_protect) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); return; } } } #endif setsockopt(remotefd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); #ifdef SO_NOSIGPIPE setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); #endif if (listener->mptcp == 1) { int err = setsockopt(remotefd, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt)); if (err == -1) { ERROR("failed to enable multipath TCP"); } } // Setup setnonblocking(remotefd); #ifdef SET_INTERFACE if (listener->iface) { if (setinterface(remotefd, listener->iface) == -1) ERROR("setinterface"); } #endif server_t *server = new_server(serverfd, listener->method); remote_t *remote = new_remote(remotefd, listener->timeout); server->destaddr = listener->tunnel_addr; server->remote = remote; remote->server = server; int r = connect(remotefd, remote_addr, get_sockaddr_len(remote_addr)); if (r == -1 && errno != CONNECT_IN_PROGRESS) { ERROR("connect"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } // listen to remote connected event ev_io_start(EV_A_ & remote->send_ctx->io); ev_timer_start(EV_A_ & remote->send_ctx->watcher); }
static void server_recv_cb(EV_P_ ev_io *w, int revents) { struct server_ctx *server_ctx = (struct server_ctx *)w; struct sockaddr_storage src_addr; memset(&src_addr, 0, sizeof(struct sockaddr_storage)); char *buf = malloc(BUF_SIZE); socklen_t src_addr_len = sizeof(struct sockaddr_storage); unsigned int offset = 0; #ifdef UDPRELAY_REDIR char control_buffer[64] = { 0 }; struct msghdr msg; struct iovec iov[1]; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); msg.msg_name = &src_addr; msg.msg_namelen = src_addr_len; msg.msg_control = control_buffer; msg.msg_controllen = sizeof(control_buffer); iov[0].iov_base = buf; iov[0].iov_len = BUF_SIZE; msg.msg_iov = iov; msg.msg_iovlen = 1; ssize_t buf_len = recvmsg(server_ctx->fd, &msg, 0); if (buf_len == -1) { ERROR("[udp] server_recvmsg"); goto CLEAN_UP; } if (get_dstaddr(&msg, &dst_addr)) { LOGE("[udp] unable to get dest addr"); goto CLEAN_UP; } src_addr_len = msg.msg_namelen; #else ssize_t buf_len = recvfrom(server_ctx->fd, buf, BUF_SIZE, 0, (struct sockaddr *)&src_addr, &src_addr_len); if (buf_len == -1) { // error on recv // simply drop that packet ERROR("[udp] server_recvfrom"); goto CLEAN_UP; } #endif if (verbose) { LOGI("[udp] server receive a packet"); } #ifdef UDPRELAY_REMOTE tx += buf_len; buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, server_ctx->auth); if (buf == NULL) { ERROR("[udp] server_ss_decrypt_all"); goto CLEAN_UP; } #endif #ifdef UDPRELAY_LOCAL #if !defined(UDPRELAY_TUNNEL) && !defined(UDPRELAY_REDIR) uint8_t frag = *(uint8_t *)(buf + 2); offset += 3; #endif #endif // packet size > default MTU if (verbose && buf_len > MTU) { LOGE("[udp] possible ip fragment, size: %d", (int)buf_len); } /* * * SOCKS5 UDP Request * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * SOCKS5 UDP Response * +----+------+------+----------+----------+----------+ * |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | * +----+------+------+----------+----------+----------+ * | 2 | 1 | 1 | Variable | 2 | Variable | * +----+------+------+----------+----------+----------+ * * shadowsocks UDP Request (before encrypted) * +------+----------+----------+----------+-------------+ * | ATYP | DST.ADDR | DST.PORT | DATA | HMAC-SHA1 | * +------+----------+----------+----------+-------------+ * | 1 | Variable | 2 | Variable | 10 | * +------+----------+----------+----------+-------------+ * * If ATYP & ONETIMEAUTH_FLAG(0x10) == 1, Authentication (HMAC-SHA1) is enabled. * * The key of HMAC-SHA1 is (IV + KEY) and the input is the whole packet. * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). * * shadowsocks UDP Response (before encrypted) * +------+----------+----------+----------+ * | ATYP | DST.ADDR | DST.PORT | DATA | * +------+----------+----------+----------+ * | 1 | Variable | 2 | Variable | * +------+----------+----------+----------+ * * shadowsocks UDP Request and Response (after encrypted) * +-------+--------------+ * | IV | PAYLOAD | * +-------+--------------+ * | Fixed | Variable | * +-------+--------------+ * */ #ifdef UDPRELAY_REDIR char addr_header[256] = { 0 }; int addr_header_len = construct_udprealy_header(&dst_addr, addr_header); if (addr_header_len == 0) { LOGE("[udp] failed to parse tproxy addr"); goto CLEAN_UP; } // reconstruct the buffer if (BUF_SIZE < buf_len + addr_header_len) { buf = realloc(buf, buf_len + addr_header_len); } memmove(buf + addr_header_len, buf, buf_len); memcpy(buf, addr_header, addr_header_len); buf_len += addr_header_len; char *key = hash_key(dst_addr.ss_family, &src_addr); #elif UDPRELAY_TUNNEL char addr_header[256] = { 0 }; char *host = server_ctx->tunnel_addr.host; char *port = server_ctx->tunnel_addr.port; uint16_t port_num = (uint16_t)atoi(port); uint16_t port_net_num = htons(port_num); int addr_header_len = 0; struct cork_ip ip; if (cork_ip_init(&ip, host) != -1) { if (ip.version == 4) { // send as IPv4 struct in_addr host_addr; int host_len = sizeof(struct in_addr); if (dns_pton(AF_INET, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 1; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else if (ip.version == 6) { // send as IPv6 struct in6_addr host_addr; int host_len = sizeof(struct in6_addr); if (dns_pton(AF_INET6, host, &host_addr) == -1) { FATAL("IP parser error"); } addr_header[addr_header_len++] = 4; memcpy(addr_header + addr_header_len, &host_addr, host_len); addr_header_len += host_len; } else { FATAL("IP parser error"); } } else { // send as domain int host_len = strlen(host); addr_header[addr_header_len++] = 3; addr_header[addr_header_len++] = host_len; memcpy(addr_header + addr_header_len, host, host_len); addr_header_len += host_len; } memcpy(addr_header + addr_header_len, &port_net_num, 2); addr_header_len += 2; // reconstruct the buffer if (BUF_SIZE < buf_len + addr_header_len) { buf = realloc(buf, buf_len + addr_header_len); } memmove(buf + addr_header_len, buf, buf_len); memcpy(buf, addr_header, addr_header_len); buf_len += addr_header_len; char *key = hash_key(ip.version == 4 ? AF_INET : AF_INET6, &src_addr); #else char host[256] = { 0 }; char port[64] = { 0 }; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); int addr_header_len = parse_udprealy_header(buf + offset, buf_len - offset, &server_ctx->auth, host, port, &dst_addr); if (addr_header_len == 0) { // error in parse header goto CLEAN_UP; } char *addr_header = buf + offset; char *key = hash_key(dst_addr.ss_family, &src_addr); #endif struct cache *conn_cache = server_ctx->conn_cache; struct remote_ctx *remote_ctx = NULL; cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); if (remote_ctx != NULL) { if (memcmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { remote_ctx = NULL; } } // reset the timer if (remote_ctx != NULL) { ev_timer_again(EV_A_ & remote_ctx->watcher); } if (remote_ctx == NULL) { if (verbose) { #ifdef UDPRELAY_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache miss: %s <-> %s", dst, src); #else LOGI("[udp] cache miss: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } else { if (verbose) { #ifdef UDPRELAY_REDIR char src[SS_ADDRSTRLEN]; char dst[SS_ADDRSTRLEN]; strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); LOGI("[udp] cache hit: %s <-> %s", dst, src); #else LOGI("[udp] cache hit: %s:%s <-> %s", host, port, get_addr_str((struct sockaddr *)&src_addr)); #endif } } #ifdef UDPRELAY_LOCAL #if !defined(UDPRELAY_TUNNEL) && !defined(UDPRELAY_REDIR) if (frag) { LOGE("[udp] drop a message since frag is not 0, but %d", frag); goto CLEAN_UP; } #endif const struct sockaddr *remote_addr = server_ctx->remote_addr; const int remote_addr_len = server_ctx->remote_addr_len; if (remote_ctx == NULL) { // Bind to any port int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); if (remotefd < 0) { ERROR("[udp] udprelay bind() error"); goto CLEAN_UP; } setnonblocking(remotefd); #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { setinterface(remotefd, server_ctx->iface); } #endif #ifdef ANDROID if (vpn) { if (protect_socket(remotefd) == -1) { ERROR("protect_socket"); close(remotefd); goto CLEAN_UP; } } #endif // Init remote_ctx remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->af = remote_addr->sa_family; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); // Add to conn cache cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); // Start remote io ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } if (offset > 0) { buf_len -= offset; memmove(buf, buf + offset, buf_len); } if (server_ctx->auth) { buf[0] |= ONETIMEAUTH_FLAG; } buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, server_ctx->auth); int s = sendto(remote_ctx->fd, buf, buf_len, 0, remote_addr, remote_addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); } #else int cache_hit = 0; int need_query = 0; if (remote_ctx != NULL) { cache_hit = 1; // detect destination mismatch if (remote_ctx->addr_header_len != addr_header_len || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { need_query = 1; } } } else { if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); if (remotefd != -1) { setnonblocking(remotefd); #ifdef SO_BROADCAST set_broadcast(remotefd); #endif #ifdef SO_NOSIGPIPE set_nosigpipe(remotefd); #endif #ifdef SET_INTERFACE if (server_ctx->iface) { setinterface(remotefd, server_ctx->iface); } #endif remote_ctx = new_remote(remotefd, server_ctx); remote_ctx->src_addr = src_addr; remote_ctx->server_ctx = server_ctx; remote_ctx->addr_header_len = addr_header_len; memcpy(remote_ctx->addr_header, addr_header, addr_header_len); } else { ERROR("[udp] bind() error"); goto CLEAN_UP; } } } if (remote_ctx != NULL && !need_query) { size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); int s = sendto(remote_ctx->fd, buf + addr_header_len, buf_len - addr_header_len, 0, (struct sockaddr *)&dst_addr, addr_len); if (s == -1) { ERROR("[udp] sendto_remote"); if (!cache_hit) { close_and_free_remote(EV_A_ remote_ctx); } } else { if (!cache_hit) { // Add to conn cache remote_ctx->af = dst_addr.ss_family; char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); ev_io_start(EV_A_ & remote_ctx->io); ev_timer_start(EV_A_ & remote_ctx->watcher); } } } else { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; struct query_ctx *query_ctx = new_query_ctx(buf + addr_header_len, buf_len - addr_header_len); query_ctx->server_ctx = server_ctx; query_ctx->addr_header_len = addr_header_len; query_ctx->src_addr = src_addr; memcpy(query_ctx->addr_header, addr_header, addr_header_len); if (need_query) { query_ctx->remote_ctx = remote_ctx; } struct ResolvQuery *query = resolv_query(host, query_resolve_cb, NULL, query_ctx, htons(atoi(port))); if (query == NULL) { ERROR("[udp] unable to create DNS query"); close_and_free_query(EV_A_ query_ctx); goto CLEAN_UP; } query_ctx->query = query; } #endif CLEAN_UP: free(buf); }