diff --git a/Dockerfile b/Dockerfile index 0b8274c..fa2281a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,11 +13,11 @@ RUN sed 's/GeoLite2-ASN_[0-9]*.tar.gz/GeoLite2-ASN.tar.gz/g' -i GeoLite2-ASN.tar RUN sha256sum -c GeoLite2-ASN.tar.gz.sha256 RUN tar xvf GeoLite2-ASN.tar.gz --strip 1 -RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-Country&suffix=tar.gz" -O GeoLite2-Country.tar.gz -RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-Country&suffix=tar.gz.sha256" -O GeoLite2-Country.tar.gz.sha256 -RUN sed 's/GeoLite2-Country_[0-9]*.tar.gz/GeoLite2-Country.tar.gz/g' -i GeoLite2-Country.tar.gz.sha256 -RUN sha256sum -c GeoLite2-Country.tar.gz.sha256 -RUN tar xvf GeoLite2-Country.tar.gz --strip 1 +RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-City&suffix=tar.gz" -O GeoLite2-City.tar.gz +RUN wget "${MAXMIND_BASE_URL}edition_id=GeoLite2-City&suffix=tar.gz.sha256" -O GeoLite2-City.tar.gz.sha256 +RUN sed 's/GeoLite2-City_[0-9]*.tar.gz/GeoLite2-City.tar.gz/g' -i GeoLite2-City.tar.gz.sha256 +RUN sha256sum -c GeoLite2-City.tar.gz.sha256 +RUN tar xvf GeoLite2-City.tar.gz --strip 1 FROM alpine:3.17 as release LABEL name="ipinfo.tw" diff --git a/README.md b/README.md index 7cfbde7..7766ace 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,33 @@ Without any specified URI, the server will return IP address, country, AS, and u If you prefer to receive a machine-readable result, use path `/json` (without trailing slash), e.g. `https://ipinfo.tw/json`, the result will look like: ```json -{"ip":"3.115.123.234","country_code":"JP","country_name":"Japan","asn":"16509","as_desc":"Amazon.com, Inc.","user_agent":"curl/7.58.0"} +{ + "ip": "3.115.123.234", + "country_code": "JP", + "country_name": "Japan", + "asn": "16509", + "as_desc": "AMAZON-02", + "latitude": "35.68930", + "longitude": "139.68990", + "accuracy_radius": "1000", + "time_zone": "Asia/Tokyo", + "user_agent":"curl/7.58.0" +} +``` + +This will also work with ip lookup +```json +{ + "ip": "3.115.123.234", + "country_code": "JP", + "country_name": "Japan", + "asn": "16509", + "as_desc": "AMAZON-02", + "latitude": "35.68930", + "longitude": "139.68990", + "accuracy_radius": "1000", + "time_zone": "Asia/Tokyo" +} ``` #### Endpoints @@ -70,11 +96,28 @@ You can also specify the following URI to retrieve certain info: - `country`: Country code and name - `country_code`: Country code - `country_name`: Country name +- `city_name`: City name +- `geo`: Longitude & Latitude +- `accuracy_radius`: Longitude & Latitude accuracy +- `time_zone`: Timezone - `as`: AS number and description - `asn`: AS number - `as_desc`: AS description - `user_agent`: User agent string +You can also specify the following URI to retrieve certain info about an IP. Replace "{ip_address}" with the IPv4 or IPv6 you want to lookup. +- `lookup/{ip_address}/ip`: IP address +- `lookup/{ip_address}/country`: Country code and name +- `lookup/{ip_address}/country_code`: Country code +- `lookup/{ip_address}/country_name`: Country name +- `lookup/{ip_address}/city_name`: City name +- `lookup/{ip_address}/geo`: Longitude & Latitude +- `lookup/{ip_address}/accuracy_radius`: Longitude & Latitude accuracy +- `lookup/{ip_address}/time_zone`: Timezone +- `lookup/{ip_address}/as`: AS number and description +- `lookup/{ip_address}/asn`: AS number +- `lookup/{ip_address}/as_desc`: AS description + Examples: ```sh @@ -110,6 +153,35 @@ Google LLC $ wget -qO- https://ipinfo.tw/user_agent Wget + +$ wget -qO- https://ipinfo.tw/lookup/157.230.195.167 +157.230.195.167 +SG / Singapore +AS14061 / DigitalOcean, LLC + +$ curl https://ipinfo.tw/lookup/18.179.200.1/ip +18.179.200.1 + +$ curl https://ipinfo.tw/lookup/18.179.200.1/country +TW / Taiwan + +$ curl https://ipinfo.tw/lookup/18.179.200.1/country_code +HK + +$ curl https://ipinfo.tw/lookup/18.179.200.1/country_name +South Korea + +$ curl https://ipinfo.tw/lookup/18.179.200.1/as +AS16509 / Amazon.com, Inc. + +$ curl https://ipinfo.tw/lookup/18.179.200.1/as +AS8075 / Microsoft Corporation + +$ curl https://ipinfo.tw/lookup/18.179.200.1/asn +15169 + +$ curl https://ipinfo.tw/lookup/18.179.200.1/as_desc +Google LLC ``` ##### Database build time endpoint @@ -119,8 +191,9 @@ There is a special endpoint - `/build_epoch`, which will return a json object th The response of `/build_epoch` will be look like: ```json -{"GeoLite2-Country":"1655395486","GeoLite2-ASN":"1655730848"} +{"GeoLite2-City":"1655395486","GeoLite2-ASN":"1655730848"} ``` +These are also included in the headers as `X-GeoLite2-City-Build` and `X-GeoLite2-ASN-Build`. As mentioned above, on the demo domain - `ipinfo.tw`, if `https://` is not specified in the URL, connection will be redirected from http to https, in this case, `curl` will need an additional parameter: `-L`/`--location` to follow location redirection. @@ -163,4 +236,4 @@ This project is released under the GPL-3.0 license. [5]:https://alpinelinux.org/ [6]:https://nginx.org/ [7]:https://github.com/leev/ngx_http_geoip2_module -[8]:https://www.docker.com/ +[8]:https://www.docker.com/ \ No newline at end of file diff --git a/nginx/conf.d/geoip2.conf b/nginx/conf.d/geoip2.conf index 50051de..1e1cc22 100644 --- a/nginx/conf.d/geoip2.conf +++ b/nginx/conf.d/geoip2.conf @@ -1,13 +1,27 @@ -geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { +geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb { auto_reload 1d; - $ip_country_code source=$remote_addr country iso_code; - $ip_country_name source=$remote_addr country names en; - $ip_country_build_epoch metadata build_epoch; + $ip_country_code source=$remote_addr country iso_code; + $ip_country_name source=$remote_addr country names en; + $ip_city_name source=$remote_addr city names en; + $ip_latitude source=$remote_addr location latitude; + $ip_longitude source=$remote_addr location longitude; + $ip_accuracy_radius source=$remote_addr location accuracy_radius; + $ip_time_zone source=$remote_addr location time_zone; + $lookup_ip_country_code source=$lookup_ip country iso_code; + $lookup_ip_country_name source=$lookup_ip country names en; + $lookup_ip_city_name source=$lookup_ip city names en; + $lookup_ip_latitude source=$lookup_ip location latitude; + $lookup_ip_longitude source=$lookup_ip location longitude; + $lookup_ip_accuracy_radius source=$lookup_ip location accuracy_radius; + $lookup_ip_time_zone source=$lookup_ip location time_zone; + $ip_city_build_epoch metadata build_epoch; } geoip2 /usr/share/GeoIP/GeoLite2-ASN.mmdb { auto_reload 1d; - $ip_asn source=$remote_addr autonomous_system_number; - $ip_aso source=$remote_addr autonomous_system_organization; + $ip_asn source=$remote_addr autonomous_system_number; + $ip_aso source=$remote_addr autonomous_system_organization; + $lookup_ip_asn source=$lookup_ip autonomous_system_number; + $lookup_ip_aso source=$lookup_ip autonomous_system_organization; $ip_as_build_epoch metadata build_epoch; } diff --git a/nginx/conf.d/ipinfo.conf b/nginx/conf.d/ipinfo.conf index a21c46e..e0281ca 100644 --- a/nginx/conf.d/ipinfo.conf +++ b/nginx/conf.d/ipinfo.conf @@ -1,18 +1,17 @@ server { - listen 8080 default_server; - listen [::]:8080 default_server; - server_name _; - add_header X-Powered-By "ipinfo.tw/github" always; + listen 8080 default_server; + listen [::]:8080 default_server; - add_header Cache-Control "no-store" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - add_header Content-Security-Policy "default-src 'none'; img-src 'self'" always; + server_name _; - set $ip_country "$ip_country_code / $ip_country_name"; - set $ip_as "AS$ip_asn / $ip_aso"; + add_header X-Powered-By "ipinfo.tw/github" always; + add_header X-GeoLite2-ASN-Build $ip_as_build_epoch always; + add_header Cache-Control "no-store" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'none'; img-src 'self'" always; location = /favicon.ico { log_not_found off; @@ -26,47 +25,38 @@ server { location = /github { return 301 https://github.com/PeterDaveHello/ipinfo.tw; } - location = /ip { - return 200 "$remote_addr\n"; - } - location = /country { - return 200 "$ip_country\n"; - } - location = /country_code { - return 200 "$ip_country_code\n"; - } - location = /country_name { - return 200 "$ip_country_name\n"; - } - location = /as { - return 200 "$ip_as\n"; - } - location = /asn { - return 200 "$ip_asn\n"; - } - location = /as_desc { - return 200 "$ip_aso\n"; - } - location = /user_agent { - return 200 "$http_user_agent\n"; - } + location ~* ^/index.htm(l)?$ { rewrite ^(.*)$ /; } - location = / { - return 200 "$remote_addr\n$ip_country\n$ip_as\n\n$http_user_agent\n"; - } - location = /json { - default_type application/json; - return 200 "{\"ip\":\"$remote_addr\",\"country_code\":\"$ip_country_code\",\"country_name\":\"$ip_country_name\",\"asn\":\"$ip_asn\",\"as_desc\":\"$ip_aso\",\"user_agent\":\"$http_user_agent\"}\n"; - } + + location ~* "/(.*)" { + default_type ""; + + if ($request_uri ~* "/(.*)") { + add_header Content-Type $ip_response_content_type; + add_header X-Powered-By "ipinfo.tw/github" always; + add_header X-GeoLite2-City-Build $ip_city_build_epoch always; + add_header X-GeoLite2-ASN-Build $ip_as_build_epoch always; + add_header Cache-Control "no-store" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; + add_header Content-Security-Policy "default-src 'none'; img-src 'self'" always; + } + + return 200 $ip_response; +} + location = /build_epoch { - default_type application/json; - return 200 "{\"GeoLite2-Country\":\"$ip_country_build_epoch\",\"GeoLite2-ASN\":\"$ip_as_build_epoch\"}\n"; + default_type application/json; + return 200 "{\"GeoLite2-City\":\"$ip_city_build_epoch\",\"GeoLite2-ASN\":\"$ip_as_build_epoch\"}\n"; } location @404 { - return 404 "404 not found. See https://github.com/PeterDaveHello/ipinfo.tw \n"; + default_type text/plain; + return 404 "404 not found. See https://github.com/PeterDaveHello/ipinfo.tw \n"; } error_page 404 = @404; diff --git a/nginx/conf.d/map.conf b/nginx/conf.d/map.conf new file mode 100644 index 0000000..b7afd68 --- /dev/null +++ b/nginx/conf.d/map.conf @@ -0,0 +1,55 @@ +map $1 $lookup_ip { + # Regex to test for IPv4 in NGINX Map + "~(([0-9]{1,3}\.){3}[0-9]{1,3})" $1; + + # Regex to test for IPv6 in NGINX Map + "~(([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]))" $1; + + default ""; +} + +# If using the requesting IP, use this map block to determine which response to provide. +map $1 $ip_response { + "" "$remote_addr\n$ip_country_code / $ip_country_name\nAS$ip_asn / $ip_aso\n$ip_latitude, $ip_longitude\n$ip_accuracy_radius KM\n$ip_time_zone\n\n$http_user_agent\n"; + "~^ip\/?$" "$remote_addr\n"; + "~^country\/?$" "$ip_country_code / $ip_country_name\n"; + "~^country_code\/?$" "$ip_country_code\n"; + "~^country_name\/?$" "$ip_country_name\n"; + "~^city_name\/?$" "$ip_city_name\n"; + "~^geo\/?$" "$ip_latitude, $ip_longitude\n"; + "~^accuracy_radius\/?$" "$ip_accuracy_radius\n"; + "~^time_zone\/?$" "$ip_time_zone\n"; + "~^(as\/?$)" "AS$ip_asn / $ip_aso\n"; + "~^(asn\/?$)" "$ip_asn\n"; + "~^(as_desc\/?$)" "$ip_aso\n"; + "~^(user_agent\/?$)" "$http_user_agent\n"; + "~^(json)\/?$" "{\"ip\":\"$remote_addr\",\"country_code\":\"$ip_country_code\",\"country_name\":\"$ip_country_name\",\"asn\":\"$ip_asn\",\"as_desc\":\"$ip_aso\",\"latitude\":\"$ip_latitude\",\"longitude\":\"$ip_longitude\",\"accuracy_radius\":\"$ip_accuracy_radius\",\"time_zone\":\"$ip_time_zone\",\"user_agent\":\"$http_user_agent\"}\n"; + + # This section caters to the lookup functionality. + "~^lookup\/?$" "Invalid IP.\n\nPlease enter valid IPv4 or IPv6 address.\n\nExample: /lookup/1.1.1.1 or /lookup/2606:4700:4700:0000:1111\n"; + "~^lookup\/([^\/]+)\/ip\/?$" "$lookup_ip\n"; + "~^lookup\/([^\/]+)\/country\/?$" "$lookup_ip_country_code / $lookup_ip_country_name\n"; + "~^lookup\/([^\/]+)\/country_code\/?$" "$lookup_ip_country_code\n"; + "~^lookup\/([^\/]+)\/country_name\/?$" "$lookup_ip_country_name\n"; + "~^lookup\/([^\/]+)\/city_name\/?$" "$lookup_ip_city_name\n"; + "~^lookup\/([^\/]+)\/geo\/?$" "$lookup_ip_latitude, $lookup_ip_longitude\n"; + "~^lookup\/([^\/]+)\/accuracy_radius\/?$" "$lookup_ip_accuracy_radius\n"; + "~^lookup\/([^\/]+)\/time_zone\/?$" "$lookup_ip_time_zone\n"; + "~^lookup\/([^\/]+)\/as\/?$" "AS$lookup_ip_asn / $lookup_ip_aso\n"; + "~^lookup\/([^\/]+)\/asn\/?$" "$lookup_ip_asn\n"; + "~^lookup\/([^\/]+)\/as_desc\/?$" "$lookup_ip_aso\n"; + "~^lookup\/([^\/]+)\/json\/?$" "{\"ip\":\"$lookup_ip\",\"country_code\":\"$lookup_ip_country_code\",\"country_name\":\"$lookup_ip_country_name\",\"asn\":\"$lookup_ip_asn\",\"as_desc\":\"$lookup_ip_aso\",\"latitude\":\"$lookup_ip_latitude\",\"longitude\":\"$lookup_ip_longitude\",\"accuracy_radius\":\"$lookup_ip_accuracy_radius\",\"time_zone\":\"$lookup_ip_time_zone\"}\n"; + "~^lookup\/([^\/]+)\/?$" "$lookup_ip\n$lookup_ip_country_code / $lookup_ip_country_name\nAS$lookup_ip_asn / $lookup_ip_aso\n$lookup_ip_latitude, $lookup_ip_longitude\n$lookup_ip_accuracy_radius KM\n$lookup_ip_time_zone\n"; + + default "404 not found. See https://github.com/PeterDaveHello/ipinfo.tw \n"; +} + +# If using the requesting IP, use this map block to determine which response type to provide. +map $request_uri $ip_response_content_type { + "~^\/(json)\/?$" application/json; + + # This section caters to the lookup functionality. + "~^\/lookup\/([^\/]+)\/json\/?$" application/json; + + default text/plain; +} \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf index b88ce89..87a2053 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -23,5 +23,8 @@ http { tcp_nodelay on; types_hash_max_size 2048; + map_hash_max_size 2048; + map_hash_bucket_size 1024; + include /etc/nginx/conf.d/*.conf; }