diff --git a/app/src/main/cpp/src/websocket_client.cpp b/app/src/main/cpp/src/websocket_client.cpp index 4034f8bd..55abc625 100644 --- a/app/src/main/cpp/src/websocket_client.cpp +++ b/app/src/main/cpp/src/websocket_client.cpp @@ -67,6 +67,7 @@ Java_org_fptn_vpn_services_websocket_NativeWebSocketClientImpl_nativeCreate( jstring server_ip_param, jint server_port_param, jstring tun_ipv4_param, + jstring tun_ipv6_param, jstring sni_param, jstring access_token_param, jstring expected_md5_fingerprint_param, @@ -76,24 +77,25 @@ Java_org_fptn_vpn_services_websocket_NativeWebSocketClientImpl_nativeCreate( auto server_ip = fptn::wrapper::ConvertToCString(env, server_ip_param); int server_port = server_port_param; auto tun_ipv4 = fptn::wrapper::ConvertToCString(env, tun_ipv4_param); + auto tun_ipv6 = fptn::wrapper::ConvertToCString(env, tun_ipv6_param); auto sni = fptn::wrapper::ConvertToCString(env, sni_param); auto access_token = fptn::wrapper::ConvertToCString(env, access_token_param); auto expected_md5_fingerprint = fptn::wrapper::ConvertToCString(env, expected_md5_fingerprint_param); - const auto censorship_strategy_name = fptn::wrapper::ConvertToCString( + const auto censorship_strategy_name = fptn::wrapper::ConvertToCString( env,censorship_strategy_name_param); - fptn::protocol::https::CensorshipStrategy censorship_strategy = + fptn::protocol::https::CensorshipStrategy censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSni; - if (censorship_strategy_name == "OBFUSCATION") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kTlsObfuscator; - } else if (censorship_strategy_name == "SNI-REALITY") { - censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode; - } + if (censorship_strategy_name == "OBFUSCATION") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kTlsObfuscator; + } else if (censorship_strategy_name == "SNI-REALITY") { + censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode; + } jobject global_object_ref = env->NewWeakGlobalRef(thiz); auto* websocket_client = new WrapperWebsocketClient(global_object_ref, - std::move(server_ip), server_port, std::move(tun_ipv4), std::move(sni), + std::move(server_ip), server_port, std::move(tun_ipv4), std::move(tun_ipv6), std::move(sni), std::move(access_token), std::move(expected_md5_fingerprint), censorship_strategy); auto jobj_client = reinterpret_cast(websocket_client); diff --git a/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.cpp b/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.cpp index 9439fc87..7e4f7414 100644 --- a/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.cpp +++ b/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.cpp @@ -23,6 +23,7 @@ WrapperWebsocketClient::WrapperWebsocketClient(jobject wrapper, std::string server_ip, int server_port, std::string tun_ipv4, + std::string tun_ipv6, std::string sni, std::string access_token, std::string expected_md5_fingerprint, @@ -33,6 +34,7 @@ WrapperWebsocketClient::WrapperWebsocketClient(jobject wrapper, server_ip_(std::move(server_ip)), server_port_(server_port), tun_ipv4_(std::move(tun_ipv4)), + tun_ipv6_(std::move(tun_ipv6)), sni_(std::move(sni)), access_token_(std::move(access_token)), expected_md5_fingerprint_(std::move(expected_md5_fingerprint)), @@ -97,8 +99,7 @@ void WrapperWebsocketClient::Run() { try { const auto server_ip_addr = fptn::common::network::IPv4Address::Create(server_ip_); const auto tun_ipv4_addr = fptn::common::network::IPv4Address::Create(tun_ipv4_); - const auto tun_ipv6_addr = fptn::common::network::IPv6Address::Create( - FPTN_CLIENT_DEFAULT_ADDRESS_IP6); + const auto tun_ipv6_addr = fptn::common::network::IPv6Address::Create(tun_ipv6_); if (!server_ip_addr.IsValid() || !tun_ipv4_addr.IsValid() || !tun_ipv6_addr.IsValid()) { SPDLOG_ERROR( diff --git a/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.h b/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.h index e9add55c..d912025a 100644 --- a/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.h +++ b/app/src/main/cpp/src/wrappers/wrapper_websocket_client/wrapper_websocket_client.h @@ -20,6 +20,7 @@ class WrapperWebsocketClient final { std::string server_ip, int server_port, std::string tun_ipv4, + std::string tun_ipv6, std::string sni, std::string access_token, std::string expected_md5_fingerprint, @@ -55,6 +56,7 @@ class WrapperWebsocketClient final { const std::string server_ip_; const int server_port_; const std::string tun_ipv4_; + const std::string tun_ipv6_; const std::string sni_; const std::string access_token_; const std::string expected_md5_fingerprint_; diff --git a/app/src/main/java/org/fptn/vpn/enums/ConnectionSubnets.java b/app/src/main/java/org/fptn/vpn/enums/ConnectionSubnets.java index 02c07eda..5185dd96 100644 --- a/app/src/main/java/org/fptn/vpn/enums/ConnectionSubnets.java +++ b/app/src/main/java/org/fptn/vpn/enums/ConnectionSubnets.java @@ -12,29 +12,58 @@ @Getter public enum ConnectionSubnets { - TUN_ADDRESS("10.10.0.1", 32), - TUN_INTERFACE_SUBNET("10.10.0.0", 16), - FPTN_SUBNET("172.16.0.0", 12), - LOCAL_SUBNET("192.168.0.0", 16), - ALL_SUBNET("0.0.0.0", 0), + // todo: fix IPv6 + LOCAL_TUN_ADDRESS("10.10.0.1", 32, "fd00::1", 128), + LOCAL_TUN_INTERFACE_SUBNET("10.10.0.0", 16, "fd00:::", 64), + FPTN_SERVER_SUBNET("172.16.0.0", 12, "fc00:1::", 64), + LOCAL_SUBNET("192.168.0.0", 16, "::::", 128), + ALL_SUBNET("0.0.0.0", 0, "::::", 128); - // todo: rename me! - HZ_WHAT_IS_THIS_IP("172.20.0.1", 32); + private final String ipV4Address; + private final int v4prefix; - private final String ipAddress; - private final int prefix; + private final String ipV6Address; + private final int v6prefix; - ConnectionSubnets(String ipAddress, int prefix) { - this.ipAddress = ipAddress; - this.prefix = prefix; + ConnectionSubnets(String ipV4Address, int v4prefix, String ipV6Address, int v6prefix) { + this.ipV4Address = ipV4Address; + this.v4prefix = v4prefix; + this.ipV6Address = ipV6Address; + this.v6prefix = v6prefix; } @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) - public IpPrefix getAsIpPrefix() throws UnknownHostException { - return new IpPrefix(InetAddress.getByName(ipAddress), prefix); + public IpPrefix getAsIpV4Prefix() throws UnknownHostException { + return new IpPrefix(InetAddress.getByName(ipV4Address), v4prefix); } - public String getAsIPWithPrefix() { - return ipAddress + "/" + prefix; + public String getAsIpV4PrefixAsString() { + return ipV4Address + "/" + v4prefix; } + + @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) + public IpPrefix getAsIpV6Prefix() throws UnknownHostException { + return new IpPrefix(InetAddress.getByName(ipV6Address), v6prefix); + } + + public String getAsIpV6PrefixAsString() { + return ipV6Address + "/" + v6prefix; + } + + public String getIpV4Address() { + return ipV4Address; + } + + public String getIpV6Address() { + return ipV6Address; + } + + public int getIpV4Prefix() { + return v4prefix; + } + + public int getIpV6Prefix() { + return v6prefix; + } + } diff --git a/app/src/main/java/org/fptn/vpn/services/vpn/FptnConnection.java b/app/src/main/java/org/fptn/vpn/services/vpn/FptnConnection.java index fabba69f..5b881675 100644 --- a/app/src/main/java/org/fptn/vpn/services/vpn/FptnConnection.java +++ b/app/src/main/java/org/fptn/vpn/services/vpn/FptnConnection.java @@ -1,11 +1,10 @@ package org.fptn.vpn.services.vpn; import static org.fptn.vpn.enums.ConnectionSubnets.ALL_SUBNET; -import static org.fptn.vpn.enums.ConnectionSubnets.FPTN_SUBNET; -import static org.fptn.vpn.enums.ConnectionSubnets.HZ_WHAT_IS_THIS_IP; +import static org.fptn.vpn.enums.ConnectionSubnets.FPTN_SERVER_SUBNET; import static org.fptn.vpn.enums.ConnectionSubnets.LOCAL_SUBNET; -import static org.fptn.vpn.enums.ConnectionSubnets.TUN_ADDRESS; -import static org.fptn.vpn.enums.ConnectionSubnets.TUN_INTERFACE_SUBNET; +import static org.fptn.vpn.enums.ConnectionSubnets.LOCAL_TUN_ADDRESS; +import static org.fptn.vpn.enums.ConnectionSubnets.LOCAL_TUN_INTERFACE_SUBNET; import android.app.PendingIntent; import android.content.pm.PackageManager; @@ -20,6 +19,7 @@ import org.fptn.vpn.enums.ConnectionState; import org.fptn.vpn.enums.NetworkType; import org.fptn.vpn.enums.PerAppVpnMode; +import org.fptn.vpn.services.websocket.DnsServers; import org.fptn.vpn.services.websocket.WebSocketAlreadyShutdownException; import org.fptn.vpn.services.websocket.WebSocketClientWrapper; import org.fptn.vpn.utils.DataRateCalculator; @@ -32,6 +32,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.InetAddress; +import java.net.UnknownHostException; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; @@ -61,6 +62,8 @@ public class FptnConnection extends Thread { * Maximum packet size is constrained by the MTU */ private static final int MAX_PACKET_SIZE = 1500; + public static final int IP_V4_PREFIX_LENGTH = 32; + public static final int IP_V6_PREFIX_LENGTH = 128; @Getter private final int connectionId; @@ -112,7 +115,7 @@ public FptnConnection(final FptnService service, final String sniHostName, final BypassCensorshipMethod censorshipStrategy, final PerAppVpnMode perAppVpnMode, - final List appInfos) { + final List appInfos) throws UnknownHostException { this.service = service; this.connectionId = connectionId; this.serverEntity = serverEntity; @@ -122,15 +125,19 @@ public FptnConnection(final FptnService service, this.censorshipStrategy = censorshipStrategy; this.perAppVpnMode = perAppVpnMode; this.appInfos = appInfos; + + InetAddress inetAddress = InetAddress.getByName(serverEntity.getHost()); this.webSocketClient = new WebSocketClientWrapper( this.serverEntity, - TUN_ADDRESS.getIpAddress(), + LOCAL_TUN_ADDRESS.getIpV4Address(), + LOCAL_TUN_ADDRESS.getIpV6Address(), this::onConnectionOpen, this::onMessageReceived, this::onConnectionFailure, this.sniHostName, this.censorshipStrategy ); + this.maxReconnectCount = maxReconnectCount; this.delayBetweenAttempts = delayBetweenAttempts; } @@ -143,16 +150,13 @@ public void run() { sendConnectionStateToService(ConnectionState.CONNECTING); VpnService.Builder builder = service.new Builder(); - builder.addAddress(TUN_ADDRESS.getIpAddress(), TUN_ADDRESS.getPrefix()); - builder.addRoute(HZ_WHAT_IS_THIS_IP.getIpAddress(), HZ_WHAT_IS_THIS_IP.getPrefix()); - builder.setMtu(MAX_PACKET_SIZE); - // enable blocking reading - builder.setBlocking(true); - - /* - From documentation: You can create either an allowed list, or, a disallowed list, but not both - */ - if (perAppVpnMode == PerAppVpnMode.ONLY_ALLOWED){ + builder.setBlocking(true) // enable blocking reading EXTREMELY IMPORTANT + .setSession(serverEntity.getName()) + .setConfigureIntent(configureVpnIntent) + .setMtu(MAX_PACKET_SIZE); + + // From documentation: You can create either an allowed list, or, a disallowed list, but not both + if (perAppVpnMode == PerAppVpnMode.ONLY_ALLOWED) { for (AppInfo appInfo : appInfos) { String packageName = appInfo.getPackageName(); try { @@ -161,7 +165,7 @@ public void run() { Log.d(TAG, "Package not found: " + packageName); } } - } else if (perAppVpnMode == PerAppVpnMode.EXCEPT_DISALLOWED){ + } else if (perAppVpnMode == PerAppVpnMode.EXCEPT_DISALLOWED) { for (AppInfo appInfo : appInfos) { String packageName = appInfo.getPackageName(); try { @@ -171,22 +175,33 @@ public void run() { } } } + InetAddress inetAddress = InetAddress.getByName(serverEntity.getHost()); + + DnsServers dns_server = webSocketClient.getDnsServers(); + + // IPv4 + builder.addDnsServer(dns_server.getIpv4()); + builder.addAddress(LOCAL_TUN_ADDRESS.getIpV4Address(), LOCAL_TUN_ADDRESS.getIpV4Prefix()); + builder.addRoute(dns_server.getIpv4(), 32); + + // IPv6 + builder.addDnsServer(dns_server.getIpv6()); + builder.addAddress(LOCAL_TUN_ADDRESS.getIpV6Address(), LOCAL_TUN_ADDRESS.getIpV6Prefix()); + builder.addRoute(dns_server.getIpv6(), 128); - final String dnsServer = webSocketClient.getDnsServerIPv4(); - builder.addDnsServer(dnsServer); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - builder.excludeRoute(new IpPrefix(InetAddress.getByName(serverEntity.getHost()), 32)); - builder.excludeRoute(TUN_INTERFACE_SUBNET.getAsIpPrefix()); - builder.excludeRoute(FPTN_SUBNET.getAsIpPrefix()); - builder.excludeRoute(LOCAL_SUBNET.getAsIpPrefix()); - builder.addRoute(ALL_SUBNET.getIpAddress(), ALL_SUBNET.getPrefix()); + builder.excludeRoute(new IpPrefix(inetAddress, IP_V4_PREFIX_LENGTH)); + builder.excludeRoute(LOCAL_TUN_INTERFACE_SUBNET.getAsIpV4Prefix()); + builder.excludeRoute(FPTN_SERVER_SUBNET.getAsIpV4Prefix()); + builder.excludeRoute(LOCAL_SUBNET.getAsIpV4Prefix()); + builder.addRoute(ALL_SUBNET.getIpV4Address(), ALL_SUBNET.getV4prefix()); } else { - IPAddress rootSubnet = new IPAddressString(ALL_SUBNET.getAsIPWithPrefix()).getAddress(); + IPAddress rootSubnet = new IPAddressString(ALL_SUBNET.getAsIpV4PrefixAsString()).getAddress(); List subnetsToExclude = Stream.of( - serverEntity.getHost() + "/32", - TUN_INTERFACE_SUBNET.getAsIPWithPrefix(), - FPTN_SUBNET.getAsIPWithPrefix(), - LOCAL_SUBNET.getAsIPWithPrefix() + String.format("%s/%s", serverEntity.getHost(), IP_V4_PREFIX_LENGTH), + LOCAL_TUN_INTERFACE_SUBNET.getAsIpV4PrefixAsString(), + FPTN_SERVER_SUBNET.getAsIpV4PrefixAsString(), + LOCAL_SUBNET.getAsIpV4PrefixAsString() ) .map(sub -> new IPAddressString(sub).getAddress()) .collect(Collectors.toList()); @@ -197,12 +212,10 @@ public void run() { String hostIp = ipAddress.getLower().toAddressString().getHostAddress().toString(); Integer networkPrefixLength = ipAddress.getLower().toAddressString().getNetworkPrefixLength(); Log.d(getTag(), "subnetsToInclude.ipAddress: " + hostIp + "/" + networkPrefixLength); - builder.addRoute(hostIp, networkPrefixLength != null ? networkPrefixLength : 32); + builder.addRoute(hostIp, networkPrefixLength != null ? networkPrefixLength : IP_V4_PREFIX_LENGTH); } } - builder.setSession(serverEntity.getName()).setConfigureIntent(configureVpnIntent); - synchronized (service) { vpnInterface = builder.establish(); } diff --git a/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java b/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java index e0513854..f7216f94 100644 --- a/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java +++ b/app/src/main/java/org/fptn/vpn/services/vpn/FptnService.java @@ -46,6 +46,7 @@ import org.fptn.vpn.vpnclient.exception.ErrorCode; import org.fptn.vpn.vpnclient.exception.PVNClientException; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -284,7 +285,8 @@ public int onStartCommand(Intent intent, int flags, int startId) { connect(server, sniHostname); } - } catch (ExecutionException | InterruptedException | RuntimeException e) { + } catch (ExecutionException | InterruptedException | RuntimeException | + UnknownHostException e) { disconnect(new PVNClientException(e.getMessage())); } }); @@ -414,7 +416,7 @@ private void setConnectionState(ConnectionState connectionState, PVNClientExcept .build()); } - private void connect(ServerEntity serverEntity, String sniHostname) { + private void connect(ServerEntity serverEntity, String sniHostname) throws UnknownHostException { // Moving VPNService to foreground to give it higher priority in system updateNotificationWithMessage(getString(R.string.connecting_to) + serverEntity.getServerInfo(), ""); diff --git a/app/src/main/java/org/fptn/vpn/services/websocket/DnsServers.java b/app/src/main/java/org/fptn/vpn/services/websocket/DnsServers.java new file mode 100644 index 00000000..8937a1ff --- /dev/null +++ b/app/src/main/java/org/fptn/vpn/services/websocket/DnsServers.java @@ -0,0 +1,14 @@ +package org.fptn.vpn.services.websocket; + +public class DnsServers { + private final String ipv4; + private final String ipv6; + + public DnsServers(String ipv4, String ipv6) { + this.ipv4 = ipv4; + this.ipv6 = ipv6; + } + + public String getIpv4() { return ipv4; } + public String getIpv6() { return ipv6; } +} diff --git a/app/src/main/java/org/fptn/vpn/services/websocket/NativeWebSocketClientImpl.java b/app/src/main/java/org/fptn/vpn/services/websocket/NativeWebSocketClientImpl.java index 44fbdb39..63af9e0c 100644 --- a/app/src/main/java/org/fptn/vpn/services/websocket/NativeWebSocketClientImpl.java +++ b/app/src/main/java/org/fptn/vpn/services/websocket/NativeWebSocketClientImpl.java @@ -31,7 +31,8 @@ public class NativeWebSocketClientImpl { public NativeWebSocketClientImpl( String host, int port, - String tunAddress, + String tunAddressIPv4, + String tunAddressIPv6, String accessToken, String md5ServerFingerprint, OnOpenCallback onOpenCallback, @@ -53,7 +54,8 @@ public NativeWebSocketClientImpl( this.nativeHandle = nativeCreate( host, port, - tunAddress, + tunAddressIPv4, + tunAddressIPv6, sniHostName, accessToken, md5ServerFingerprint, @@ -134,6 +136,7 @@ public void onMessageImpl(byte[] msg) { private native long nativeCreate(String server_ip, int server_port, String tun_ipv4, + String tun_ipv6, String sni, String access_token, String expected_md5_fingerprint, diff --git a/app/src/main/java/org/fptn/vpn/services/websocket/WebSocketClientWrapper.java b/app/src/main/java/org/fptn/vpn/services/websocket/WebSocketClientWrapper.java index 18aa0c8f..d3b33ed4 100644 --- a/app/src/main/java/org/fptn/vpn/services/websocket/WebSocketClientWrapper.java +++ b/app/src/main/java/org/fptn/vpn/services/websocket/WebSocketClientWrapper.java @@ -21,7 +21,8 @@ public class WebSocketClientWrapper { private static final String LOGIN_URL = "/api/v1/login"; private final ServerEntity serverEntity; - private final String tunAddress; + private final String tunAddressIPv4; + private final String tunAddressIPv6; private final OnOpenCallback onOpenCallback; private final OnMessageReceivedCallback onMessageReceivedCallback; private final OnFailureCallback onFailureCallback; @@ -35,14 +36,16 @@ public class WebSocketClientWrapper { private boolean shutdown = false; public WebSocketClientWrapper(ServerEntity serverEntity, - String tunAddress, + String tunAddressIPv4, + String tunAddressIPv6, OnOpenCallback onOpenCallback, OnMessageReceivedCallback onMessageReceivedCallback, OnFailureCallback onFailureCallback, String sniHostName, BypassCensorshipMethod censorshipStrategy) { this.serverEntity = serverEntity; - this.tunAddress = tunAddress; + this.tunAddressIPv4 = tunAddressIPv4; + this.tunAddressIPv6 = tunAddressIPv6; this.onOpenCallback = onOpenCallback; this.onMessageReceivedCallback = onMessageReceivedCallback; this.onFailureCallback = onFailureCallback; @@ -71,7 +74,8 @@ public synchronized void startWebSocket() throws PVNClientException, WebSocketAl nativeWebSocketClient = new NativeWebSocketClientImpl( serverEntity.getHost(), serverEntity.getPort(), - tunAddress, + tunAddressIPv4, + tunAddressIPv6, accessToken, serverEntity.getMd5ServerFingerprint(), onOpenCallback, @@ -142,24 +146,24 @@ private String getAccessToken() throws PVNClientException { throw new PVNClientException(ErrorCode.CONNECT_TO_SERVER_ERROR); } - public String getDnsServerIPv4() throws PVNClientException { + public DnsServers getDnsServers() throws PVNClientException { NativeResponse response = nativeHttpsClient.Get(DNS_URL, 15); - if (response != null) { - if (response.code == 200) { - try { - JSONObject jsonResponse = new JSONObject(response.body); - String dnsServer = jsonResponse.getString("dns"); - Log.i(getTag(), "DNS " + dnsServer + " retrieval successful."); - return dnsServer; - } catch (JSONException e) { - Log.e(getTag(), "Some error occurs on receiving DNS response: " + e); - throw new PVNClientException(ErrorCode.CONNECT_TO_SERVER_ERROR); - } + if (response != null && response.code == 200) { + try { + JSONObject jsonResponse = new JSONObject(response.body); + String ipv4 = jsonResponse.getString("dns"); + String ipv6 = jsonResponse.getString("dns_ipv6"); + Log.i(getTag(), "DNS_IPv4: " + ipv4 + " DNS_IPv6: " + ipv6); + return new DnsServers(ipv4, ipv6); + } catch (JSONException e) { + Log.e(getTag(), "Error parsing DNS response: " + e); + throw new PVNClientException(ErrorCode.CONNECT_TO_SERVER_ERROR); } } throw new PVNClientException(ErrorCode.CONNECT_TO_SERVER_ERROR); } + private String getTag() { return this.getClass().getCanonicalName(); } diff --git a/app/src/main/java/org/fptn/vpn/utils/NetworkUtils.java b/app/src/main/java/org/fptn/vpn/utils/NetworkUtils.java index 834c62d7..5d2ccad5 100644 --- a/app/src/main/java/org/fptn/vpn/utils/NetworkUtils.java +++ b/app/src/main/java/org/fptn/vpn/utils/NetworkUtils.java @@ -8,6 +8,7 @@ import org.fptn.vpn.enums.NetworkType; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -28,7 +29,8 @@ public static String getCurrentIPAddress() { while (inetAddressEnumeration.hasMoreElements()) { InetAddress inetAddress = inetAddressEnumeration.nextElement(); if (!inetAddress.isLoopbackAddress() - && inetAddress instanceof Inet4Address) { //!inetAddress.getHostAddress().contains(":") + && (inetAddress instanceof Inet4Address || inetAddress instanceof Inet6Address)) { + Log.d(TAG, "getCurrentIPAddress(): " + inetAddress.getHostAddress()); return inetAddress.getHostAddress(); } }