├── VERSION ├── 404.php ├── .gitattributes ├── README.md ├── .gitignore ├── config.dist.php ├── .htaccess ├── functions.php ├── stylesheet.css ├── api.php └── index.php /VERSION: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /404.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GeoIP_Server 2 | Simple php geoip server that returns map and json (uses MaxMind data) 3 | 4 | Automate installation and updating MaxMind data: https://github.com/palinkas-jo-reggelt/GeoLite2SQL 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore config file & testing files 2 | /config.php 3 | /test* 4 | 5 | # Ignoring directories 6 | # Both the directory itself and its contents will be ignored. 7 | uploads/ 8 | photos/ 9 | tmp/ 10 | giveout/ -------------------------------------------------------------------------------- /config.dist.php: -------------------------------------------------------------------------------- 1 | 'localhost', 9 | 'username' => 'geoip', 10 | 'password' => 'supersecretpassword', 11 | 'dbname' => 'geoip', 12 | 'table_city' => 'geocity', // table name for city ip data 13 | 'table_loc' => 'citylocations', // table name for city location name data 14 | 'driver' => 'mysql', 15 | 'port' => '3306' 16 | ); 17 | 18 | ?> -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | RewriteRule ^api$ /api.php [NC,L] 3 | RewriteRule ^api/$ /api.php [NC,L] 4 | RewriteRule ^api/(.*)$ /api.php?geoip=$1 [NC,L] 5 | RewriteRule ^map/(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})|((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))))$ /index.php?geoip=$1 [NC,L] 6 | RewriteRule ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})$ /index.php?geoip=$1 [NC,L] 7 | ErrorDocument 404 /404.php 8 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | = ip2long('100.64.0.0')) && (ip2long($geoip) <= ip2long('100.127.255.255'))) {return true;} 12 | else if ((ip2long($geoip) >= ip2long('172.16.0.0')) && (ip2long($geoip) <= ip2long('172.31.255.255'))) {return true;} 13 | else if ((ip2long($geoip) >= ip2long('224.0.0.0')) && (ip2long($geoip) <= ip2long('239.255.255.255'))) {return true;} 14 | else if ((ip2long($geoip) >= ip2long('240.0.0.0')) && (ip2long($geoip) <= ip2long('255.255.255.255'))) {return true;} 15 | else {return false;} 16 | } 17 | 18 | ?> -------------------------------------------------------------------------------- /stylesheet.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #fefefe; 3 | font-family: "Roboto"; 4 | font-size: 12pt; 5 | } 6 | 7 | a:link, a:active, a:visited { 8 | color: #FF0000; 9 | text-transform: underline; 10 | } 11 | 12 | a:hover { 13 | color: #FF0000; 14 | text-transform: none; 15 | } 16 | 17 | .wrapper { 18 | max-width: 900px; 19 | position: relative; 20 | margin: auto; 21 | /* padding-top: 10px; */ 22 | } 23 | 24 | .section { 25 | padding: 5px 0 15px 0; 26 | /* margin: 10px; */ 27 | display: block; 28 | /* border: 1px dashed #ccc; */ 29 | /* border-radius: 20px; */ 30 | } 31 | 32 | .section a:link, a:visited { 33 | color: black; 34 | text-decoration: none; 35 | } 36 | 37 | .section a:hover, a:active { 38 | color: red; 39 | text-decoration: underline; 40 | } 41 | 42 | .section h2 { 43 | font-size:16px; 44 | font-weight:bold; 45 | text-align:left; 46 | } 47 | 48 | .section h3 { 49 | font-size:25px; 50 | font-weight:bold; 51 | text-align:center; 52 | } 53 | 54 | .secleft { 55 | float: left; 56 | width: 50%; 57 | display: block; 58 | } 59 | 60 | .secright { 61 | float: right; 62 | width: 50%; 63 | display: block; 64 | } 65 | 66 | .secinner{ 67 | box-sizing: border-box; 68 | padding: 0 5px 5px 5px; 69 | } 70 | 71 | #map { 72 | max-width: 450px; 73 | width: calc(100vw-10px); 74 | height: 50vh; 75 | } 76 | 77 | .footer { 78 | line-height: 1.5em; 79 | text-align: center; 80 | font-size: 0.6em; 81 | } 82 | 83 | .clear { 84 | clear: both; 85 | } 86 | 87 | /* ### SIMPLE TABLE CSS ### */ 88 | .simple-div-table { 89 | display: table; 90 | width: 100%; 91 | font-size: 0.8em; 92 | border-left: 1px solid #ccc; 93 | border-bottom: 1px solid #ccc; 94 | } 95 | 96 | .simple-div-table-row-header { 97 | display: table-row; 98 | font-weight: bold; 99 | text-align: center; 100 | background: yellow; 101 | } 102 | 103 | .simple-div-table-row { 104 | display: table-row; 105 | } 106 | 107 | .simple-div-table-row:nth-of-type(even) { 108 | background: #eee; 109 | border: 1px solid #ccc; 110 | } 111 | 112 | .simple-div-table-col { 113 | display: table-cell; 114 | padding: 3px; 115 | border-right: 1px solid #ccc; 116 | border-top: 1px solid #ccc; 117 | } 118 | 119 | .center { 120 | text-align: center; 121 | } 122 | 123 | .right { 124 | text-align: right; 125 | } 126 | 127 | .left { 128 | text-align: left; 129 | } 130 | 131 | @media only screen and (max-width: 380px) { 132 | .wrapper { 133 | /* width: 345px; */ 134 | } 135 | .secleft { 136 | float: none; 137 | width: 100%; 138 | } 139 | .secright { 140 | float: none; 141 | margin: 0px; 142 | width: 100% ; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /api.php: -------------------------------------------------------------------------------- 1 | prepare(" 18 | SELECT * 19 | FROM ( 20 | SELECT * 21 | FROM ".$Database['table_city']." 22 | WHERE INET6_ATON('".$geoip."') <= network_end LIMIT 1 23 | ) AS a 24 | INNER JOIN ".$Database['table_loc']." AS b ON a.geoname_id = b.geoname_id 25 | WHERE network_start <= INET6_ATON('".$geoip."'); 26 | "); 27 | $sql->execute(); 28 | while($row = $sql->fetch(PDO::FETCH_ASSOC)){ 29 | $json = array( 30 | 'status'=>200, 31 | 'message'=>'IP Found', 32 | 'data'=>array( 33 | 'reserved_ip'=>false, 34 | 'ip'=>$geoip, 35 | 'postal_code'=>$row["postal_code"], 36 | 'latitude'=>$row["latitude"], 37 | 'longitude'=>$row["longitude"], 38 | 'accuracy_radius'=>$row["accuracy_radius"], 39 | 'locale_code'=>$row["locale_code"], 40 | 'continent_code'=>$row["continent_code"], 41 | 'continent_name'=>$row["continent_name"], 42 | 'country_code'=>$row["country_code"], 43 | 'country_name'=>$row["country_name"], 44 | 'subdivision_1_iso_code'=>$row["subdivision_1_iso_code"], 45 | 'state_abbr'=>$row["subdivision_1_iso_code"], 46 | 'subdivision_1_name'=>$row["subdivision_1_name"], 47 | 'state_name'=>$row["subdivision_1_name"], 48 | 'subdivision_2_iso_code'=>$row["subdivision_2_iso_code"], 49 | 'subdivision_2_name'=>$row["subdivision_2_name"], 50 | 'city_name'=>$row["city_name"], 51 | 'metro_code'=>$row["metro_code"], 52 | 'time_zone'=>$row["time_zone"], 53 | 'is_in_european_union'=>$row["is_in_european_union"] 54 | ) 55 | ); 56 | } 57 | $rowsReturned = $sql->rowCount(); 58 | if ($rowsReturned > 0) { 59 | header('Content-Type: application/json; charset=utf-8'); 60 | echo json_encode($json, JSON_PRETTY_PRINT); 61 | } else { 62 | $json = array( 63 | 'status'=>404, 64 | 'message'=>'Not Found', 65 | 'error'=>array( 66 | 'code'=>404, 67 | 'reserved_ip'=>false, 68 | 'ip'=>$geoip, 69 | 'message'=>'IP GeoIP data could not be found' 70 | ) 71 | ); 72 | header('Content-Type: application/json; charset=utf-8'); 73 | echo json_encode($json, JSON_PRETTY_PRINT); 74 | } 75 | } else { 76 | $json = array( 77 | 'status'=>400, 78 | 'message'=>'Bad Request', 79 | 'error'=>array( 80 | 'code'=>404, 81 | 'reserved_ip'=>true, 82 | 'ip'=>$geoip, 83 | 'message'=>'IP Reserved' 84 | ) 85 | ); 86 | header('Content-Type: application/json; charset=utf-8'); 87 | echo json_encode($json, JSON_PRETTY_PRINT); 88 | } 89 | } else { 90 | $json = array( 91 | 'status'=>400, 92 | 'message'=>'Bad Request', 93 | 'error'=>array( 94 | 'code'=>404, 95 | 'reserved_ip'=>false, 96 | 'ip'=>null, 97 | 'message'=>'Non IP input data' 98 | ) 99 | ); 100 | header('Content-Type: application/json; charset=utf-8'); 101 | echo json_encode($json, JSON_PRETTY_PRINT); 102 | } 103 | 104 | ?> -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | GeoIP 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
"; 30 | 31 | if (isPrivateOrLoopback($geoip)) { 32 | echo " 33 |
34 |

GEOIP

35 |
36 | ".$geoip." IS A RESERVED ADDRESS!

37 | Check your own address: ".preg_replace("/https?:\/\//","",$base_url)."/map/".$_SERVER['REMOTE_ADDR']."

38 |
39 |
"; 40 | } else { 41 | 42 | echo " 43 |
44 |

GEOIP

45 |
46 |
47 |
48 |
49 |
Description
50 |
Value
51 |
"; 52 | 53 | $sql = $pdo->prepare(" 54 | SELECT * 55 | FROM ( 56 | SELECT * 57 | FROM ".$Database['table_city']." 58 | WHERE INET6_ATON('".$geoip."') <= network_end LIMIT 1 59 | ) AS a 60 | INNER JOIN ".$Database['table_loc']." AS b ON a.geoname_id = b.geoname_id 61 | WHERE network_start <= INET6_ATON('".$geoip."'); 62 | "); 63 | $sql->execute(); 64 | while($row = $sql->fetch(PDO::FETCH_ASSOC)){ 65 | $latitude = $row['latitude']; 66 | $longitude = $row['longitude']; 67 | if (strlen($row['accuracy_radius'])>0) {$km = " km";} else {$km = " ";} 68 | if ($row['is_in_european_union']==0) {$eu = "false";} else {$eu = "true";} 69 | $accuracy_radius = $row['accuracy_radius']; 70 | echo " 71 |
72 |
ip 
73 |
".$geoip." 
74 |
75 |
76 |
postal_code 
77 |
".$row['postal_code']." 
78 |
79 |
80 |
latitude 
81 |
".$row['latitude']." 
82 |
83 |
84 |
longitude 
85 |
".$row['longitude']." 
86 |
87 |
88 |
accuracy_radius 
89 |
".$row['accuracy_radius'].$km." 
90 |
91 |
92 |
locale_code 
93 |
".$row['locale_code']." 
94 |
95 |
96 |
continent_code 
97 |
".$row['continent_code']." 
98 |
99 |
100 |
continent_name 
101 |
".$row['continent_name']." 
102 |
103 |
104 |
country_code 
105 |
".$row['country_code']." 
106 |
107 |
108 |
country_name 
109 |
".$row['country_name']." 
110 |
111 |
112 |
subdivision_1_iso_code 
113 |
".$row['subdivision_1_iso_code']." 
114 |
115 |
116 |
state_abbr 
117 |
".$row['subdivision_1_iso_code']." 
118 |
119 |
120 |
subdivision_1_name 
121 |
".$row['subdivision_1_name']." 
122 |
123 |
124 |
state_name 
125 |
".$row['subdivision_1_name']." 
126 |
127 |
128 |
subdivision_2_iso_code 
129 |
".$row['subdivision_2_iso_code']." 
130 |
131 |
132 |
subdivision_2_name 
133 |
".$row['subdivision_2_name']." 
134 |
135 |
136 |
city_name 
137 |
".$row['city_name']." 
138 |
139 |
140 |
metro_code 
141 |
".$row['metro_code']." 
142 |
143 |
144 |
time_zone 
145 |
".$row['time_zone']." 
146 |
147 |
148 |
is_in_european_union 
149 |
".$eu." 
150 |
"; 151 | } 152 | 153 | echo " 154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | API: ".preg_replace("/https?:\/\//","",$base_url)."/api/".$geoip." 167 |
168 |
169 | 170 | 171 | "; 198 | } 199 | 200 | echo " 201 | 215 |
216 | 217 | "; 218 | 219 | ?> --------------------------------------------------------------------------------