How to pass users actual address to NAM Identity Server when request coming in via Load Balancer or Proxy server
Most NAM setups involve a Load Balancer (LB) fronting either the Access Gateway or Identity Server nodes. When these Load Balancers are set up in SNAT / Proxy mode, the IP address of the incoming request will be that or the LB and not the users IP address. Any NAM decisions that perform an action based on the users IP address are therefor difficult or in some cases not possible.
The Access Gateway has the ability to do Authorization based on the value in the XFF header; the AG automatically appends the users XFF header info into the outgoing request sent to the Web server in case additional checks need to be made there.
The Identity Server has several features that leverage the IP address of the authenticating/authenticated users such as Kerberos challenge exclusion (ability to exclude certain IP addresses from executing contracts as with Kerberos fallback (https://www.netiq.com/documentation/access-manager-41/admin/data/b1tvhkg.html#using_name_pw_form), logging user IP addresses with audit events, role based evaluations, or even tracking session log files looking for user specific information. The IDP unfortunately does not have any checks to parse the XFF header like the AG does, making it more difficult.
Assuming that the LB can inject the X-Forwarded-For HTTP header into requests forwarded to the Identity Server or Access Gateway, there are some external options that may be possible to retrieve the users IP address. This document will outline how the tomcat remoteip filter can be used to help rewrite the incoming IP address of the user request, to the actual user IP address.
This tomcat remoteip filter (http://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/filters/RemoteIpFilter.html) replaces the apparent client remote IP address and hostname for the request with the IP address list presented by a proxy or a load balancer via a request headers (e.g. "X-Forwarded-For").
When enabled, the filter simply scans for the X-Forwarded-For HTTP header in the incoming request and replaces it's internal IP address structures with that IP address and not the actual IP address the request came in from (which would be the LB or Proxy address).
To enable the filter with NAM 4.1 Identity Server, modify the /opt/novell/nids/lib/webapp/WEB-INF/web.xml file and add the following information (replace the LB IP address with your IP address and make sure that the LB can inject the XFF header)
<!-- ================================================= Neil - rewrite XFF header to IP Address - LB IP address is 126.96.36.199 ================================================== -->
The filter does the IP address check before the IDP does, and rewrites the IP address info before passing it to IDP to have tomcat retrieve the client IP address. If the IDP is simply calling request.remoteAddr to retrieve the IP address of the incoming request, then we will have the actual client ip address from the XFF headet returned and not the Load Balancer IP address from where the request came in. In the case of the Kerberos exclude feature above, you could add the users internal subnet to the include list, and anything else outside of that would automatically fallback to another authentication method.
Here's an example of the type of request that would come into the IDP server from the LB when the filter kicks in. To simulate the setup, one could install the 'Modify Headers' Firefox add on, and add the XFF header as shown below.
When accessing my IDP server from this Firefox instance for testing purposes, the XFF header gets added so that the complete headers seen in the incoming request are shows below (can see XFF header - users actual IP address - added with the value that I added into the Modify Headers plugin:
GET /nidp/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept-Encoding: gzip, deflate
The actual page that gets rendered is identical ie. users will see no difference. For the sake of testing and validating the users IP address, I added the following two lines to the default login.jsp page
String sIPAddress = (String)request.getRemoteAddr();
out.println("************************ LOGIN.JSP Source IP Address: "+sIPAddress);
The resulting login page shows the users IP address in red box below, along with the series of HTTP requests generated
Looking at this incoming HTTP request on the IDP server logs (/var/opt/novell/nam/logs/idp/tomcat/catalina.out) in debug mode, we can see that the 'Remote Client IP Address' is rewritten to be 188.8.131.52 ie. the actual users IP address behind the LB.
<amLogEntry> 2015-08-24T17:48:22Z DEBUG NIDS Application:
****** HttpServletRequest Information:
Context Path: /nidp
Servlet Path: /app
Query String: sid=0&sid=0
Path Info: /login
Server Name: nam41sba.lab.novell.com
Server Port: 443
Content Length: 57
Content Type: application/x-www-form-urlencoded
Auth Type: null
Request URL: https://nam41sba.lab.novell.com/nidp/app/login
Host IP Address: 184.108.40.206
Remote Client IP Address: 220.127.116.11
Cookie: (0 of 21): JSESSIONID, E16877A3EDE276C80F4E0249FDC8F2C9
Cookie: (1 of 21): __utma, 47136440.1622976940.1409914128.1438695959.1439985824.15
Cookie: (2 of 21): __utmz, 47136440.1409914128.1.1.utmcsr
Header: Name: x-forwarded-for, Value: 18.104.22.168
Header: Name: connection, Value: keep-alive
Session Id: 39B02761296FF6AFECC92824FA74403F
<amLogEntry> 2015-08-24T17:48:23Z INFO NIDS Application: Event Id: 3014666, Target: cn=basti,ou=sa,o=system, Sub-Target: 39B02761296FF6AFECC92824FA74403F, Note 1: Local, Note 2: Secure Name/Password - Form, Note 3: secure/name/password/uri, Numeric 1: 0, Data: 22.214.171.124 </amLogEntry>
Assuming that we are auditing the user login events, the event triggered with this login is the following, again confirming the users actual IP address is logged.
[Tue, 24 Aug 2015 17:48:24 +0000] [Novell Access Manager\nidp]: AMDEVICEID#DB7471BE99DE2C40: AMAUTHID#6749352DD9BA4274EEE5ADFFA687E8DD: User session was authenticated: [cn=basti,o=novell]. Authentication Type: [Local] Authenticating Entity Name: [Secure Name/Password - Form] Contract Class or Method Name: [secure/name/password/uri] Source IP Address: [126.96.36.199]