appliedsec/pygeoip

error: illegal IP address string passed to inet_pton

vinitkumar opened this issue · 7 comments

error: illegal IP address string passed to inet_pton
  File "django/core/handlers/base.py", line 92, in get_response
    response = middleware_method(request)
  File "newrelic/hooks/framework_django.py", line 223, in wrapper
    return wrapped(*args, **kwargs)
  File "easy_timezones/middleware.py", line 42, in process_request
    tz = db.time_zone_by_addr(ip)
  File "pygeoip/__init__.py", line 583, in time_zone_by_addr
    ipnum = util.ip2long(addr)
  File "pygeoip/util.py", line 39, in ip2long
    return int(binascii.hexlify(socket.inet_pton(socket.AF_INET6, ip
 )), 16)

I suppose it is a bug in pygeoip. We have been getting this crash for sometime in our server. Can you please suggest a workaround or a publish a fix.

As I see socket.AF_INET6 in your trace I assume you pass a IPv6 address, can you tell me which address your are trying to look up?

Note: This error is raised since the underlying inet_pton implementation raise a validation error. See this man page for details in-case you use Linux: http://man7.org/linux/man-pages/man3/inet_pton.3.html

Could this be a case of whitespace around your input address?

>>> socket.inet_pton(socket.AF_INET, '127.0.0.1 ')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
socket.error: illegal IP address string passed to inet_pton

Here:

[28/10/14 4:58:28 pm] Aashish Sangle: 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36',
 'HTTP_VIA': '1.1 gatewaymtl (squid), 1.1 vegur',
 'HTTP_X_FORWARDED_FOR': 'unknown, 185.15.249.252',
[28/10/14 4:58:34 pm] Aashish Sangle: 'REMOTE_ADDR': '10.62.253.228',
 'REMOTE_PORT': '14782',

ip : 'unknown' stack trace from app

So the code doesn't check if it's a valid ip using some regex? You think it is a good idea to make sure the ip passing after confirming it is a valid ip address?

Update:

Found out that squid proxy alters the ip address and appends Unknown to it making the pygeoip and underlying code crash because of an invalid ip address.

I would argue that passing unknown, 185.15.249.252 to the lookup and then get socket.error: illegal IP address string passed to inet_pton back is pretty reasonable and expected. Not sure what we will gain from a catch and raise.

@tiwilliam Actually, I am not passing this IP address as one of our client is accessing the service from behind a firewall. My suggestion is that pygeoip assumes that the IP passed to it is a valid IP address which might not be true when the request comes behind a firewall which modifies the IP address making it an illegal IP address.

The whole point of using a geoip based backend is to provide redirection/timezone awareness (our use case) to the system. If it crashes for requests behinds the firewall, it beats the purpose of using it in first place. I hope you understand my problem. Also, I don't think there is much code involved in getting this fix and it is not going to affect the code in any negative way. Validating an IP address is not a bad thing AFAIK. Please let me know if I misunderstood anything.

I get your point, but in this case I think the error is how your application is parsing the X-Forwarded-For header. X-Forwarded-For may contain a list of hosts, it can for example look like this: 127.0.0.1, 10.62.253.228, 185.15.249.252. I don't think pygeoip is responsible for guessing which one of these you want to lookup. X-Forwarded-For may also contain port numbers, so I will leave this to a proper HTTP library to parse.