From 90b750094d0760dc2a11b68ba1caa57abef6ecfa Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 19 Mar 2014 20:47:10 +0800 Subject: [PATCH] Apply udpgw patch from linusyang --- src/main/jni/badvpn/protocol/udpgw_proto.h | 14 + .../jni/badvpn/tun2socks/SocksUdpGwClient.c | 379 ++++++++++++++++++ .../jni/badvpn/tun2socks/SocksUdpGwClient.h | 42 ++ src/main/jni/badvpn/tun2socks/tun2socks.c | 32 ++ .../shadowsocks/ShadowsocksVpnService.scala | 22 +- 5 files changed, 481 insertions(+), 8 deletions(-) diff --git a/src/main/jni/badvpn/protocol/udpgw_proto.h b/src/main/jni/badvpn/protocol/udpgw_proto.h index 606fe6c4..cd800d9e 100644 --- a/src/main/jni/badvpn/protocol/udpgw_proto.h +++ b/src/main/jni/badvpn/protocol/udpgw_proto.h @@ -39,6 +39,16 @@ #define UDPGW_CLIENT_FLAG_DNS (1 << 2) #define UDPGW_CLIENT_FLAG_IPV6 (1 << 3) +#ifdef BADVPN_SOCKS_UDP_RELAY +B_START_PACKED +struct socks_udp_header { + uint16_t rsv; + uint8_t frag; + uint8_t atyp; +} B_PACKED; +B_END_PACKED +#endif + B_START_PACKED struct udpgw_header { uint8_t flags; @@ -63,7 +73,11 @@ B_END_PACKED static int udpgw_compute_mtu (int dgram_mtu) { bsize_t bs = bsize_add( +#ifdef BADVPN_SOCKS_UDP_RELAY + bsize_fromsize(sizeof(struct socks_udp_header)), +#else bsize_fromsize(sizeof(struct udpgw_header)), +#endif bsize_add( bsize_max( bsize_fromsize(sizeof(struct udpgw_addr_ipv4)), diff --git a/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.c b/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.c index 949d114b..cb9fa6de 100644 --- a/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.c +++ b/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.c @@ -33,6 +33,13 @@ #include +#ifdef BADVPN_SOCKS_UDP_RELAY + +#include +#define CONNECTION_UDP_BUFFER_SIZE 1 + +#else + static void free_socks (SocksUdpGwClient *o); static void try_connect (SocksUdpGwClient *o); static void reconnect_timer_handler (SocksUdpGwClient *o); @@ -40,6 +47,317 @@ static void socks_client_handler (SocksUdpGwClient *o, int event); static void udpgw_handler_servererror (SocksUdpGwClient *o); static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len); +#endif + +#ifdef BADVPN_SOCKS_UDP_RELAY +static void dgram_handler (SocksUdpGwClient_connection *o, int event); +static void dgram_handler_received (SocksUdpGwClient_connection *o, uint8_t *data, int data_len); +static int conaddr_comparator (void *unused, SocksUdpGwClient_conaddr *v1, SocksUdpGwClient_conaddr *v2); +static SocksUdpGwClient_connection * find_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr); +static SocksUdpGwClient_connection * reuse_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr); +static void connection_send (SocksUdpGwClient_connection *o, const uint8_t *data, int data_len); +static void connection_first_job_handler (SocksUdpGwClient_connection *con); +static SocksUdpGwClient_connection *connection_init (SocksUdpGwClient *client, SocksUdpGwClient_conaddr conaddr, const uint8_t *data, int data_len); +static void connection_free (SocksUdpGwClient_connection *o); + +static void dgram_handler (SocksUdpGwClient_connection *o, int event) +{ + SocksUdpGwClient *client = o->client; + ASSERT(client); + + DebugObject_Access(&client->d_obj); + + BLog(BLOG_INFO, "UDP error"); +} + +static void dgram_handler_received (SocksUdpGwClient_connection *o, uint8_t *data, int data_len) +{ + SocksUdpGwClient *client = o->client; + ASSERT(client); + + DebugObject_Access(&client->d_obj); + ASSERT(data_len >= 0) + ASSERT(data_len <= client->udpgw_mtu) + + // accept packet + PacketPassInterface_Done(&o->udp_recv_if); + + // check header + if (data_len < sizeof(struct socks_udp_header)) { + BLog(BLOG_ERROR, "missing header"); + return; + } + struct socks_udp_header header; + memcpy(&header, data, sizeof(header)); + data += sizeof(header); + data_len -= sizeof(header); + uint8_t frag = header.frag; + uint8_t atyp = header.atyp; + + // check fragment + if (frag) { + BLog(BLOG_ERROR, "unexpected frag"); + return; + } + + // parse address + BAddr remote_addr; + if (atyp == SOCKS_ATYP_IPV6) { + if (data_len < sizeof(struct udpgw_addr_ipv6)) { + BLog(BLOG_ERROR, "missing ipv6 address"); + return; + } + struct udpgw_addr_ipv6 addr_ipv6; + memcpy(&addr_ipv6, data, sizeof(addr_ipv6)); + data += sizeof(addr_ipv6); + data_len -= sizeof(addr_ipv6); + BAddr_InitIPv6(&remote_addr, addr_ipv6.addr_ip, addr_ipv6.addr_port); + } else { + if (data_len < sizeof(struct udpgw_addr_ipv4)) { + BLog(BLOG_ERROR, "missing ipv4 address"); + return; + } + struct udpgw_addr_ipv4 addr_ipv4; + memcpy(&addr_ipv4, data, sizeof(addr_ipv4)); + data += sizeof(addr_ipv4); + data_len -= sizeof(addr_ipv4); + BAddr_InitIPv4(&remote_addr, addr_ipv4.addr_ip, addr_ipv4.addr_port); + } + + // check remote addr + if (!BAddr_Compare(&remote_addr, &o->conaddr.remote_addr)) { + BLog(BLOG_ERROR, "remote addr not match"); + return; + } + + // check remaining data + if (data_len > client->udp_mtu) { + BLog(BLOG_ERROR, "too much data"); + return; + } + + // submit to user + client->handler_received(client->user, o->conaddr.local_addr, remote_addr, data, data_len); +} + +static int conaddr_comparator (void *unused, SocksUdpGwClient_conaddr *v1, SocksUdpGwClient_conaddr *v2) +{ + int r = BAddr_CompareOrder(&v1->remote_addr, &v2->remote_addr); + if (r) { + return r; + } + return BAddr_CompareOrder(&v1->local_addr, &v2->local_addr); +} + +static SocksUdpGwClient_connection * find_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr) +{ + BAVLNode *tree_node = BAVL_LookupExact(&o->connections_tree, &conaddr); + if (!tree_node) { + return NULL; + } + + return UPPER_OBJECT(tree_node, SocksUdpGwClient_connection, connections_tree_node); +} + +static SocksUdpGwClient_connection * reuse_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr) +{ + ASSERT(!find_connection(o, conaddr)) + ASSERT(o->num_connections > 0) + + // get least recently used connection + SocksUdpGwClient_connection *con = UPPER_OBJECT(LinkedList1_GetFirst(&o->connections_list), SocksUdpGwClient_connection, connections_list_node); + + // remove from connections tree by conaddr + BAVL_Remove(&o->connections_tree, &con->connections_tree_node); + + // set new conaddr + con->conaddr = conaddr; + + // insert to connections tree by conaddr + ASSERT_EXECUTE(BAVL_Insert(&o->connections_tree, &con->connections_tree_node, NULL)) + + return con; +} + +static void connection_send (SocksUdpGwClient_connection *o, const uint8_t *data, int data_len) +{ + // get buffer location + uint8_t *out; + if (!BufferWriter_StartPacket(&o->udp_send_writer, &out)) { + BLog(BLOG_ERROR, "out of UDP buffer"); + return; + } + int out_pos = 0; + + // write header + BAddr remote_addr = o->conaddr.remote_addr; + struct socks_udp_header header; + header.rsv = 0; + header.frag = 0; + if (remote_addr.type == BADDR_TYPE_IPV4) { + header.atyp = SOCKS_ATYP_IPV4; + } else { + header.atyp = SOCKS_ATYP_IPV6; + } + memcpy(out + out_pos, &header, sizeof(header)); + out_pos += sizeof(header); + + // write address + switch (remote_addr.type) { + case BADDR_TYPE_IPV4: { + struct udpgw_addr_ipv4 addr_ipv4; + addr_ipv4.addr_ip = remote_addr.ipv4.ip; + addr_ipv4.addr_port = remote_addr.ipv4.port; + memcpy(out + out_pos, &addr_ipv4, sizeof(addr_ipv4)); + out_pos += sizeof(addr_ipv4); + } break; + case BADDR_TYPE_IPV6: { + struct udpgw_addr_ipv6 addr_ipv6; + memcpy(addr_ipv6.addr_ip, remote_addr.ipv6.ip, sizeof(addr_ipv6.addr_ip)); + addr_ipv6.addr_port = remote_addr.ipv6.port; + memcpy(out + out_pos, &addr_ipv6, sizeof(addr_ipv6)); + out_pos += sizeof(addr_ipv6); + } break; + } + + // write packet to buffer + memcpy(out + out_pos, data, data_len); + out_pos += data_len; + + // submit written message + BufferWriter_EndPacket(&o->udp_send_writer, out_pos); +} + +static void connection_first_job_handler (SocksUdpGwClient_connection *con) +{ + connection_send(con, con->first_data, con->first_data_len); +} + +static SocksUdpGwClient_connection *connection_init (SocksUdpGwClient *client, SocksUdpGwClient_conaddr conaddr, const uint8_t *data, int data_len) +{ + // allocate structure + SocksUdpGwClient_connection *o = (SocksUdpGwClient_connection *) malloc(sizeof(*o)); + if (!o) { + BLog(BLOG_ERROR, "malloc failed"); + goto fail; + } + + // init arguments + o->client = client; + o->conaddr = conaddr; + o->first_data = data; + o->first_data_len = data_len; + + // init first job + BPending_Init(&o->first_job, BReactor_PendingGroup(client->reactor), (BPending_handler)connection_first_job_handler, o); + BPending_Set(&o->first_job); + + // init UDP dgram + if (!BDatagram_Init(&o->udp_dgram, client->socks_server_addr.type, client->reactor, o, (BDatagram_handler)dgram_handler)) { + goto fail0; + } + + // set SO_REUSEADDR + if (!BDatagram_SetReuseAddr(&o->udp_dgram, 1)) { + BLog(BLOG_ERROR, "set SO_REUSEADDR failed"); + goto fail1; + } + + // set UDP dgram send address + BIPAddr ipaddr; + memset(&ipaddr, 0, sizeof(ipaddr)); + ipaddr.type = client->socks_server_addr.type; + BDatagram_SetSendAddrs(&o->udp_dgram, client->socks_server_addr, ipaddr); + + // init UDP dgram interfaces + BDatagram_SendAsync_Init(&o->udp_dgram, client->udp_mtu); + BDatagram_RecvAsync_Init(&o->udp_dgram, client->udp_mtu); + + // init UDP writer + BufferWriter_Init(&o->udp_send_writer, client->udp_mtu, BReactor_PendingGroup(client->reactor)); + + // init UDP buffer + if (!PacketBuffer_Init(&o->udp_send_buffer, BufferWriter_GetOutput(&o->udp_send_writer), BDatagram_SendAsync_GetIf(&o->udp_dgram), CONNECTION_UDP_BUFFER_SIZE, BReactor_PendingGroup(client->reactor))) { + BLog(BLOG_ERROR, "PacketBuffer_Init failed"); + goto fail2; + } + + // init UDP recv interface + PacketPassInterface_Init(&o->udp_recv_if, client->udp_mtu, (PacketPassInterface_handler_send)dgram_handler_received, o, BReactor_PendingGroup(client->reactor)); + + // init UDP recv buffer + if (!SinglePacketBuffer_Init(&o->udp_recv_buffer, BDatagram_RecvAsync_GetIf(&o->udp_dgram), &o->udp_recv_if, BReactor_PendingGroup(client->reactor))) { + BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed"); + goto fail3; + } + + // insert to connections tree by conaddr + ASSERT_EXECUTE(BAVL_Insert(&client->connections_tree, &o->connections_tree_node, NULL)); + + // insert to connections list + LinkedList1_Append(&client->connections_list, &o->connections_list_node); + + // increment number of connections + client->num_connections++; + + // succeed to init + return o; + +fail3: + PacketPassInterface_Free(&o->udp_recv_if); + PacketBuffer_Free(&o->udp_send_buffer); +fail2: + BufferWriter_Free(&o->udp_send_writer); + BDatagram_RecvAsync_Free(&o->udp_dgram); + BDatagram_SendAsync_Free(&o->udp_dgram); +fail1: + BDatagram_Free(&o->udp_dgram); + +fail0: + BPending_Free(&o->first_job); + free(o); +fail: + return NULL; +} + +static void connection_free (SocksUdpGwClient_connection *o) +{ + SocksUdpGwClient *client = o->client; + + // decrement number of connections + client->num_connections--; + + // remove from connections list + LinkedList1_Remove(&client->connections_list, &o->connections_list_node); + + // remove from connections tree by conaddr + BAVL_Remove(&client->connections_tree, &o->connections_tree_node); + + // free UDP receive buffer + SinglePacketBuffer_Free(&o->udp_recv_buffer); + + // free UDP receive interface + PacketPassInterface_Free(&o->udp_recv_if); + + // free UDP buffer + PacketBuffer_Free(&o->udp_send_buffer); + + // free UDP writer + BufferWriter_Free(&o->udp_send_writer); + + // free UDP dgram interfaces + BDatagram_RecvAsync_Free(&o->udp_dgram); + BDatagram_SendAsync_Free(&o->udp_dgram); + + // free UDP dgram + BDatagram_Free(&o->udp_dgram); + + // free structure + free(o); +} + +#else + static void free_socks (SocksUdpGwClient *o) { ASSERT(o->have_socks) @@ -158,6 +476,8 @@ static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr return; } +#endif + int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections, int send_buffer_size, btime_t keepalive_time, BAddr socks_server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info, BAddr remote_udpgw_addr, btime_t reconnect_time, BReactor *reactor, void *user, @@ -165,7 +485,9 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections { // see asserts in UdpGwClient_Init ASSERT(!BAddr_IsInvalid(&socks_server_addr)) +#ifndef BADVPN_SOCKS_UDP_RELAY ASSERT(remote_udpgw_addr.type == BADDR_TYPE_IPV4 || remote_udpgw_addr.type == BADDR_TYPE_IPV6) +#endif // init arguments o->udp_mtu = udp_mtu; @@ -177,6 +499,22 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections o->user = user; o->handler_received = handler_received; +#ifdef BADVPN_SOCKS_UDP_RELAY + // compute MTUs + o->udpgw_mtu = udpgw_compute_mtu(o->udp_mtu); + o->max_connections = max_connections; + + // limit max connections to number of conid's + if (o->max_connections > UINT16_MAX + 1) { + o->max_connections = UINT16_MAX + 1; + } + + // init connections tree by conaddr + BAVL_Init(&o->connections_tree, OFFSET_DIFF(SocksUdpGwClient_connection, conaddr, connections_tree_node), (BAVL_comparator)conaddr_comparator, NULL); + + // init connections list + LinkedList1_Init(&o->connections_list); +#else // init udpgw client if (!UdpGwClient_Init(&o->udpgw_client, udp_mtu, max_connections, send_buffer_size, keepalive_time, o->reactor, o, (UdpGwClient_handler_servererror)udpgw_handler_servererror, @@ -193,6 +531,7 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections // try connecting try_connect(o); +#endif DebugObject_Init(&o->d_obj); return 1; @@ -205,6 +544,13 @@ void SocksUdpGwClient_Free (SocksUdpGwClient *o) { DebugObject_Free(&o->d_obj); +#ifdef BADVPN_SOCKS_UDP_RELAY + // free connections + while (!LinkedList1_IsEmpty(&o->connections_list)) { + SocksUdpGwClient_connection *con = UPPER_OBJECT(LinkedList1_GetFirst(&o->connections_list), SocksUdpGwClient_connection, connections_list_node); + connection_free(con); + } +#else // free SOCKS if (o->have_socks) { free_socks(o); @@ -215,6 +561,7 @@ void SocksUdpGwClient_Free (SocksUdpGwClient *o) // free udpgw client UdpGwClient_Free(&o->udpgw_client); +#endif } void SocksUdpGwClient_SubmitPacket (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, int is_dns, const uint8_t *data, int data_len) @@ -222,7 +569,39 @@ void SocksUdpGwClient_SubmitPacket (SocksUdpGwClient *o, BAddr local_addr, BAddr DebugObject_Access(&o->d_obj); // see asserts in UdpGwClient_SubmitPacket +#ifdef BADVPN_SOCKS_UDP_RELAY + ASSERT(local_addr.type == BADDR_TYPE_IPV4 || local_addr.type == BADDR_TYPE_IPV6) + ASSERT(remote_addr.type == BADDR_TYPE_IPV4 || remote_addr.type == BADDR_TYPE_IPV6) + ASSERT(data_len >= 0) + ASSERT(data_len <= o->udp_mtu) + + // build conaddr + SocksUdpGwClient_conaddr conaddr; + conaddr.local_addr = local_addr; + conaddr.remote_addr = remote_addr; + + // lookup connection + SocksUdpGwClient_connection *con = find_connection(o, conaddr); + + // if no connection and can't create a new one, reuse the least recently used une + if (!con && o->num_connections == o->max_connections) { + con = reuse_connection(o, conaddr); + } + + if (!con) { + // create new connection + con = connection_init(o, conaddr, data, data_len); + } else { + // move connection to front of the list + LinkedList1_Remove(&o->connections_list, &con->connections_list_node); + LinkedList1_Append(&o->connections_list, &con->connections_list_node); + + // send packet to existing connection + connection_send(con, data, data_len); + } +#else // submit to udpgw client UdpGwClient_SubmitPacket(&o->udpgw_client, local_addr, remote_addr, is_dns, data, data_len); +#endif } diff --git a/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.h b/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.h index 217e0ec1..eeda3710 100644 --- a/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.h +++ b/src/main/jni/badvpn/tun2socks/SocksUdpGwClient.h @@ -32,8 +32,20 @@ #include #include #include +#ifdef BADVPN_SOCKS_UDP_RELAY +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else #include #include +#endif typedef void (*SocksUdpGwClient_handler_received) (void *user, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len); @@ -46,14 +58,44 @@ typedef struct { BReactor *reactor; void *user; SocksUdpGwClient_handler_received handler_received; +#ifdef BADVPN_SOCKS_UDP_RELAY + int udpgw_mtu; + int num_connections; + int max_connections; + BAVL connections_tree; + LinkedList1 connections_list; +#else UdpGwClient udpgw_client; BTimer reconnect_timer; int have_socks; BSocksClient socks_client; int socks_up; +#endif DebugObject d_obj; } SocksUdpGwClient; +#ifdef BADVPN_SOCKS_UDP_RELAY +typedef struct { + BAddr local_addr; + BAddr remote_addr; +} SocksUdpGwClient_conaddr; + +typedef struct { + SocksUdpGwClient *client; + SocksUdpGwClient_conaddr conaddr; + BPending first_job; + const uint8_t *first_data; + int first_data_len; + BDatagram udp_dgram; + BufferWriter udp_send_writer; + PacketBuffer udp_send_buffer; + SinglePacketBuffer udp_recv_buffer; + PacketPassInterface udp_recv_if; + BAVLNode connections_tree_node; + LinkedList1Node connections_list_node; +} SocksUdpGwClient_connection; +#endif + int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections, int send_buffer_size, btime_t keepalive_time, BAddr socks_server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info, BAddr remote_udpgw_addr, btime_t reconnect_time, BReactor *reactor, void *user, diff --git a/src/main/jni/badvpn/tun2socks/tun2socks.c b/src/main/jni/badvpn/tun2socks/tun2socks.c index 8aeaf5b5..4730ef43 100644 --- a/src/main/jni/badvpn/tun2socks/tun2socks.c +++ b/src/main/jni/badvpn/tun2socks/tun2socks.c @@ -585,10 +585,15 @@ void print_help (const char *name) " [--password ]\n" " [--password-file ]\n" " [--append-source-to-username]\n" +#ifdef ANDROID + " [--enable-udprelay]\n" + " [--udprelay-max-connections ]\n" +#else " [--udpgw-remote-server-addr ]\n" " [--udpgw-max-connections ]\n" " [--udpgw-connection-buffer-size ]\n" " [--udpgw-transparent-dns]\n" +#endif "Address format is a.b.c.d:port (IPv4) or [addr]:port (IPv6).\n", name ); @@ -820,6 +825,10 @@ int parse_arguments (int argc, char *argv[]) else if (!strcmp(arg, "--append-source-to-username")) { options.append_source_to_username = 1; } +#ifdef ANDROID + else if (!strcmp(arg, "--enable-udprelay")) { + options.udpgw_remote_server_addr = "0.0.0.0:0"; +#else else if (!strcmp(arg, "--udpgw-remote-server-addr")) { if (1 >= argc - i) { fprintf(stderr, "%s: requires an argument\n", arg); @@ -827,8 +836,13 @@ int parse_arguments (int argc, char *argv[]) } options.udpgw_remote_server_addr = argv[i + 1]; i++; +#endif } +#ifdef ANDROID + else if (!strcmp(arg, "--udprelay-max-connections")) { +#else else if (!strcmp(arg, "--udpgw-max-connections")) { +#endif if (1 >= argc - i) { fprintf(stderr, "%s: requires an argument\n", arg); return 0; @@ -839,6 +853,7 @@ int parse_arguments (int argc, char *argv[]) } i++; } +#ifndef ANDROID else if (!strcmp(arg, "--udpgw-connection-buffer-size")) { if (1 >= argc - i) { fprintf(stderr, "%s: requires an argument\n", arg); @@ -853,6 +868,7 @@ int parse_arguments (int argc, char *argv[]) else if (!strcmp(arg, "--udpgw-transparent-dns")) { options.udpgw_transparent_dns = 1; } +#endif else { fprintf(stderr, "unknown option: %s\n", arg); return 0; @@ -959,7 +975,11 @@ int process_arguments (void) // resolve remote udpgw server address if (options.udpgw_remote_server_addr) { if (!BAddr_Parse2(&udpgw_remote_server_addr, options.udpgw_remote_server_addr, NULL, 0, 0)) { +#ifdef ANDROID + BLog(BLOG_ERROR, "udprelay server addr: BAddr_Parse2 failed"); +#else BLog(BLOG_ERROR, "remote udpgw server addr: BAddr_Parse2 failed"); +#endif return 0; } } @@ -2080,7 +2100,11 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote switch (local_addr.type) { case BADDR_TYPE_IPV4: { +#ifdef ANDROID + BLog(BLOG_INFO, "UDP: from udprelay %d bytes", data_len); +#else BLog(BLOG_INFO, "UDP: from udpgw %d bytes", data_len); +#endif if (data_len > UINT16_MAX - (sizeof(struct ipv4_header) + sizeof(struct udp_header)) || data_len > BTap_GetMTU(&device) - (int)(sizeof(struct ipv4_header) + sizeof(struct udp_header)) @@ -2119,10 +2143,18 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote } break; case BADDR_TYPE_IPV6: { +#ifdef ANDROID + BLog(BLOG_INFO, "UDP/IPv6: from udprelay %d bytes", data_len); +#else BLog(BLOG_INFO, "UDP/IPv6: from udpgw %d bytes", data_len); +#endif if (!options.netif_ip6addr) { +#ifdef ANDROID + BLog(BLOG_ERROR, "got IPv6 packet from udprelay but IPv6 is disabled"); +#else BLog(BLOG_ERROR, "got IPv6 packet from udpgw but IPv6 is disabled"); +#endif return; } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index adda7930..b7304bf0 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -77,7 +77,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { def startShadowsocksDaemon() { val cmd: String = (Path.BASE + - "ss-local -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f " + + "ss-local -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -u -f " + Path.BASE + "ss-local.pid") .format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod) if (BuildConfig.DEBUG) Log.d(TAG, cmd) @@ -186,18 +186,24 @@ class ShadowsocksVpnService extends VpnService with BaseService { val fd = conn.getFd - val cmd = (Path.BASE + + var cmd = (Path.BASE + "tun2socks --netif-ipaddr %s " - + "--dnsgw %s:8153 " + "--netif-netmask 255.255.255.0 " + "--socks-server-addr 127.0.0.1:%d " + "--tunfd %d " + "--tunmtu %d " - + "--loglevel 3 " + + "--loglevel 5 " + "--pid %stun2socks.pid") - .format(PRIVATE_VLAN.format("2"), PRIVATE_VLAN.format("1"), config.localPort, fd, VPN_MTU, - Path.BASE) - if (BuildConfig.DEBUG) Log.d(TAG, cmd) + .format(PRIVATE_VLAN.format("2"), config.localPort, fd, VPN_MTU, Path.BASE) + + if (config.isUdpDns) + cmd += " --enable-udprelay" + else + cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1")) + + if (BuildConfig.DEBUG) + Log.d(TAG, cmd) + System.exec(cmd) } @@ -205,7 +211,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { def handleConnection: Boolean = { startVpn() startShadowsocksDaemon() - startDnsDaemon() + if (!config.isUdpDns) startDnsDaemon() true }