Android examples for Network:IP Address
Get outbound IP address
/***************************************************************************** * Project: Android IPv6Config//from w ww . ja va2 s . c o m * Description: Android application to change IPv6 kernel configuration * Author: Ren? Mayrhofer * Copyright: Ren? Mayrhofer, 2011-2014 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. *****************************************************************************/ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.NetworkInterface; import java.net.SocketException; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.Enumeration; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import android.annotation.SuppressLint; import android.util.Log; public class Main { /** Our logger for this class. */ private final static Logger logger = null; /** * This is the host queried for the externally visible IPv6 address of the * client when connecting to Internet services. The host name is resolved to * IPv6 addresses (AAAA DNS entries) to make sure that we connect via IPv6. */ public final static String GET_OUTBOUND_IP_SERVER = "doc.to"; public final static String GET_OUTBOUND_IP_SERVER_ADDRESSv6 = "2002:1fc1:a27a:1::1"; public final static String GET_OUTBOUND_IP_SERVER_ADDRESSv4 = "31.193.162.123"; public final static int GET_OUTBOUND_IP_PORT = 443; public final static String GET_OUTBOUND_IP_URL_PROTOCOL = "https://"; public final static String GET_OUTBOUND_IP_URL_PATH = "/getip/"; /** * This is the URL queried for the externally visible IPv6 address of the client * when connecting to Internet services. */ public final static String GET_OUTBOUND_IP_URL = GET_OUTBOUND_IP_URL_PROTOCOL + GET_OUTBOUND_IP_SERVER + ":" + GET_OUTBOUND_IP_PORT + GET_OUTBOUND_IP_URL_PATH; /** * This method tries to retrieve the IPv6/IPv4 address visible to servers by * querying https://doc.to/getip/. * * Attention: this may take a few seconds - don't do it in the foreground! * * @param queryIPv6 * If true, connects via IPv6. If false, connects via IPv4. * @return the IPv6/IPv4 address of this host that is used to connect to other * hosts or null if IPv6/IPv4 connections to https://doc.to are not * possible. */ public static String getOutboundIPAddress(boolean queryIPv6) { try { // first resolve the host's AAAA entries to make sure to connect to the host via // IPv6 InetAddress[] serverAddrs = InetAddress.getAllByName(GET_OUTBOUND_IP_SERVER); InetAddress server = null; for (InetAddress addr : serverAddrs) { if (queryIPv6 && addr instanceof Inet6Address) { logger.log(Level.FINE, "Resolved " + GET_OUTBOUND_IP_SERVER + " to IPv6 address " + addr.getHostAddress()); if (server == null) server = (Inet6Address) addr; else logger.log(Level.WARNING, "Found multiple IPv6 addresses for host " + GET_OUTBOUND_IP_SERVER + ", but expected only one. Will use the one found first " + server.getHostAddress() + " and ignore the one found now " + addr.getHostAddress()); } else if (!queryIPv6 && addr instanceof Inet4Address) { logger.log(Level.FINE, "Resolved " + GET_OUTBOUND_IP_SERVER + " to IPv4 address " + addr.getHostAddress()); if (server == null) server = (Inet4Address) addr; else logger.log(Level.WARNING, "Found multiple IPv4 addresses for host " + GET_OUTBOUND_IP_SERVER + ", but expected only one. Will use the one found first " + server.getHostAddress() + " and ignore the one found now " + addr.getHostAddress()); } } if (server == null) { if (queryIPv6) server = InetAddress.getByName(GET_OUTBOUND_IP_SERVER_ADDRESSv6); else server = InetAddress.getByName(GET_OUTBOUND_IP_SERVER_ADDRESSv4); logger.log(Level.WARNING, "Could not resolve host " + GET_OUTBOUND_IP_SERVER + " to " + (queryIPv6 ? "IPv6" : "IPv4") + " address, assuming DNS resolver/server to be broken. " + "Will now try with hard-coded address " + server + " although it may have changed."); } // now that we have the IPv6 address to connect to, query the URL String url = GET_OUTBOUND_IP_URL_PROTOCOL + (queryIPv6 ? ("[" + server.getHostAddress() + "]") : server.getHostAddress()) + ":" + GET_OUTBOUND_IP_PORT + GET_OUTBOUND_IP_URL_PATH; logger.log(Level.FINER, "Querying URL " + url + " for outbound " + (queryIPv6 ? "IPv6" : "IPv4") + " address"); return queryServerForOutboundAddress(url); } catch (UnknownHostException e) { logger.log(Level.WARNING, "Unable to resolve host " + GET_OUTBOUND_IP_SERVER, e); return null; } } /** * This method queries the passed customURL or "https://doc.to/getip/" if null * is given and expects to read the outbound IP address of this client in * return. * * The only reason to use HTTPS instead of plain HTTP is that the latter is * often subject to tampering by deep packet inspection and other potentially * unsafe Internet practices. Therefore, we don't care about validating the * particular HTTPS URL and disable all certificate validation on purpose. If a * man-in-the-middle attack is being performed on this particular connection, * then it is highly unlikely that we will be able to establish an IPv6 tunnel * anyways. * * @param customURL * The URL to query. If null, GET_OUTBOUND_IP_URL will be used. * @return the outbound IP address of this host as seen be the server. */ @SuppressLint("TrulyRandom") public static String queryServerForOutboundAddress(String customURL) { String url = customURL != null ? customURL : GET_OUTBOUND_IP_URL; try { // setup 1 before querying the URL: enable following HTTP redirects HttpURLConnection.setFollowRedirects(true); // setup 2 before querying the URL: disable certificate checks // create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; // install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // and also disable hostname verification HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); // finally query the HTTPS URL // URLConnection conn = new URL("https", "[2002:5078:37d:1::19]", 443, // GET_OUTBOUND_IP_URL_PATH).openConnection(); URLConnection conn = new URL(url).openConnection(); conn.setUseCaches(false); // doesn't seem to be required /* * conn.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) "); * conn.setRequestProperty("Accept","[star]/[star]"); */ logger.log(Level.FINE, "Connecting to URL " + url); conn.connect(); if (conn instanceof HttpURLConnection) { int statusCode = ((HttpURLConnection) conn).getResponseCode(); logger.log(Level.FINE, "URL " + url + " returned content type " + conn.getContentType() + " and status code " + statusCode); if (statusCode < 200 || statusCode >= 300) { logger.warning("Querying for server-resolved IP address resulted in status code " + statusCode + ", can not parse response"); return ((HttpURLConnection) conn).getResponseMessage(); } InputStreamReader in = new InputStreamReader((InputStream) conn.getContent()); BufferedReader buff = new BufferedReader(in, 2048); StringBuffer reply = new StringBuffer(); String line = null; do { line = buff.readLine(); if (line != null) { if (reply.length() > 0) reply.append("\n"); reply.append(line); } } while (line != null); return reply.toString(); } return null; } catch (MalformedURLException e) { logger.log(Level.SEVERE, "Internal error: URL deemed invalid " + url, e); return null; } catch (IOException e) { logger.log(Level.WARNING, "Unable to connect to URL " + url + " and/or host " + GET_OUTBOUND_IP_SERVER, e); return null; } catch (NoSuchAlgorithmException e) { logger.log(Level.WARNING, "Unable to install custom TrustManager/SSLContext without certificate validation", e); return null; } catch (KeyManagementException e) { logger.log(Level.WARNING, "Unable to install custom TrustManager/SSLContext without certificate validation", e); return null; } } }