Skip to content

数据库校外访问登不上?用 IP 归属地三步排查(附 Python 脚本) ​

研究生放假回家想下篇论文,打开知网提示「IP 不在授权范围」,给图书馆老师发消息,对方回一句:你现在用的出口 IP 是家里宽带的,当然进不去。中国知网、Web of Science、Elsevier 这类数据库的授权逻辑大多是「按 IP 段」——只对校园网出口的 IP 段开放,不认账号。所以校外访问失败,八成是「你根本没从授权通道出去」。这篇讲怎么用 IP 归属地三步排查,附一个能直接跑的 Python 脚本。

一、数据库到底按什么授权 ​

大部分学术数据库的授权是机构订阅 + IP 段白名单:学校把校园网出口 IP 段报给数据库商,商家的服务器只放行这些段。你在校园内,出口是这个段,正常访问;你在家里连宽带,出口是电信/联通的某个城市节点,不在名单里,直接被拒——哪怕你登录了学校的账号也没用,因为老库的授权链路里根本没有「账号」这环。

所以校外访问有几种标准姿势:

  • VPN 拨入校园网:连上后你的流量从学校出口出去,IP 段变回校园网段;
  • 学校代理(Web 代理/SS):原理同上,流量走学校出口;
  • CARSI / 统一身份认证:新协议,走 Shibboleth,不在本文讨论的 IP 排查范围内,但它是趋势,能用的学校优先用。

排查时先想清楚自己走了哪条路——很多人是「没拨 VPN 直接开浏览器访问」,那一切排查都是多余的。

二、三步排查法 ​

第一步:查当前出口 IP 的归属地。 在浏览器访问 https://ip9.com.cn/get(不传 ip 参数就是查你自己),记下返回的国家、省市、运营商。看到 isp 是电信、联通、移动,说明你走的是家用宽带出口,不是学校网络;看到 prov 和你学校的省份对不上,也一样。

第二步:判断有没有走对通道。 拨上学校 VPN 后再查一次同样的接口,出口 IP 应该变成学校所在城市的运营商或学校自有出口,归属地和 isp 会明显变化。两次结果一样,说明 VPN 根本没生效(连接了但没路由全局,或代理分流规则把它漏了)。

第三步:拿信息报障。 如果通道没问题还是进不去,把「出口 IP + 归属地 + 运营商 + 访问的数据库名 + 报错截图」一起发给图书馆或信息化部门。管理员拿着这组信息,能最快判断是授权段没加、IPv6 漏配,还是数据库商侧的问题——比来回折腾强得多。

三、Python 排查脚本 ​

下面是完整可运行的脚本:调 IP9 免费接口查当前出口 IP 归属地,再帮你比对「学校授权段」和现在的出口 IP 是否匹配。学校授权段是一个 CIDR 列表,填你自己的校园网段或用脚本自带的示例。

python
#!/usr/bin/env python3
"""校外访问数据库排查小工具:查出口 IP 归属地 + 比对授权段"""
import ipaddress
import json
import urllib.request

GEO_API = "https://ip9.com.cn/get"          # 不传 ip = 查当前出口 IP

# 学校数据库授权段(CIDR 列表),示例数据,替换成你们学校的
SCHOOL_NETS = [
    "202.114.0.0/16",   # 示例:某高校教育网段
    "10.20.0.0/16",     # 示例:校园内网段
]

def current_ip_geo():
    """查当前出口 IP 的归属地(无需注册,60 次/分钟够用)"""
    req = urllib.request.Request(GEO_API, headers={"User-Agent": "lib-access-check/1.0"})
    with urllib.request.urlopen(req, timeout=5) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    if data.get("ret") != 200:
        raise RuntimeError(f"接口返回异常: ret={data.get('ret')}")
    return data["data"]

def in_school_nets(ip_str, nets):
    ip = ipaddress.ip_address(ip_str)
    for net_str in nets:
        if ip in ipaddress.ip_network(net_str, strict=False):
            return net_str
    return None

def main():
    d = current_ip_geo()
    ip = d["ip"]
    print(f"当前出口 IP : {ip}")
    print(f"归属地      : {d['country']} {d.get('prov','')} {d.get('city','')}")
    print(f"运营商      : {d.get('isp','')}")

    if ":" in ip:
        print("提示:当前是 IPv6 出口,学校可能只给 IPv4 段授权,可试着断开 IPv6 再访问。")
        return

    hit = in_school_nets(ip, SCHOOL_NETS)
    if hit:
        print(f"✅ 出口 IP 在授权段 {hit} 内,进不去的话问题在别处(账号/数据库商侧)。")
    else:
        print("❌ 出口 IP 不在学校授权段内。原因大概率是:没走 VPN/代理通道,或走了但没生效。")
        print("   处理:拨入校园 VPN 后重跑本脚本,直到出口 IP 归属地变成学校所在地/学校自有出口。")

if __name__ == "__main__":
    main()

运行:python3 check_db_access.py。第一次跑大概率输出 ❌,拨上 VPN 再跑一次变 ✅,整个过程两分钟,比报障等回复快。

四、排查时容易忽略的几个点 ​

  • 手机热点格外坑:热点出口是手机运营商的中转节点,归属地经常是省会城市,看着「像学校城市」其实不是校园网段,拿 CIDR 比对最靠谱,别靠地名猜。
  • IPv6 双栈漏配:很多学校只给数据库商报了 IPv4 段,浏览器优先走 IPv6 时照样被拒。排查时先确认自己走的是 v4 还是 v6 出口(上面脚本已经帮你判断)。
  • 运营商 NAT 出口共享:家庭宽带是大 NAT,一个出口 IP 可能同时被几百户用,这本身不奇怪;「IP 归属地对不上」才说明通道有问题。
  • 报障信息要一次给全:出口 IP、归属地、数据库名、报错页面,四项齐了管理员才能直接定位,别发一句「数据库进不去」就等回复。

总结 ​

校外访问数据库失败,九成是通道问题:出口 IP 不在授权段。用 IP9 免费接口 https://ip9.com.cn/get(不传参查当前出口 IP),配合上面的 Python 脚本,先确认归属地、再比对授权段、最后拿完整信息报障。多数情况下不用麻烦管理员,拨好 VPN 自己就解决了。官网:https://www.ip9.com.cn 。