0

I log all visits to my website, such as date, url requested, and IP Address. I gained a few entries today from an "internal" IP of the format 10.x.x.x. Whoever this was, accessed several links on my site, and I can't tell what this "connection" was doing exactly. I really want to ask, "how" did they spoof their IP, "what" was likely this "connection's" intent, "how" did they receive any data back from my site if they are using an internal IP? I hope these questions aren't too vague.

Thanks

2
  • IP addresses used for TCP connections cannot be spoofed. Tell us more about your server's hosting situation.
    – EEAA
    Apr 8, 2017 at 5:25
  • I'm running on a linode box that proxies requests through nginx to apache. I have this PHP code that determines the connection's IP address, and along with other data, logs it to a MySQL database. Its just a basic LAMP website pretty much. Hope that was enough info for you Apr 8, 2017 at 6:02

1 Answer 1

2

Since your server "proxies requests through nginx to apache" you might see the proxy-server's internal IP-address (although you would normally then see that in all requests) rather than the clients IP-address.

If your proxy server adds a header with the original IP-address and your application records that header, you need to ensure the proxy server actually replaces the ip-address in that header if it is already present.

For instance in situations where the client is also behind a proxy that sets the same header i.e

client with internal-IP 
\__ client-proxy sets "X-forwarded-for: internal-IP" 
   \__ (internet) 
      \__ your nginx proxy passes unmodified "X-forwarded-for: internal-IP" 
         \__ PHP reads the  internal-IP

where you would need:

client with internal-IP 
\__ client-proxy sets "X-forwarded-for: internal-IP" 
   \__ (internet) 
      \__ your nginx proxy sets a replacement "X-forwarded-for: public-IP-of-client-proxy" 
         \__ PHP reads the public-IP-of-client-proxy

It could also be that nginx appends the public-IP-of-client-proxy to the existing header and you need to check your code to see how it would handles multiple values.


In response to your comment:

Your PHP code is the following:

function get_ip_address() {
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
                    return $ip;
                }
            }
        }
    }
}

That code checks for a number of different (potential) headers and will return the first header that contains a valid IP-address and if no such headers are present it will return the server variable $_SERVER[REMOTE_ADDR] which contains the client IP-address apache detected.

In case of a reverse proxy $_SERVER[REMOTE_ADDR] will always be the ip-address of your proxy, so that probably doesn't tell you what you want to know.

A fairly common thing to do is to instruct your reverse proxy to set a header with the client ip-address as detected by the proxy.
In your nginx config that would look like:

location /some/path/ {
    proxy_set_header FORWARDED_FOR $remote_addr;
    proxy_pass http://apache.example.com:8000/some/path;
}

Apache with mod_php will make that available as the _SERVER[HTTP_FORWARDED_FOR] header and there you go: your code detects the correct remote ip-address of the client.

Except that your code falls apart if another header, that has precedence in your code, is already set. I.E. When a client request with the custom header CLIENT_IP: <some-ip> gets parsed by your code, that is the ip-address that will be detected by your PHP function, instead of the actual client ip-address.

Test what happens with for instance: curl -H "CLIENT_IP: 10.0.0.0" http://yoursite.example.com/

Solution: in your code only accept the actual header that you set in nginx, or use nginx to unset or overwrite all the potential headers that your code is looking for.

6
  • Thank you. I have less than 20 "internal IP" records (out of almost 200k total). That's why I'm doubting my server config is the issue. I'm going to attach the PHP code I use to get the IP address. It looks like it tries several variables to get the value from, and it's possible I'm reading the wrong variable in some cases. pastebin.com/jzcA6ZZF Maybe I need to patch this PHP code?? Apr 8, 2017 at 13:36
  • But I could be wrong about how nginx is handling the headers. It's a very plain nginx configuration to be honest, it's not doing much. I could post that too if it helps, but hopefully the PHP code is where I can fix this Apr 8, 2017 at 13:44
  • see my edit in response to your code
    – HBruijn
    Apr 8, 2017 at 16:01
  • Thank you, I think my best bet is to update the nginx config so my php code reads the right value! Maybe I can set a custom header, and place priority on that header in the php code. Something like, NGINX_CONFIG_CLIENT_IP I guess Apr 8, 2017 at 17:33
  • This PHP code will accept and log whatever IP address is specified in the header, whether that's what you want or not. In reality, you only want to the accept these particular headers from specific server IP addresses (in the case of your Apache instance, only accept this header from the Nginx server's IP; and in the case of your Nginx instance, drop all of the headers, etc).
    – oo.
    Apr 9, 2017 at 0:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.