Skip to content

Linux 怎么查 IP 归属地?一条命令加一个函数,日志排查看 IP 全靠它

敲一句 curl 就能在终端查 IP 归属地,不用开浏览器。但只停在"能查"不够——封装成 shell 函数,日志里揪出的 IP 挨个过、封禁前先看对方在哪个地区,几秒搞定。Ubuntu/Debian/CentOS 通用。

一、Linux 上什么时候要查 IP 归属地

说三个最常碰到的场景:

  1. SSH 爆破溯源/var/log/auth.log 里全是 Failed password,来源 IP 一大串。逐个查归属地,发现都来自同一家海外机房——直接防火墙封段。
  2. Nginx 访问日志异常。某个 IP 疯狂刷接口,查归属地是住宅宽带还是机房再决定封不封:机房 IP 直接封误伤率低,住宅 IP 可能是真人,先观察。
  3. 多台服务器溯源。某台机器被攻击,登录先确认攻击来源是不是同事的出口 IP(分公司专线之类),查归属地 + 运营商比翻工单快。

人在终端里,不想为查个 IP 开网页、复制粘贴。命令行直接出结果,才能跟 grep、awk 串成流水线。

二、方案设计:免费接口 + curl + 一个解析函数

查询走 IP9 免费接口 https://ip9.com.cn/get?ip=<ip>,免注册、免 key,返回 JSON 含国家、省份、城市、运营商等字段,限速 60 次/分钟/IP,排查够用。

curl 直接返回 JSON,但一长串 {"country":"中国","prov":"广东"...} 在终端里不好读,所以拆两层:查询层用 curl 拿 JSON,展示层用 python3 解析排版(系统自带 python3,比 jq 稳)。两层包进 shell 函数 ipinfo,写进 ~/.bashrc 就能天天用。单条命令解决"查一次",函数解决"天天查"

三、Shell 实现:一条命令 + 一个函数

先看裸命令:

bash
curl -s "https://ip9.com.cn/get?ip=114.114.114.114"

JSON 里的 data 就是归属地结果。把它封装成函数,追加到 ~/.bashrc 末尾:

bash
# ipinfo —— 查 IP 归属地;ipinfo [ip],不传 ip 查本机出口
ipinfo() {
    local ip="${1:-}"
    local url="https://ip9.com.cn/get"
    [ -n "$ip" ] && url="$url?ip=$ip"

    local json
    json=$(curl -s --max-time 5 "$url") || { echo "请求失败:网络不通或超时"; return 1; }

    # python3 只负责解析排版
    echo "$json" | python3 -c '
import sys, json
try:
    j = json.load(sys.stdin)
except Exception:
    print("返回的不是合法 JSON,可能被限流"); sys.exit(1)
if j.get("ret") != 200:
    ret = j.get("ret")
    print("查询失败 ret=" + str(ret) + "(400 格式非法,429 超限速)"); sys.exit(1)
d = j["data"]
loc = (d.get("country","") + " " + d.get("prov","") + " " + d.get("city","")).strip()
print("IP:     " + d.get("ip",""))
print("归属地: " + loc)
print("运营商: " + d.get("isp",""))
print("经纬度: " + str(d.get("lat")) + ", " + str(d.get("lng")) + "  (城市中心点)")
'
}

# iplog —— 从日志文件批量查 IP,自动去重 + 限速
iplog() {
    local file="$1"
    [ -z "$file" ] && { echo "用法: iplog /var/log/auth.log"; return 1; }
    grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' "$file" \
        | sort | uniq -c | sort -rn | head -20 \
        | while read -r cnt ip; do
            printf "次数%-5s " "$cnt"
            ipinfo "$ip" | sed -n '1,3p' | tr '\n' ' '
            echo
            sleep 1    # 免费版 60 次/分钟,必须限速
        done
}

source ~/.bashrc 后就能用:

bash
ipinfo                      # 查本机出口 IP 归属地
ipinfo 8.8.8.8              # 查指定 IP
iplog /var/log/auth.log     # SSH 日志里最活跃的 20 个 IP 及其归属地

输出:

text
次数   12  IP: 103.xxx.xxx.xxx  归属地: 中国 香港  运营商: 某某数据中心

全是机房段,直接 iptables 封段或丢给 fail2ban。想确认是不是机房 IP,IP9 的 VIP 版多返回 ip_type(ISP 家庭/BUS 企业/IDC 机房)和 ip_asn;免费版先用省市 + 运营商判断也够。

四、落地注意事项

实操中容易踩的坑:

  • 限速别踩:免费版 60 次/分钟/IP,iplog 已加 sleep 1;自己写循环批量查几百个 IP,间隔至少 1 秒,否则撞 ret=429
  • 分清内外网ip addr 看到的是内网地址,直接查会得到"保留地址"之类的无效结果;函数不传参时返回的才是真实出口。
  • 超时兜底:curl 带 --max-time 5,接口抽风不会挂死终端;函数对非 200、非 JSON 都有提示。
  • 经纬度是城市中心:接口返回的经纬度是城市中心点坐标,大致标注可以,别当精确位置用。
  • 别在生产脚本里裸奔:这是排查工具。上生产风控要把查询服务化、加缓存,别让业务请求直连第三方接口。

总结

把"查 IP 归属地"从"打开网页复制粘贴"变成终端里的一条命令、一个函数,日志溯源和封禁决策会顺手很多。核心就两步:curl 请求 https://ip9.com.cn/get?ip=<ip>,python3 把 JSON 排成好读的几行。函数放进 ~/.bashrc,SSH 爆破、爬虫乱爬、异常流量,来一个查一个。免费版够日常排查,要机房类型和 ASN 判断就看官网 https://www.ip9.com.cn 的 VIP 说明。