Previously we had opened a case regarding the use of the Request.ServerVariable("REMOTE_ADDR") in ASP code. When we front our ASP sites with the LTM this Server Variable is changed to the a self-ip on the ltm. Since this code reference is pervasive we'd has preferred to not change it, but changing was certainly an option (undesirable nonetheless). However, we have discovered that we have a few vendor packages written in .NET and ASP that also use REMOTE_ADDR, and the issue is that we have no control over their code. We need to get a solution that will essentially substitute the client ip into the header so that it will be consumed by REMOTE_ADDR correctly. I was trying to work with the following iRule but I don't know what header value to change so that REMOTE_ADDR will pick it up.

HTTP::header replace REMOTE_ADDR [IP::remote_addr]

Also, we tried Layer4 Forwarding without any success. I think that the iRule should "fit the bill", but I have no idea what to replace. Is there a list of header values you pass from the LTM that we could look at so we can determine which one contains the self-ip which is subsequently pulled by REMOTE_ADDR?

14 Answer(s):


You will need to change the application code or disable SNAT. REMOTE_ADDR is a CGI variable which IIS provides based on the source IP address of the TCP packet. It is not set based on an HTTP header value.

So if you're using SNAT and want to get the original client IP address, you can enable insertion of the X-Forwarded-For HTTP header on a custom HTTP profile. This dictates that LTM insert the original client IP address in an HTTP header named X-Forwarded-For. You would need to change all references in the application from REMOTE_ADDR to HTTP_X_FORWARDED_FOR.

For more info, you can check SOL4816:

SOL4816 - Using the X-Forwarded-For HTTP header to preserve the original client IP address for traffic translated by a SNAT (Click here)

Hi Aaron,

Thanks for the update.
Is there any way of doing this without using the x-forwarded method. say I dont have access to the back end servers?

If you can change the default gateway of the servers to the LTM's floating self IP address on the server VLAN (and no clients access the virtual server from the same VLAN as the servers) you could disable SNAT on the virtual server. If you need to use SNAT, you'd need to change the app to parse the client IP address from a custom HTTP header like the XFF header.

If you're using the client IP address for anything but reporting, you should also remove any pre-existing XFF headers by setting the HTTP profile option for 'Header to Remove' to X-Forwarded-For. This ensures that LTM will remove any XFF headers inserted by a previous device in the chain before inserting its own XFF header.

Hi Aaron,

Many thanks for the options, I will see how best I can use this in my set up and let you know the outcome.
We need to utilize Auto Map SNAT so that our traffic can be routed
properly through our ASM (Our ASM functionality would not work without
it). Also, we have vendor code that references REMOTE_ADDR so changing
it to reference XFF header is not an option for us.

Do you have a standalone ASM unit (or units) being load balanced by an LTM unit? If so, I think auto lasthop on the ASM would ensure the response to the client goes back from the ASM to the LTM even if the LTM is not performing SNAT. This assumes the flow is:

client - LTM - ASM - server

We do indeed have the architecture you mention, but we have our pools
configured with priority groups so that the LTM will route directly to
our servers if the ASM is non-functional. Would this matter?
I don't see how that would work without SNAT on the LTM or on the ASM, as I think the server would need to dynamically update it's routing table based on the state of the ASM unit. Anyone else have ideas?

Do you have two ASM units? If so, you wouldn't need to worry about failing open directly to the web server pool.

The configuration involving the priority group for direct access to the
HTTP servers via the LTM in case of ASM failover was suggested and
configured by an F5 ASM consultant as best practice. We do indeed have a
failover pair of ASMs but the consultant deemed this configuration as
the best way to ensure 0% downtime for our properties.
Have you heard of anyone loading an ISAPI filter on the IIS server
directly to make this change? I saw a posting on devcentral in which the
developer "faked" IIS into adding the Xforward information into the IIS
logs instead of the actual client ip. Perhaps the same "fake" could be
done for standard use of REMOTE_ADDR. Thoughts?
If you have a pair of ASM units, I personally don't see the need to fail open direct to the pool. But I don't have all of the details of your implementation and requirements. What would take both ASM units down? Would you also need to account for a similar possibility of both LTM units going down simultaneously? If you're concerned about the ASM processes themselves, I suppose you could configure a non-ASM VIP on the ASM units and add that as a lower priority pool member on the LTMs.

The XFF logging DLL which Joe created (Click here) will log the XFF value, but won't change the CGI variable REMOTE_ADDR which IIS sets.

The following was sent from our F5 account engineer. Thoughts on her

In order for the BIG-IP to enhance the performance and security of
application traffic, that traffic has to go into and out of the BIG-IP
(or any load balancer). If a server that is behind the BIG-IP uses the
BIG-IP as its default gateway, then the original client address is
retained. The source IP is that of the client and can be used by the
server. This is a routed configuration and probably the most common
If a real server does not use the BIG-IP as the gateway, then the only
way to get traffic back to the BIG-IP is to use "SNAT". With SNAT, the
BIG-IP changes the IP source address of the client to the BIG-IP's
address. Then the server will send traffic back to the BIG-IP. The
"SNAT" configuration is also very common. Since the original client
address is no longer in the packet, a header is inserted, usually the
X-Forwarded-For header, that includes the client address. Then the web
server runs some code to extract the client IP value. Here is a link to
the IIS filter at F5 DevCentral: The X-Forwarded-For
header is a de facto standard and widely used anytime a load balancer is
The only other option is to use an "npath" configuration. In this setup,
the real server accepts traffic directed to the virtual IP address and
the return traffic bypasses the BIG-IP. This requires special setup on
the real server and is much less commonly used, since its use eliminates
much of the benefit of having an application delivery platform and it is
not as easy to support.
I agree with all of that, with two clarifications: the DLL will modify the IP address which IIS logs. I don't think it will have any effect on the SERVER_ADDR CGI variable. And with ASM it is important that the response go back through ASM so that you can see what effect the request had on the server (ie the response code from the web server). Also, there might be an issue where ASM wastes resources waiting for the response that will never arrive. This is a guess though. So I don't think nPath is a good solution with ASM.

I think a reasonable solution would be to depend on redundancy of the active-standby ASM units. Or if you're very concerned about ASM on both units being affected by some kind of attack, you could create a second non-ASM VIP on the ASM units and use that as a lower priority member in the LTM pool.

I don't know much about IIS, but some searching brings me, which seems to be pretty definitive (if you look at the comments) that there is no way on IIS to change that variable. The only way to make it be the real client IP is to have your IIS server receive traffic from the real client IP.

You also said that your ASM setup (ASM is something else I'm not an expert on) requires SNAT. I'm going to assume that that's true. In that case, even vlangroups will not help. So as far as I can see, there is no clean solution.

There's one wacky thing that *might* work, though, which is have the packets coming from the ASM be rewritten to have the real client IPs. One way to accomplish this *might* be via tagged vlans. The traffic flow would be:

1) Traffic comes in to your LTM from the Internet on, say, VLAN 100.
2) The LTM inserts a custom header with the real client IP
3) The LTM SNATs the traffic and sends it to the ASM on VLAN 100.
4) The ASM sends the traffic back to another, different VIP on the LTM on, say, VLAN 200.
5) The LTM, via an iRule, reads the custom header, and re-SNATs the traffic back to the original client IP, and sends it to the server on VLAN 200.

I think that this should work, and that auto-lasthop should make things just work for the return traffic.

This assumes your servers support tagged VLANs (which they really should). If they don't, then you might be able to accomplish the same thing with Route Domains on v10.x.

Again, I can't promise this is a solution, but it might be worth trying.
Unfortunately I think I may have been steering us down the wrong path.
For the site on which we're trying to retrieve the client IP we don't
not use the ASM. The traffic for this site is routed directly from the
LTM to the IIS server. Since that is the case what would your suggestion
be outside of making a gateway change on the IIS server (Which we have
attempted multiple times without success).

Your answer: