CLOUDSTACK-7941: CloudStack should log IP address of actual client even if a 
ReverseProxy is there

(cherry picked from commit f0a4a639de231929bd63f673c4d6adc6bfb5ca80)
Signed-off-by: Rohit Yadav <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/6715c6cc
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/6715c6cc
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/6715c6cc

Branch: refs/heads/4.5
Commit: 6715c6ccfa68b53a3891f49ec98b568511c9cfb9
Parents: dca38d3
Author: Saksham Srivastava <[email protected]>
Authored: Mon Nov 17 16:28:49 2014 +0530
Committer: Rohit Yadav <[email protected]>
Committed: Tue Jan 20 11:32:09 2015 +0530

----------------------------------------------------------------------
 server/src/com/cloud/api/ApiServlet.java | 94 +++++++++++++++++++++------
 1 file changed, 73 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6715c6cc/server/src/com/cloud/api/ApiServlet.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServlet.java 
b/server/src/com/cloud/api/ApiServlet.java
index c7d0609..3d2e843 100644
--- a/server/src/com/cloud/api/ApiServlet.java
+++ b/server/src/com/cloud/api/ApiServlet.java
@@ -16,35 +16,38 @@
 // under the License.
 package com.cloud.api;
 
-import org.apache.cloudstack.api.auth.APIAuthenticationManager;
-import org.apache.cloudstack.api.auth.APIAuthenticationType;
-import org.apache.cloudstack.api.auth.APIAuthenticator;
-import com.cloud.user.Account;
-import com.cloud.user.AccountService;
-import com.cloud.user.User;
-import com.cloud.utils.HttpUtils;
-import com.cloud.utils.StringUtils;
-import com.cloud.utils.db.EntityManager;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiServerService;
 import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.auth.APIAuthenticationManager;
+import org.apache.cloudstack.api.auth.APIAuthenticationType;
+import org.apache.cloudstack.api.auth.APIAuthenticator;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.managed.context.ManagedContext;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.support.SpringBeanAutowiringSupport;
 
-import javax.inject.Inject;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.HashMap;
-import java.util.Map;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.utils.HttpUtils;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.net.NetUtils;
 
 @Component("apiServlet")
 @SuppressWarnings("serial")
@@ -120,7 +123,7 @@ public class ApiServlet extends HttpServlet {
     }
 
     void processRequestInContext(final HttpServletRequest req, final 
HttpServletResponse resp) {
-        final String remoteAddress = req.getRemoteAddr();
+        final String remoteAddress = getClientAddress(req);
         final StringBuilder auditTrailSb = new StringBuilder(128);
         auditTrailSb.append(" ").append(remoteAddress);
         auditTrailSb.append(" -- ").append(req.getMethod()).append(' ');
@@ -304,4 +307,53 @@ public class ApiServlet extends HttpServlet {
             CallContext.unregister();
         }
     }
+
+    //This method will try to get login IP of user even if servlet is behind 
reverseProxy or loadBalancer
+    private String getClientAddress(HttpServletRequest request) {
+        String ip = null;
+        ip = request.getHeader("X-Forwarded-For");
+        ip = getCorrectIPAddress(ip);
+        if (ip != null) {
+            return ip;
+        }
+
+        ip = request.getHeader("HTTP_CLIENT_IP");
+        ip = getCorrectIPAddress(ip);
+        if (ip != null) {
+            return ip;
+        }
+
+        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        ip = getCorrectIPAddress(ip);
+        if (ip != null) {
+            return ip;
+        }
+
+        ip = request.getHeader("Remote_Addr");
+        ip = getCorrectIPAddress(ip);
+        if (ip != null) {
+            return ip;
+        }
+
+        ip = request.getRemoteAddr();
+        return ip;
+    }
+
+    private String getCorrectIPAddress(String ip) {
+        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            return null;
+        }
+        if(NetUtils.isValidIp(ip)) {
+            return ip;
+        }
+        //it could be possible to have multiple IPs in HTTP header, this 
happens if there are multiple proxy in between
+        //the client and the servlet, so parse the client IP
+        String[] ips = ip.split(",");
+        for(String i : ips) {
+            if(NetUtils.isValidIp(i.trim())) {
+                return i.trim();
+            }
+        }
+        return null;
+    }
 }

Reply via email to