import ipaddress import maxminddb from fastapi import FastAPI, Request import json import datetime import logging import sys import os from logging.handlers import RotatingFileHandler LOG_FILE = os.path.join('/code', 'ip_query.log') try: formatter = logging.Formatter('%(message)s') log_handler = RotatingFileHandler( LOG_FILE, maxBytes=10*1024*1024, backupCount=5, encoding='utf-8' ) log_handler.setFormatter(formatter) logger = logging.getLogger('ip_query') logger.setLevel(logging.INFO) logger.addHandler(log_handler) startup_log = { "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "事件": "系统启动", "状态": "成功" } logger.info(json.dumps(startup_log, ensure_ascii=False)) except Exception as e: print(f"日志初始化失败: {e}") sys.exit(1) city_reader = maxminddb.open_database('GeoLite2-City.mmdb') asn_reader = maxminddb.open_database('GeoLite2-ASN.mmdb') cn_reader = maxminddb.open_database('GeoCN.mmdb') lang = ["zh-CN", "en"] asn_map = { 9812: "东方有线", 9389: "中国长城", 17962: "天威视讯", 17429: "歌华有线", 7497: "科技网", 24139: "华数", 9801: "中关村", 4538: "教育网", 24151: "CNNIC", 38019: "中国移动", 139080: "中国移动", 9808: "中国移动", 24400: "中国移动", 134810: "中国移动", 24547: "中国移动", 56040: "中国移动", 56041: "中国移动", 56042: "中国移动", 56044: "中国移动", 132525: "中国移动", 56046: "中国移动", 56047: "中国移动", 56048: "中国移动", 59257: "中国移动", 24444: "中国移动", 24445: "中国移动", 137872: "中国移动", 9231: "中国移动", 58453: "中国移动", 4134: "中国电信", 4812: "中国电信", 23724: "中国电信", 136188: "中国电信", 137693: "中国电信", 17638: "中国电信", 140553: "中国电信", 4847: "中国电信", 140061: "中国电信", 136195: "中国电信", 17799: "中国电信", 139018: "中国电信", 134764: "中国电信", 4837: "中国联通", 4808: "中国联通", 134542: "中国联通", 134543: "中国联通", 59019: "金山云", 135377: "优刻云", 45062: "网易云", 37963: "阿里云", 45102: "阿里云国际", 45090: "腾讯云", 132203: "腾讯云国际", 55967: "百度云", 38365: "百度云", 58519: "华为云", 55990: "华为云", 136907: "华为云", 4609: "澳門電訊", 13335: "Cloudflare", 55960: "亚马逊云", 14618: "亚马逊云", 16509: "亚马逊云", 15169: "谷歌云", 396982: "谷歌云", 36492: "谷歌云", } def get_as_info(number): r = asn_map.get(number) if r: return r def get_des(d): for i in lang: if i in d['names']: return d['names'][i] return d['names']['en'] def get_country(d): r = get_des(d) if r in ["香港", "澳门", "台湾"]: return "中国" + r return r def province_match(s): arr = ['内蒙古', '黑龙江', '河北', '山西', '吉林', '辽宁', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州', '云南', '陕西', '甘肃', '青海', '广西', '西藏', '宁夏', '新疆', '北京', '天津', '上海', '重庆'] for i in arr: if i in s: return i return '' def de_duplicate(regions): regions = filter(bool, regions) ret = [] [ret.append(i) for i in regions if i not in ret] return ret def get_addr(ip, mask): network = ipaddress.ip_network(f"{ip}/{mask}", strict=False) first_ip = network.network_address return f"{first_ip}/{mask}" def get_maxmind(ip: str): ret = {"ip": ip} asn_info = asn_reader.get(ip) if asn_info: as_ = {"number": asn_info["autonomous_system_number"], "name": asn_info["autonomous_system_organization"]} info = get_as_info(as_["number"]) if info: as_["info"] = info ret["as"] = as_ city_info, prefix = city_reader.get_with_prefix_len(ip) ret["addr"] = get_addr(ip, prefix) if not city_info: return ret if "location" in city_info: location = city_info["location"] ret["location"] = { "latitude": location.get("latitude"), "longitude": location.get("longitude") } if "country" in city_info: country_code = city_info["country"]["iso_code"] country_name = get_country(city_info["country"]) ret["country"] = {"code": country_code, "name": country_name} if "registered_country" in city_info: registered_country_code = city_info["registered_country"]["iso_code"] ret["registered_country"] = {"code": registered_country_code, "name": get_country(city_info["registered_country"])} regions = [get_des(i) for i in city_info.get('subdivisions', [])] if "city" in city_info: c = get_des(city_info["city"]) if (not regions or c not in regions[-1]) and c not in country_name: regions.append(c) regions = de_duplicate(regions) if regions: ret["regions"] = regions return ret def get_cn(ip: str, info={}): ret, prefix = cn_reader.get_with_prefix_len(ip) if not ret: return info["addr"] = get_addr(ip, prefix) regions = de_duplicate([ret["province"], ret["city"], ret["districts"]]) if regions: info["regions"] = regions info["regions_short"] = de_duplicate([province_match(ret["province"]), ret["city"].replace('市', ''), ret["districts"]]) if "as" not in info: info["as"] = {} info["as"]["info"] = ret['isp'] if ret['net']: info["type"] = ret['net'] return ret def get_ip_info(ip): info = get_maxmind(ip) if "country" in info and info["country"]["code"] == "CN" and ("registered_country" not in info or info["registered_country"]["code"] == "CN"): get_cn(ip, info) return info def query(): while True: try: ip = input('IP: \t').strip() info = get_ip_info(ip) print(f"网段:\t{info['addr']}") if "location" in info: print(f"经纬度:\t{info['location']['latitude']}, {info['location']['longitude']}") if "as" in info: print(f"ISP:\t", end=' ') if "info" in info["as"]: print(info["as"]["info"], end=' ') else: print(info["as"]["name"], end=' ') if "type" in info: print(f"({info['type']})", end=' ') print(f"ASN{info['as']['number']}", end=' ') print(info['as']["name"]) if "registered_country" in info and ("country" not in info or info["country"]["code"] != info["registered_country"]["code"]): print(f"注册地:\t{info['registered_country']['name']}") if "country" in info: print(f"使用地:\t{info['country']['name']}") if "regions" in info: print(f"位置: \t{' '.join(info['regions'])}") except Exception as e: print(e) raise e finally: print("\n") app = FastAPI() @app.get("/") async def api(request: Request, ip: str = None): client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host query_ip = ip.strip() if ip else client_ip result = get_ip_info(query_ip) log_data = { "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "访问IP": client_ip, "查询IP": query_ip, "请求头": dict(request.headers), "查询结果": result } logger.info(json.dumps(log_data, ensure_ascii=False)) return result @app.get("/{ip}") async def path_api(request: Request, ip: str): client_ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host result = get_ip_info(ip) log_data = { "时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "访问IP": client_ip, "查询IP": ip, "请求头": dict(request.headers), "查询结果": result } logger.info(json.dumps(log_data, ensure_ascii=False)) return result if __name__ == '__main__': query() import uvicorn uvicorn.run(app, host="0.0.0.0", port=8080, server_header=False, proxy_headers=True)