0

I'm trying to write a simple geolocation thing that will pass the IP address at the end of the URL to a query string.

In my apache.conf I have the following directives:

RewriteEngine On
RewriteBase /geo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} .*/([0-9_._]+)/?$
RewriteRule .*  /lookup.php?ip=%1  [L,QSA]

So Im looking to have the URL:

https://example.com/geo/100.101.0.101  or
https://example.com/geo/100.101.0.101/

Send the ipv4 address to:

 https://example.com/lookup.php?ip=100.101.0.101

Having it work with ipv6 would be a super as well.

Michael Fever
  • 845
  • 2
  • 8
  • 26

1 Answers1

0

Your Rewrite is not 100% accurate

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# IPv4
RewriteCond %{REQUEST_URI} ^/?geo/([0-9\.]+)/?$ [NC,OR]
# IPv6
RewriteCond %{REQUEST_URI} ^/?geo/([0-9a-f:]+)/?$ [NC]
RewriteRule ^.*$  /lookup.php?ip=%1  [L,QSA]

Explanation:

RewriteBase /geo/ makes only sense if you do e.g. RewriteRule ^.*$ lookup.php?ip=%1 [L,QSA] and lookup.php is actually in http://example.com/geo/lookup.php

The %{REQUEST_URI} should start with geo/<ip> dependent on your server a leading /is include.

An IP includes only numbers (0-9), a-f (only IPv6) and . or : depending on the version of the IP address (IPv4 or IPv6).

At the moment it is also possible to send invalid formated IP addresses like, /geo/999..777.444 but I assume you will check this in your App. But if you have /geo/xx+666=765 than this will not be rewritten at all.

If you really want to only rewrite valid IP addresses than you have to use a much complexer RegEx:

# IPv4 
RewriteCond %{REQUEST_URI} ^/?geo/(((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/?$ [NC,OR]
# IPv6  
RewriteCond %{REQUEST_URI} ^/?geo/(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/?$ [NC]

Based on RegEx from https://stackoverflow.com/a/17871737/5427950

I tested this positive an an Ubuntu 16.04.03 LTS server with Apache 2.4.27

Webdesigner
  • 1,954
  • 1
  • 9
  • 16