44

As far as I've understood, if you try to issue a HTTP request with a spoofed IP address, then the TCP handshake fails, so it's not possible to complete the HTTP request, because the SYN/ACK from the server doesn't reach the evil client ...

...in most cases. But let's now mostly disregard these four cases:
- Man in the middle (MITM) attacks
- The case when the evil client controls the network of the Web server
- The case when the evil client fakes another IP on its own local network
- BGP attacks

Then I can indeed trust the IP address of a HTTP request?

Background: I'm thinking about building a map of IP addresses and resource usage, and block IP addresses that consume too much resources. But I'm wondering if there is, for example, some way to fake an infinit number of IP addresses (by issuing successful HTTP requests with faked IPs), so that the Web server's resource-usage-by-IP-buffers grows huge and causes out-of-memory errors.

(Hmm, perhaps an evil Internet router could fake very many requests. But they aren't evil are they. (This would be a MITM attack? That's why I said mostly disregard, above))

KajMagnus
  • 687
  • 1
  • 5
  • 10
  • 1
    Standard boilerplate warning about `X-Forwarded-For`/`mod_rpaf`/`X-Real-IP`/etc. applies here. Those values cannot be trusted unless you can trust the source of the values. This includes the Apache variable `REMOTE_ADDR` if you are using `mod_rpaf` or the newer module for 2.4 and later that does the same thing. – Ladadadada May 02 '12 at 08:49
  • To clarify, you are concerned about the impact of using/implementing per-IP rate limits at the application layer and any additional vulnerability to denial-of-service attacks? – MattH May 02 '12 at 09:45
  • @MattH: Yes, perhaps that's the question I should have asked. I wonder if doing that, in the app layer, introduces additional vulnerabilities, yes. – KajMagnus May 02 '12 at 10:02
  • What do you mean by "trust"? Yes, it's the TCP/IP end point - but the request may, for example, be proxied via an XSS victim. – symcbean May 02 '12 at 11:40
  • Just set a fixed size limit on the map. If the map gets too large, remove the entry that is the oldest or that tracks the fewest resources or something like that. – David Schwartz May 02 '12 at 12:21
  • @symcbean Yes that's probably what I meant by "trust". XSS victims is an interesting thought :-) seems like a lightweight botnet – KajMagnus May 02 '12 at 15:43
  • @DavidSchwartz Yes I'll set a fixed size or use Google Guava's [CacheBuilder](http://docs.guava-libraries.googlecode.com/git/javadoc/index.html) – KajMagnus May 02 '12 at 15:45
  • There are difficult issues with per-IP resource meter even **without IP spoofing**. And it is even a lot more difficult with IPv6 (like, close to impossible). – curiousguy Aug 20 '12 at 17:23

3 Answers3

26

Yes (with your assumptions of neglecting the client being able to intercept the return of the handshake at a spoofed IP) if you do things correctly. HTTP requests are done over TCP; until the handshake is completed the web server doesn't start processing the HTTP request. Granted a random user could attempt to spoof the end of a handshake; but as they have to guess the server generated ACK, they should only have a 1 in 2^32 (~4 billion) chance of doing it successfully each time.

As Ladadadada commented make sure you aren't picking up the wrong value of the remote IP address in your web application. You want the IP address from the IP datagram header (specifically, the source IP address). You do not want values like X-Forwarded-For / X-Real-IP that can be trivially forged as they are set in the HTTP header. Definitely test by trying to spoof some IP addresses; with say a browser plugin or manually with telnet yourserver.com 80.

The purpose of these fields is so web proxies (that may say cache content to serve it faster) can communicate to webservers the user's real IP address rather than the proxies IP address (which may be for hundreds of users). However, since anyone can set this field it should not be trusted.

dr jimbob
  • 38,768
  • 8
  • 92
  • 161
2

Can I trust the source IP of an HTTP request?

You can be reasonably assured that the source IP address of an HTTP request is the source address of the TCP connection that generated the request.

When to trust an IP address is a complicated context-specific question, but it isn't really what you're asking.

you are concerned about the impact of using/implementing per-IP rate limits at the application layer and any additional vulnerability to denial-of-service attacks?

I wonder if doing that, in the app layer, introduces additional vulnerabilities, yes.

It depends entirely on your implementation, both policy and technology.

  • What sort of resource do you want to rate limit consumption of?
  • What do you want to achieve by creating this rate limit?
  • Over what period of time do you want to perform accounting?
  • Where do you want to apply the limit?
  • Is IP address the best key for the rate limit?
  • What are the likely reasons for over consumption?
  • What should the user experience be in the event of over consumption?

Depending on the answers to these questions, the rate limit may be better placed elsewhere in the service infrastructure, e.g. dedicated firewall, local firewall. Or if access is authenticated, then the authenticated credential may be a better key for rate accounting and your bounds would be defined.

MattH
  • 121
  • 1
  • Okay, so I might need to add rate limiting both in the firewall (`iptables`) and in the application. It would actually be very easy to DoS the application, if only `iptables` did some rate limiting (some server functions do somewhat heavy database queries). But if `iptables` did no rate limiting, then I suppose generic DDoS attacks would become a lot easier. – KajMagnus May 02 '12 at 20:19
  • If users authenticate themselves, then I currently intend to track resource usage (for disk usage, emails sent, database IO) in a quota system. And inform them nicely, when they're running out of quota. – KajMagnus May 02 '12 at 20:22
  • >"Is IP address the best key for the rate limit?" -- Hmm, is there anything else? I can think of this: 1) IP address. 2) user id, if the user identifies him/herself. 3) Ethernet interface, e.g. `eth0`. But I cannot come up with any other keys. Perhaps subnet address in some manner? Or all IPs belonging to a certain country? Hmm. (Do you have some other ideas?) – KajMagnus May 02 '12 at 20:31
  • iptables does offer rate limiting. If you have only authenticated users of your service, then username is a good key to limit their activity. The results of heavy DB queries can (should) be cached (e.g. memcached) were possible... think `F5` hissy-fit protection. – MattH May 02 '12 at 20:43
1

What would be the point in issuing spoofed SYN to a HTTP server if you don't intend to continue the TCP handshake? Your web server won't see the HTTP request unless the (possibly faked) client gets the SYN/ACK, and continues to establish the TCP session, and sends a HTTP request.

Store the database on disk, structure it cleverly (like a tree) for fast lookups.

If the client is spoofed or not, does that really make a difference for you? If they misbehave, they misbehave, no matter if they are spoofed or not.

From a web server point of view, I would consider the remote IP being the true remote IP.

MattBianco
  • 231
  • 3
  • 9
  • >"Store the database on disk" - Hadn't thought of that. Thanks. Could be a good idea, so perhaps there need be no out-of-memory application errors. (I wonder if it'd make other DoS attacks possible though if file access is slow. But I could cache parts of the file in RAM.) – KajMagnus May 02 '12 at 08:44
  • >"If the client is spoofed or not, does that really make a difference for you?" -- If it were possible to generate an terribly huge amount of spoofed IP numbers it would make a difference. Otherwise I think not. – KajMagnus May 02 '12 at 08:45
  • >> "What would be the point in issuing spoofed SYN to a HTTP server if you don't intend to continue the TCP handshake?" -- I don't know, I wouldn't do it :-) SYN flood attack perhaps? – KajMagnus May 02 '12 at 08:54