Update main.py
Browse files
main.py
CHANGED
@@ -1,106 +1,125 @@
|
|
1 |
import ipaddress
|
2 |
import maxminddb
|
3 |
from fastapi import FastAPI, Request
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
city_reader = maxminddb.open_database('GeoLite2-City.mmdb')
|
6 |
asn_reader = maxminddb.open_database('GeoLite2-ASN.mmdb')
|
7 |
cn_reader = maxminddb.open_database('GeoCN.mmdb')
|
8 |
-
lang = ["zh-CN","en"]
|
9 |
asn_map = {
|
10 |
-
9812:"东方有线",
|
11 |
-
9389:"中国长城",
|
12 |
-
17962:"天威视讯",
|
13 |
-
17429:"歌华有线",
|
14 |
-
7497:"科技网",
|
15 |
-
24139:"华数",
|
16 |
-
9801:"中关村",
|
17 |
-
4538:"教育网",
|
18 |
-
24151:"CNNIC",
|
19 |
-
|
20 |
-
38019:"中国移动",139080:"中国移动",9808:"中国移动",24400:"中国移动",134810:"中国移动",24547:"中国移动",
|
21 |
-
56040:"中国移动",56041:"中国移动",56042:"中国移动",56044:"中国移动",132525:"中国移动",56046:"中国移动",
|
22 |
-
56047:"中国移动",56048:"中国移动",59257:"中国移动",24444:"中国移动",
|
23 |
-
24445:"中国移动",137872:"中国移动",9231:"中国移动",58453:"中国移动",
|
24 |
-
|
25 |
-
4134:"中国电信",4812:"中国电信",23724:"中国电信",136188:"中国电信",137693:"中国电信",17638:"中国电信",
|
26 |
-
140553:"中国电信",4847:"中国电信",140061:"中国电信",136195:"中国电信",17799:"中国电信",139018:"中国电信",
|
27 |
-
133776:"中国电信",58772:"中国电信",146966:"中国电信",63527:"中国电信",58539:"中国电信",58540:"中国电信",
|
28 |
-
141998:"
|
29 |
-
137694:"中国电信",137698:"中国电信",136167:"中国电信",148969:"中国电信",134764:"中国电信",
|
30 |
-
134770:"中国电信",148981:"中国电信",134774:"中国电信",136190:"中国电信",140647:"中国电信",
|
31 |
-
132225:"中国电信",140485:"中国电信",4811:"中国电信",131285:"中国电信",137689:"中国电信",
|
32 |
-
137692:"中国电信",140636:"中国电信",140638:"中国电信",140345:"中国电信",38283:"中国电信",
|
33 |
-
140292:"中国电信",140903:"中国电信",17897:"中国电信",134762:"中国电信",139019:"中国电信",
|
34 |
-
141739:"中国电信",141771:"中国电信",134419:"中国电信",140276:"中国电信",58542:"中国电信",
|
35 |
-
140278:"中国电信",139767:"中国电信",137688:"中国电信",137691:"中国电信",4809:"中国电信",
|
36 |
-
58466:"中国电信",137687:"中国电信",134756:"中国电信",134760:"中国电信",
|
37 |
-
133774:"中国电信",133775:"中国电信",4816:"中国电信",134768:"中国电信",
|
38 |
-
58461:"中国电信",58519:"中国电信",58520:"中国电信",131325:"中国电信",
|
39 |
-
|
40 |
-
4837:"中国联通",4808:"中国联通",134542:"中国联通",134543:"中国联通",10099:"中国联通",
|
41 |
-
140979:"中国联通",138421:"中国联通",17621:"中国联通",17622:"中国联通",17816:"中国联通",
|
42 |
-
140726:"中国联通",17623:"中国联通",136958:"中国联通",9929:"中国联通",58519:"中国联通",
|
43 |
-
140716:"中国联通",4847:"中国联通",136959:"中国联通",135061:"中国联通",139007:"中国联通",
|
44 |
-
|
45 |
-
59019:"金山云",
|
46 |
-
135377:"优刻云",
|
47 |
-
45062:"网易云",
|
48 |
-
137718:"火山引擎",
|
49 |
-
37963:"阿里云",45102:"阿里云国际",
|
50 |
-
45090:"腾讯云",132203:"腾讯云国际",
|
51 |
-
55967:"百度云",38365:"百度云",
|
52 |
-
58519:"华为云",
|
53 |
-
4609:"澳門電訊",
|
54 |
-
134773:"珠江宽频",
|
55 |
-
1659:"台湾教育网",
|
56 |
-
8075:"微软云",
|
57 |
-
17421:"中华电信",
|
58 |
-
3462:"HiNet",
|
59 |
-
13335:"Cloudflare",
|
60 |
-
55960:"亚马逊云",14618:"亚马逊云",16509:"亚马逊云",
|
61 |
-
15169:"谷歌云",396982:"谷歌云",36492:"谷歌云",
|
62 |
}
|
63 |
|
|
|
64 |
def get_as_info(number):
|
65 |
r = asn_map.get(number)
|
66 |
if r:
|
67 |
return r
|
68 |
-
|
|
|
69 |
def get_des(d):
|
70 |
for i in lang:
|
71 |
if i in d['names']:
|
72 |
return d['names'][i]
|
73 |
return d['names']['en']
|
74 |
|
|
|
75 |
def get_country(d):
|
76 |
r = get_des(d)
|
77 |
if r in ["香港", "澳门", "台湾"]:
|
78 |
return "中国" + r
|
79 |
return r
|
80 |
|
|
|
81 |
def province_match(s):
|
82 |
-
arr=['内蒙古','黑龙江','河北','山西','吉林','辽宁','江苏','浙江','安徽','福建','江西','山东','河南','湖北','湖南','广东','海南','四川','贵州','云南','陕西','甘肃','青海','广西','西藏','宁夏','新疆','北京','天津','上海','重庆']
|
83 |
for i in arr:
|
84 |
if i in s:
|
85 |
return i
|
86 |
return ''
|
87 |
|
|
|
88 |
def de_duplicate(regions):
|
89 |
-
regions = filter(bool,regions)
|
90 |
ret = []
|
91 |
[ret.append(i) for i in regions if i not in ret]
|
92 |
return ret
|
93 |
|
|
|
94 |
def get_addr(ip, mask):
|
95 |
network = ipaddress.ip_network(f"{ip}/{mask}", strict=False)
|
96 |
first_ip = network.network_address
|
97 |
return f"{first_ip}/{mask}"
|
98 |
|
|
|
99 |
def get_maxmind(ip: str):
|
100 |
-
ret = {"ip":ip}
|
101 |
asn_info = asn_reader.get(ip)
|
102 |
if asn_info:
|
103 |
-
as_ = {"number":asn_info["autonomous_system_number"],"name":asn_info["autonomous_system_organization"]}
|
104 |
info = get_as_info(as_["number"])
|
105 |
if info:
|
106 |
as_["info"] = info
|
@@ -113,35 +132,35 @@ def get_maxmind(ip: str):
|
|
113 |
if "country" in city_info:
|
114 |
country_code = city_info["country"]["iso_code"]
|
115 |
country_name = get_country(city_info["country"])
|
116 |
-
ret["country"] = {"code":country_code,"name":country_name}
|
117 |
-
|
118 |
if "registered_country" in city_info:
|
119 |
registered_country_code = city_info["registered_country"]["iso_code"]
|
120 |
-
ret["registered_country"] = {"code":registered_country_code,"name":get_country(city_info["registered_country"])}
|
121 |
-
|
122 |
regions = [get_des(i) for i in city_info.get('subdivisions', [])]
|
123 |
|
124 |
-
|
125 |
if "city" in city_info:
|
126 |
c = get_des(city_info["city"])
|
127 |
-
if (not regions or c not in regions[-1])and c not in country_name:
|
128 |
regions.append(c)
|
129 |
-
|
130 |
regions = de_duplicate(regions)
|
131 |
if regions:
|
132 |
ret["regions"] = regions
|
133 |
-
|
134 |
return ret
|
135 |
|
136 |
-
|
|
|
137 |
ret, prefix = cn_reader.get_with_prefix_len(ip)
|
138 |
if not ret:
|
139 |
return
|
140 |
info["addr"] = get_addr(ip, prefix)
|
141 |
-
regions = de_duplicate([ret["province"],ret["city"],ret["districts"]])
|
142 |
if regions:
|
143 |
info["regions"] = regions
|
144 |
-
info["regions_short"] = de_duplicate([province_match(ret["province"]),ret["city"].replace('市',''),ret["districts"]])
|
145 |
if "as" not in info:
|
146 |
info["as"] = {}
|
147 |
info["as"]["info"] = ret['isp']
|
@@ -149,59 +168,75 @@ def get_cn(ip:str, info={}):
|
|
149 |
info["type"] = ret['net']
|
150 |
return ret
|
151 |
|
|
|
152 |
def get_ip_info(ip):
|
153 |
info = get_maxmind(ip)
|
154 |
if "country" in info and info["country"]["code"] == "CN" and ("registered_country" not in info or info["registered_country"]["code"] == "CN"):
|
155 |
-
get_cn(ip,info)
|
156 |
return info
|
157 |
|
|
|
158 |
def query():
|
159 |
while True:
|
160 |
try:
|
161 |
ip = input('IP: \t').strip()
|
162 |
info = get_ip_info(ip)
|
163 |
-
|
|
|
|
|
|
|
164 |
print(f"网段:\t{info['addr']}")
|
165 |
-
|
166 |
if "as" in info:
|
167 |
-
print(f"ISP:\t",end=' ')
|
168 |
if "info" in info["as"]:
|
169 |
-
print(info["as"]["info"],end=' ')
|
170 |
else:
|
171 |
-
print(info["as"]["name"],end=' ')
|
172 |
if "type" in info:
|
173 |
-
print(f"({info['type']})",end=' ')
|
174 |
-
print(f"ASN{info['as']['number']}",end=' ')
|
175 |
print(info['as']["name"])
|
176 |
-
|
177 |
if "registered_country" in info and ("country" not in info or info["country"]["code"] != info["registered_country"]["code"]):
|
178 |
print(f"注册地:\t{info['registered_country']['name']}")
|
179 |
-
|
180 |
if "country" in info:
|
181 |
print(f"使用地:\t{info['country']['name']}")
|
182 |
-
|
183 |
if "regions" in info:
|
184 |
print(f"位置: \t{' '.join(info['regions'])}")
|
185 |
-
|
186 |
except Exception as e:
|
187 |
print(e)
|
188 |
raise e
|
189 |
finally:
|
190 |
print("\n")
|
191 |
-
|
|
|
192 |
app = FastAPI()
|
193 |
|
|
|
194 |
@app.get("/")
|
195 |
def api(request: Request, ip: str = None):
|
196 |
if not ip:
|
197 |
ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
|
|
|
|
|
|
|
|
|
198 |
return get_ip_info(ip.strip())
|
199 |
|
|
|
200 |
@app.get("/{ip}")
|
201 |
def path_api(ip):
|
|
|
|
|
|
|
202 |
return get_ip_info(ip)
|
203 |
|
|
|
204 |
if __name__ == '__main__':
|
205 |
query()
|
206 |
import uvicorn
|
207 |
-
uvicorn.run(app, host="0.0.0.0", port=8080, server_header=False, proxy_headers=True)
|
|
|
1 |
import ipaddress
|
2 |
import maxminddb
|
3 |
from fastapi import FastAPI, Request
|
4 |
+
import logging
|
5 |
+
from datetime import datetime
|
6 |
+
|
7 |
+
#配置日志记录
|
8 |
+
logging.basicConfig(
|
9 |
+
level=logging.INFO,
|
10 |
+
format='%(asctime)s - %(levelname)s - %(message)s',
|
11 |
+
handlers=[
|
12 |
+
logging.FileHandler('access.log'), #日志文件
|
13 |
+
logging.StreamHandler() #控制台输出
|
14 |
+
]
|
15 |
+
)
|
16 |
|
17 |
city_reader = maxminddb.open_database('GeoLite2-City.mmdb')
|
18 |
asn_reader = maxminddb.open_database('GeoLite2-ASN.mmdb')
|
19 |
cn_reader = maxminddb.open_database('GeoCN.mmdb')
|
20 |
+
lang = ["zh-CN", "en"]
|
21 |
asn_map = {
|
22 |
+
9812: "东方有线",
|
23 |
+
9389: "中国长城",
|
24 |
+
17962: "天威视讯",
|
25 |
+
17429: "歌华有线",
|
26 |
+
7497: "科技网",
|
27 |
+
24139: "华数",
|
28 |
+
9801: "中关村",
|
29 |
+
4538: "教育网",
|
30 |
+
24151: "CNNIC",
|
31 |
+
|
32 |
+
38019: "中国移动",139080: "中国移动",9808: "中国移动",24400: "中国移动",134810: "中国移动",24547: "中国移动",
|
33 |
+
56040: "中国移动",56041: "中国移动",56042: "中国移动",56044: "中国移动",132525: "中国移动",56046: "中国移动",
|
34 |
+
56047: "中国移动",56048: "中国移动",59257: "中国移动",24444: "中国移动",
|
35 |
+
24445: "中国移动",137872: "中国移动",9231: "中国移动",58453: "中国移动",
|
36 |
+
|
37 |
+
4134: "中国电信",4812: "中国电信",23724: "中国电信",136188: "中国电信",137693: "中国电信",17638: "中国电信",
|
38 |
+
140553: "中国电信",4847: "中国电信",140061: "中国电信",136195: "中国电信",17799: "中国电信",139018: "中国电信",
|
39 |
+
133776: "中国电信",58772: "中国电信",146966: "中国电信",63527: "中国电信",58539: "中国电信",58540: "中国电信",
|
40 |
+
141998: "��国电信",138169: "中国电信",139203: "中国电信",58563: "中国电信",137690: "中国电信",63838: "中国电信",
|
41 |
+
137694: "中国电信",137698: "中国电信",136167: "中国电信",148969: "中国电信",134764: "中国电信",
|
42 |
+
134770: "中国电信",148981: "中国电信",134774: "中国电信",136190: "中国电信",140647: "中国电信",
|
43 |
+
132225: "中国电信",140485: "中国电信",4811: "中国电信",131285: "中国电信",137689: "中国电信",
|
44 |
+
137692: "中国电信",140636: "中国电信",140638: "中国电信",140345: "中国电信",38283: "中国电信",
|
45 |
+
140292: "中国电信",140903: "中国电信",17897: "中国电信",134762: "中国电信",139019: "中国电信",
|
46 |
+
141739: "中国电信",141771: "中国电信",134419: "中国电信",140276: "中国电信",58542: "中国电信",
|
47 |
+
140278: "中国电信",139767: "中国电信",137688: "中国电信",137691: "中国电信",4809: "中国电信",
|
48 |
+
58466: "中国电信",137687: "中国电信",134756: "中国电信",134760: "中国电信",
|
49 |
+
133774: "中国电信",133775: "中国电信",4816: "中国电信",134768: "中国电信",
|
50 |
+
58461: "中国电信",58519: "中国电信",58520: "中国电信",131325: "中国电信",
|
51 |
+
|
52 |
+
4837: "中国联通",4808: "中国联通",134542: "中国联通",134543: "中国联通",10099: "中国联通",
|
53 |
+
140979: "中国联通",138421: "中国联通",17621: "中国联通",17622: "中国联通",17816: "中国联通",
|
54 |
+
140726: "中国联通",17623: "中国联通",136958: "中国联通",9929: "中国联通",58519: "中国联通",
|
55 |
+
140716: "中国联通",4847: "中国联通",136959: "中国联通",135061: "中国联通",139007: "中国联通",
|
56 |
+
|
57 |
+
59019: "金山云",
|
58 |
+
135377: "优刻云",
|
59 |
+
45062: "网易云",
|
60 |
+
137718: "火山引擎",
|
61 |
+
37963: "阿里云",45102: "阿里云国际",
|
62 |
+
45090: "腾讯云",132203: "腾讯云国际",
|
63 |
+
55967: "百度云",38365: "百度云",
|
64 |
+
58519: "华为云",55990: "华为云",136907: "华为云",
|
65 |
+
4609: "澳門電訊",
|
66 |
+
134773: "珠江宽频",
|
67 |
+
1659: "台湾教育网",
|
68 |
+
8075: "微软云",
|
69 |
+
17421: "中华电信",
|
70 |
+
3462: "HiNet",
|
71 |
+
13335: "Cloudflare",
|
72 |
+
55960: "亚马逊云",14618: "亚马逊云",16509: "亚马逊云",
|
73 |
+
15169: "谷歌云",396982: "谷歌云",36492: "谷歌云",
|
74 |
}
|
75 |
|
76 |
+
|
77 |
def get_as_info(number):
|
78 |
r = asn_map.get(number)
|
79 |
if r:
|
80 |
return r
|
81 |
+
|
82 |
+
|
83 |
def get_des(d):
|
84 |
for i in lang:
|
85 |
if i in d['names']:
|
86 |
return d['names'][i]
|
87 |
return d['names']['en']
|
88 |
|
89 |
+
|
90 |
def get_country(d):
|
91 |
r = get_des(d)
|
92 |
if r in ["香港", "澳门", "台湾"]:
|
93 |
return "中国" + r
|
94 |
return r
|
95 |
|
96 |
+
|
97 |
def province_match(s):
|
98 |
+
arr = ['内蒙古', '黑龙江', '河北', '山西', '吉林', '辽宁', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南', '四川', '贵州', '云南', '陕西', '甘肃', '青海', '广西', '西藏', '宁夏', '新疆', '北京', '天津', '上海', '重庆']
|
99 |
for i in arr:
|
100 |
if i in s:
|
101 |
return i
|
102 |
return ''
|
103 |
|
104 |
+
|
105 |
def de_duplicate(regions):
|
106 |
+
regions = filter(bool, regions)
|
107 |
ret = []
|
108 |
[ret.append(i) for i in regions if i not in ret]
|
109 |
return ret
|
110 |
|
111 |
+
|
112 |
def get_addr(ip, mask):
|
113 |
network = ipaddress.ip_network(f"{ip}/{mask}", strict=False)
|
114 |
first_ip = network.network_address
|
115 |
return f"{first_ip}/{mask}"
|
116 |
|
117 |
+
|
118 |
def get_maxmind(ip: str):
|
119 |
+
ret = {"ip": ip}
|
120 |
asn_info = asn_reader.get(ip)
|
121 |
if asn_info:
|
122 |
+
as_ = {"number": asn_info["autonomous_system_number"], "name": asn_info["autonomous_system_organization"]}
|
123 |
info = get_as_info(as_["number"])
|
124 |
if info:
|
125 |
as_["info"] = info
|
|
|
132 |
if "country" in city_info:
|
133 |
country_code = city_info["country"]["iso_code"]
|
134 |
country_name = get_country(city_info["country"])
|
135 |
+
ret["country"] = {"code": country_code, "name": country_name}
|
136 |
+
|
137 |
if "registered_country" in city_info:
|
138 |
registered_country_code = city_info["registered_country"]["iso_code"]
|
139 |
+
ret["registered_country"] = {"code": registered_country_code, "name": get_country(city_info["registered_country"])}
|
140 |
+
|
141 |
regions = [get_des(i) for i in city_info.get('subdivisions', [])]
|
142 |
|
|
|
143 |
if "city" in city_info:
|
144 |
c = get_des(city_info["city"])
|
145 |
+
if (not regions or c not in regions[-1]) and c not in country_name:
|
146 |
regions.append(c)
|
147 |
+
|
148 |
regions = de_duplicate(regions)
|
149 |
if regions:
|
150 |
ret["regions"] = regions
|
151 |
+
|
152 |
return ret
|
153 |
|
154 |
+
|
155 |
+
def get_cn(ip: str, info={}):
|
156 |
ret, prefix = cn_reader.get_with_prefix_len(ip)
|
157 |
if not ret:
|
158 |
return
|
159 |
info["addr"] = get_addr(ip, prefix)
|
160 |
+
regions = de_duplicate([ret["province"], ret["city"], ret["districts"]])
|
161 |
if regions:
|
162 |
info["regions"] = regions
|
163 |
+
info["regions_short"] = de_duplicate([province_match(ret["province"]), ret["city"].replace('市', ''), ret["districts"]])
|
164 |
if "as" not in info:
|
165 |
info["as"] = {}
|
166 |
info["as"]["info"] = ret['isp']
|
|
|
168 |
info["type"] = ret['net']
|
169 |
return ret
|
170 |
|
171 |
+
|
172 |
def get_ip_info(ip):
|
173 |
info = get_maxmind(ip)
|
174 |
if "country" in info and info["country"]["code"] == "CN" and ("registered_country" not in info or info["registered_country"]["code"] == "CN"):
|
175 |
+
get_cn(ip, info)
|
176 |
return info
|
177 |
|
178 |
+
|
179 |
def query():
|
180 |
while True:
|
181 |
try:
|
182 |
ip = input('IP: \t').strip()
|
183 |
info = get_ip_info(ip)
|
184 |
+
|
185 |
+
#记录访问日志
|
186 |
+
logging.info(f"IP: {ip}, Method: CLI, Path: /query")
|
187 |
+
|
188 |
print(f"网段:\t{info['addr']}")
|
189 |
+
|
190 |
if "as" in info:
|
191 |
+
print(f"ISP:\t", end=' ')
|
192 |
if "info" in info["as"]:
|
193 |
+
print(info["as"]["info"], end=' ')
|
194 |
else:
|
195 |
+
print(info["as"]["name"], end=' ')
|
196 |
if "type" in info:
|
197 |
+
print(f"({info['type']})", end=' ')
|
198 |
+
print(f"ASN{info['as']['number']}", end=' ')
|
199 |
print(info['as']["name"])
|
200 |
+
|
201 |
if "registered_country" in info and ("country" not in info or info["country"]["code"] != info["registered_country"]["code"]):
|
202 |
print(f"注册地:\t{info['registered_country']['name']}")
|
203 |
+
|
204 |
if "country" in info:
|
205 |
print(f"使用地:\t{info['country']['name']}")
|
206 |
+
|
207 |
if "regions" in info:
|
208 |
print(f"位置: \t{' '.join(info['regions'])}")
|
209 |
+
|
210 |
except Exception as e:
|
211 |
print(e)
|
212 |
raise e
|
213 |
finally:
|
214 |
print("\n")
|
215 |
+
|
216 |
+
|
217 |
app = FastAPI()
|
218 |
|
219 |
+
|
220 |
@app.get("/")
|
221 |
def api(request: Request, ip: str = None):
|
222 |
if not ip:
|
223 |
ip = request.headers.get("x-forwarded-for") or request.headers.get("x-real-ip") or request.client.host
|
224 |
+
|
225 |
+
#记录访问日志
|
226 |
+
logging.info(f"IP: {ip}, Method: {request.method}, Path: {request.url.path}, User-Agent: {request.headers.get('user-agent')}")
|
227 |
+
|
228 |
return get_ip_info(ip.strip())
|
229 |
|
230 |
+
|
231 |
@app.get("/{ip}")
|
232 |
def path_api(ip):
|
233 |
+
#记录访问日志
|
234 |
+
logging.info(f"IP: {ip}, Method: GET, Path: /{ip}")
|
235 |
+
|
236 |
return get_ip_info(ip)
|
237 |
|
238 |
+
|
239 |
if __name__ == '__main__':
|
240 |
query()
|
241 |
import uvicorn
|
242 |
+
uvicorn.run(app, host="0.0.0.0", port=8080, server_header=False, proxy_headers=True)
|