Skip to content

Instantly share code, notes, and snippets.

@fffonion
Last active November 16, 2022 08:57
Show Gist options
  • Save fffonion/44e5fb59e2a8f0efba5c1965c6043584 to your computer and use it in GitHub Desktop.
Save fffonion/44e5fb59e2a8f0efba5c1965c6043584 to your computer and use it in GitHub Desktop.
Simple GeoIP and ASNnum query server http://ip.yooooo.us
  • nginx with ngx_http_geoip_module, echo-nginx-module, lua-nginx-module is required; libgeoip needs to be installed and geoip database should be placed under /usr/share/GeoIP.
  • http://example.com for current GeoIP and http://example.com/ip for current IP only
  • http://example.com/x.x.x.x to query any IP.
  • http://example.com/domain-name for GeoIP of domain-name and http://example.com/domain-name/ip to return IP of domain-name only. If multiple IPs are set to single domain-name, all of them will be returned. Only A record will be used.
  • Sample requests are:
$ curl http://example.com/
x.x.x.x
Country, Region, City
ASN number

$ curl http://example.com/ip
x.x.x.x

$ curl http://example.com/rdns
x.x.x.x.com

$ curl http://example.com/74.125.203.199
74.125.203.199  th-in-f199.1e100.net
United States, California, Mountain View
AS15169 Google Inc.

$ curl http://example.com/www.google.com.hk
74.125.203.199  th-in-f199.1e100.net
United States, California, Mountain View
AS15169 Google Inc.

$ curl http://example.com/www.google.com.hk/ip
74.125.203.199

$ curl http://example.com/www.google.com.hk/dns
www-wide.l.google.com 74.125.203.199

  • Run update_geoip.sh with root privilege to update GeoIP databases.
geoip_city /usr/share/GeoIP/GeoLiteCity.dat utf8;
geoip_org /usr/share/GeoIP/GeoIPASNum.dat;
geoip_proxy 127.0.0.1;
log_format app_log '$remote_addr [$time_local] "$request" $status $body_bytes_sent '
'$request_time $http_host "$http_referer" $http_user_agent';
map $remote_addr $app_loggable {
default 1;
"127.0.0.1" 0;
"::1" 0;
}
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/ip-access.log app_log if=$app_loggable;
error_log /var/log/nginx/ip-error.log warn;
location = / {
default_type "text/plain";
content_by_lua_block {
local query_ip = ngx.var.remote_addr
if ngx.var.remote_addr == "127.0.0.1"then
query_ip = ngx.var.http_x_forwarded_for
end
local resolver = require "resty.dns.resolver"
local r, err = resolver:new {
nameservers = {"8.8.8.8", {"8.8.4.4", 53} },
retrans = 5,
timeout = 2000
}
local rdns = ""
while true do
if not r then
ngx.log(ngx.ERR, "can't new resolver", err)
break
end
local answers, err = r:reverse_query(query_ip)
if not answers or #answers == 0 then
break
end
rdns = answers[1].ptrdname
break
end
if rdns then
ngx.say(query_ip .. " " .. rdns)
else
ngx.say(query_ip)
end
local has_line = false
if ngx.var.geoip_city_country_name ~= nil then
ngx.print(ngx.var.geoip_city_country_name)
has_line = true
end
if ngx.var.geoip_region_name ~= nil then
ngx.print(", ", ngx.var.geoip_region_name)
has_line = true
end
if ngx.var.geoip_city ~= nil then
ngx.print(", ", ngx.var.geoip_city)
has_line = true
end
if has_line then
ngx.print("\n")
end
if ngx.var.geoip_org ~= nil then
ngx.say(ngx.var.geoip_org)
end
}
}
location ~ ^/([\d\.\:]+)$ {
set_by_lua $query_ip '
local m, err = ngx.re.match(ngx.var.uri, "^/(.+)")
if m then
ngx.log(ngx.INFO, "ip", m[1])
return m[1]
end
';
set $up "http://127.0.0.1/";
proxy_set_header X-Forwarded-For $query_ip;
proxy_set_header Host $http_host;
proxy_pass $up;
proxy_hide_header 'Content-Type';
proxy_hide_header 'Vary';
proxy_hide_header 'Access-Control-Allow-Origin';
add_header 'Content-Type' 'text/plain';
add_header 'Vary' 'Accept-Encoding';
add_header 'Access-Control-Allow-Origin' '*';
}
location = /ip {
default_type "text/plain";
echo $remote_addr;
}
location = /rdns {
default_type "text/plain";
content_by_lua_block {
local resolver = require "resty.dns.resolver"
local r, err = resolver:new {
nameservers = {"8.8.8.8", {"8.8.4.4", 53} },
retrans = 5,
timeout = 2000
}
local rdns = "default"
if not r then
ngx.log(ngx.ERR, "can't new resolver", err)
ngx.exit(200)
end
local answers, err = r:reverse_query(ngx.var.remote_addr)
if not answers or #answers == 0 then
ngx.exit(200)
end
rds = answers[1].ptrdname
ngx.say(rds or "")
}
}
location ~ /([^/]+)/*([^/]*)$ {
default_type "text/plain";
set $query_host $1;
set $qopt $2;
content_by_lua_block {
local resolver = require "resty.dns.resolver"
local r, err = resolver:new {
nameservers = {"8.8.8.8", {"8.8.4.4", 53} },
retrans = 5,
timeout = 2000
}
if not r then
ngx.log(ngx.ERR, "can't new resolver", err)
ngx.exit(500)
end
local answers, err = r:query(ngx.var.query_host)
if not answers then
ngx.log(ngx.ERR, "query error", ngx.var.query_host, ":", err, " answer: ", answers.errcode, answers.errstr)
ngx.exit(200)
elseif #answers == 0 then
ngx.exit(200)
end
if string.len(ngx.var.qopt) > 0 then
table.foreach(answers, function(i, a)
if ngx.var.qopt == "dns" and a.cname then
ngx.print(a.cname.. " ")
end
if a.address then
ngx.say(a.address)
end
end)
else
local _ = {}
table.foreach(answers, function(i, a)
if a.address then
table.insert(_, {"/"..a.address})
end
end)
if #_ == 0 then
ngx.exit(200)
end
local resps = { ngx.location.capture_multi(_) }
for i, resp in ipairs(resps) do
ngx.say(resp.body)
end
end
}
}
}
wget -q http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoIPASNum.dat.new && mv /usr/share/GeoIP/GeoIPASNum.dat{.new,}
wget -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoLiteCity.dat.new && mv /usr/share/GeoIP/GeoLiteCity.dat{.new,}
wget -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoIP.dat.new && mv /usr/share/GeoIP/GeoIP.dat{.new,}
wget -q http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNumv6.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoIPASNumv6.dat.new && mv /usr/share/GeoIP/GeoIPASNumv6.dat{.new,}
wget -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoLiteCityv6.dat.new && mv /usr/share/GeoIP/GeoLiteCityv6.dat{.new,}
wget -q http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz -O - |gzip -d > /usr/share/GeoIP/GeoIPv6.dat.new && mv /usr/share/GeoIP/GeoIPv6.dat{.new,}
@ipsecguy
Copy link

ipsecguy commented Dec 7, 2018

Hi,

I am using your code and get different location results compared to http://ip.yooooo.us/ (mine are less accurate). Any chance you use a better maxmind (maybe the new geoip2 free) on the that site?

Andreas

@fffonion
Copy link
Author

fffonion commented Nov 27, 2019

Hi @ipsecguy, thanks for your interests! I'm currently working on putting geoip2 lite onto this site, using the magic from https://github.com/sherpya/geolite2legacy.

You can also get a converted dat file from https://www.miyuru.lk/geoiplegacy (found on the internet) or https://dl.yooooo.us/share/GeoIP-Legacy/ (WIP).

@giraffeyo007
Copy link

giraffeyo007 commented May 26, 2021

Hello,

It can help me I don't know much .conf configuration where I put it can set the directorys, it also works on .onion sites?

@fffonion
Copy link
Author

Hi @giraffeyo007, the configuration is for Nginx/Openresty, it doesn't matter if it's onion site or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment