View Javadoc
1   /**
2    * This Source Code Form is subject to the terms of the Mozilla Public
3    * License, v. 2.0. If a copy of the MPL was not distributed with this
4    * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5    *
6    * If it is not possible or desirable to put the notice in a particular
7    * file, then You may include the notice in a location (such as a LICENSE
8    * file in a relevant directory) where a recipient would be likely to look
9    * for such a notice.
10  
11   * 
12   */
13   
14  /*  ---------------------------------------------------------------------------
15   *  U.S. Government, Department of the Army
16   *  Army Materiel Command
17   *  Research Development Engineering Command
18   *  Communications Electronics Research Development and Engineering Center
19   *  ---------------------------------------------------------------------------
20   */
21  
22  package org.miloss.fgsms.common;
23  
24  import java.net.InetAddress;
25  import java.net.NetworkInterface;
26  import java.util.ArrayList;
27  import java.util.Enumeration;
28  import java.util.regex.Matcher;
29  import java.util.regex.Pattern;
30  import org.apache.log4j.Level;
31  
32  
33  /**
34   *Provides functionality to convert a requested URL to an absolute URL which is used by fgsms to uniquely identify services
35   * 
36   * @author AO
37   */
38  public class IpAddressUtility {
39  
40      public static final String logname = "fgsms.Utility";
41  /**
42       * Modifies URLs to absolute/unique URLs
43       * if isClient
44       * If an IPv4 address is present and it's one of my IPs, use the hostname
45       * else it will attempt to resolve it
46       * 
47       * if !isClient
48       * replace the server part with my hostname
49       * 
50       * in both cases, explicitly state the port number
51       * @param url
52       * @param isClient
53       * @return http(s)://hostname:port/path
54       */
55      public static String modifyURL(String url, boolean isClient) {
56          if (Utility.stringIsNullOrEmpty(url))
57              throw new IllegalArgumentException("URL cannot be null or empty");
58          String str = url;
59          
60          ArrayList<String> ips = new ArrayList<String>();
61          String host = "localhost";
62          ips.add("127.0.0.1");
63  
64          //attempt to get a list of all local ips address
65          try {
66              InetAddress addr = InetAddress.getLocalHost();
67              host = addr.getHostName().toLowerCase();
68              InetAddress localhost = InetAddress.getLocalHost();
69              ips.add(localhost.getHostAddress());
70              InetAddress[] appmyips = InetAddress.getAllByName(localhost.getCanonicalHostName());
71              if (appmyips != null && appmyips.length > 1) {
72                  for (int i = 0; i < appmyips.length; i++) {
73                      ips.add(appmyips[i].getHostAddress());
74                  }
75              }
76              Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
77              while (en.hasMoreElements()) {
78                  NetworkInterface intf = en.nextElement();
79                  Enumeration<InetAddress> eip = intf.getInetAddresses();
80                  while (eip.hasMoreElements()) {
81                      InetAddress ip = eip.nextElement();
82                      ips.add(ip.getHostAddress());
83                  }
84              }
85          } catch (Exception ex) {
86              Logger.getLogger(logname).log(Level.WARN, "Error caught attempting to obtain local ip addresses " + ex.getLocalizedMessage());
87          }
88  
89  
90  
91          //Clients only, if the url contains localhost or one of MY IP addresses, replace with my hostname, 
92          //else attempt to resolve remote hostname, 
93          //if it resolves, replace
94          //if not, leave it as is
95          if (isClient) {
96  
97              boolean containsLocalhostOrLocalIP = false;
98              if (url.contains("://localhost:")) {
99                  containsLocalhostOrLocalIP = true;
100             }
101             if (url.contains("://localhost/")) {
102                 containsLocalhostOrLocalIP = true;
103             }
104             for (int i = 0; i < ips.size(); i++) {
105                 if (url.contains("://" + ips.get(i) + "/")) {
106                     containsLocalhostOrLocalIP = true;
107                     break;
108                 }
109                 if (url.contains("://" + ips.get(i) + ":")) {
110                     containsLocalhostOrLocalIP = true;
111                     break;
112                 }
113             }
114             if (containsLocalhostOrLocalIP) {
115 
116                 String prefix = str.substring(0, 5).toLowerCase();
117                 for (int i = 0; i < ips.size(); i++) {
118                     //  http://local/something
119                     if (prefix.equals("https")) {
120                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":443/");
121                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
122                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":443/");
123                     } else if (prefix.equals("http:")) {
124                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":80/");
125                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
126                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":80/");
127 
128                     } else { //who knows what it is
129                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + "/");
130                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
131                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + "/");
132                     }
133 
134                 }
135                 if (str.startsWith("jms:")) {
136                     str = str.replaceFirst("\\:[a-zA-Z0-9\\-\\.]+:", host);
137                 }
138                 Logger.getLogger(logname).log(Level.DEBUG, "URL Modifier - original " + url + " modified " + str + " client=true");
139                 return str;
140             }
141 
142 
143             String ipurl = ContainsIPAddress(str);
144             if (!Utility.stringIsNullOrEmpty(ipurl)) {
145 
146                 //ok this transaction was captured from a client agent and the service is not co-located (not one of my ip addresses)
147                 //if the request url contains an ip address
148                 //attempt to reverse dns the ip address, replace and return
149                 try {
150                     try {
151                         // Get hostname by textual representation of IP address
152                         InetAddress addr = InetAddress.getByName(ipurl);
153 
154                         // Get canonical host name
155                         host = addr.getHostName().toLowerCase();
156                         if (Utility.stringIsNullOrEmpty(host)) {
157                             host = ipurl;
158                         }
159                     } catch (Exception e) {
160                         host = ipurl;
161                     }
162 
163                     str = str.replaceFirst(ipurl, host);
164                     // for (int i = 0; i < ips.size(); i++) {
165                     //  str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", host);
166                     //  str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", host);
167                     //  str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", host);
168                     //  }
169                     if (str.startsWith("jms:")) {
170                         str = str.replaceFirst("\\:[a-zA-Z0-9\\-\\.]+:", "\\:" + host);
171                     }
172                 } catch (Exception ex) {
173                     Logger.getLogger(logname).log(Level.WARN, "Client side url modifier, error caught trying to rdns the remote entry of  " + url + ex.getLocalizedMessage());
174                 }
175                 Logger.getLogger(logname).log(Level.DEBUG, "URL Modifier - original " + url + " modified " + str + " client=true");
176                 return str;
177             } else {
178                 //url contains some kind of host name which isn't localhost, 
179                 //attempt to resolve to IP, if it's one of my IP addresses, replace with my hostname (handler host file entries)
180                 String hostname = "";
181                 // hostname = r2.Match(url).Value;
182                 String hostnameregex = "://([^/:]+)";
183                 Pattern p = Pattern.compile(hostnameregex);
184                 Matcher m = p.matcher(str);
185                 boolean find = m.find();
186                 if (!find)
187                 {
188                     Logger.getLogger(logname).log(Level.DEBUG, "unexpected error modifing the url " + url + " maybe it's not an actual url?");
189                     return url;
190                 }
191                 hostname = str.substring(m.start(), m.end());
192                 hostname = hostname.replace("://", "");
193                 boolean found = false;
194                 //this should now be an ipaddress or hostname
195                 try {
196                     InetAddress localaddr = InetAddress.getByName(hostname);
197                     String hostnameip = localaddr.getHostAddress();
198                     for (int i = 0; i < ips.size(); i++) {
199                         if (ips.get(i).equalsIgnoreCase(hostnameip)) {
200                             //here's a bug, we need the regex patterns here
201                             found = true;
202 
203                             //Logger.getLogger(logname).log(Level.DEBUG, "URL Modifier - original " + url + " modified " + str + " client=true");
204                             //return str;
205                         }
206                     }
207                     //ok now we need to test for ports
208                 } catch (Exception e) {
209                 }
210                 if (found) {
211                     String prefix = str.substring(0, 5).toLowerCase();
212                     if (prefix.equals("https")) {
213                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":443/");
214                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
215                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":443/");
216                     } else if (prefix.equals("http:")) {
217                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":80/");
218                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
219                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":80/");
220 
221                     } else if (str.startsWith("jms:")) {
222                         str = str.replaceFirst("\\:[a-zA-Z0-9\\-\\.]+:", host);
223                     } else { //who knows what it is
224                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + "/");
225                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
226                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + "/");
227                     }
228                     //str = str.replace(hostname, host);
229                 }
230                 else
231                 {
232                      {
233                     String prefix = str.substring(0, 5).toLowerCase();
234                     if (prefix.equals("https")) {
235                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + hostname + ":443/");
236                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + hostname + ":");
237                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + hostname + ":443/");
238                     } else if (prefix.equals("http:")) {
239                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + hostname + ":80/");
240                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + hostname + ":");
241                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + hostname + ":80/");
242 
243                     } else if (str.startsWith("jms:")) {
244                         str = str.replaceFirst("\\:[a-zA-Z0-9\\-\\.]+:", hostname);
245                     } else { //who knows what it is
246                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + hostname + "/");
247                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + hostname + ":");
248                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + hostname + "/");
249                     }
250                     //str = str.replace(hostname, host);
251                 }
252                 }
253                 Logger.getLogger(logname).log(Level.DEBUG, "URL Modifier - original " + url + " modified " + str + " client=true");
254                 return str;
255 
256 
257             }
258 
259         } else { //inbound request to a server, thus whatever the hostname is in the url, replace with the actual hostname of this machine
260 
261 
262             /* URL u = null;
263             try {
264             u = new URL(url);
265             } catch (MalformedURLException ex) {
266             // Logger.getLogger(DataPusher.class.getName()).log(Level.SEVERE, null, ex);
267             }
268             if (u != null) {
269             String h1 = u.getHost();
270             for (int i = 0; i < ips.size(); i++) {
271             str = str.replaceFirst(h1, host);
272             }
273             } else*/ {
274                 String prefix = str.substring(0, 5).toLowerCase();
275                 for (int i = 0; i < ips.size(); i++) {
276                     if (prefix.equals("https")) {
277                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":443/");
278                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
279                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":443/");
280                     } else if (prefix.equals("http:")) {
281                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + ":80/");
282                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
283                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + ":80/");
284 
285                     } else { //who knows what it is
286                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + "/");
287                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
288                         str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + "/");
289                     }
290                     //      str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+\\/", "://" + host + "/");
291                     //      str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+:", "://" + host + ":");
292                     //     str = str.replaceFirst("\\://[a-zA-Z0-9\\-\\.]+?$", "://" + host + "/");
293                 }
294 
295                 if (str.contains("?")) {
296                     str = str.substring(0, str.indexOf("?"));
297                 }
298             }
299 
300             if (str.startsWith("jms:")) {
301                 str = str.replaceFirst("\\:[a-zA-Z0-9\\-\\.]+:", ":" + host + ":");
302             }
303         }
304         Logger.getLogger(logname).log(Level.DEBUG, "URL Modifier - original " + url + " modified " + str);
305 
306         return str;
307     }
308 
309     /**
310      * IPv4 only
311      * @param str
312      * @return 
313      */
314     private static String ContainsIPAddress(String str) {
315         if (Utility.stringIsNullOrEmpty(str)) {
316             return "";
317         }
318         String reg = "\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b";
319         String worker = str;
320         try {
321             Pattern p = Pattern.compile(reg);
322             Matcher m = p.matcher(worker);
323             if (m.find()) {
324                 return str.substring(m.start(), m.end());
325             } else {
326                 return "";
327             }
328 
329         } catch (Exception ex) {
330         }
331         return "";
332     }
333 }