quien-whois-lookup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

quien — Better WHOIS Lookup Tool

quien — 更优秀的WHOIS查询工具

Skill by ara.so — Daily 2026 Skills collection.
quien
is a Go-based CLI/TUI tool that replaces
whois
with tabbed interactive views and JSON-scriptable subcommands for domain WHOIS/RDAP, DNS records, mail configuration (SPF, DMARC, DKIM, BIMI), SSL/TLS, HTTP headers, tech stack detection, and IP/ASN/BGP lookups.

来自ara.so的技能——Daily 2026 Skills合集。
quien
是一款基于Go语言的CLI/TUI工具,它替代了
whois
,提供了带标签页的交互式视图和支持JSON脚本的子命令,可用于域名WHOIS/RDAP查询、DNS记录查询、邮件配置(SPF、DMARC、DKIM、BIMI)检查、SSL/TLS检测、HTTP头信息查看、技术栈识别以及IP/ASN/BGP查询。

Installation

安装

Homebrew (macOS/Linux)
sh
brew tap retlehs/tap
brew install retlehs/tap/quien
Ubuntu / Debian
sh
curl -fsSL https://apt.quien.dev/install.sh | sudo sh
Go
sh
go install github.com/retlehs/quien@latest
Verify installation
sh
quien --version
Optional — replace system whois:
sh
undefined
Homebrew(macOS/Linux)
sh
brew tap retlehs/tap
brew install retlehs/tap/quien
Ubuntu / Debian
sh
curl -fsSL https://apt.quien.dev/install.sh | sudo sh
Go语言安装
sh
go install github.com/retlehs/quien@latest
验证安装
sh
quien --version
可选——替换系统默认whois:
sh
undefined

Add to ~/.bashrc or ~/.zshrc

添加到~/.bashrc或~/.zshrc

alias whois=quien

---
alias whois=quien

---

Core CLI Commands

核心CLI命令

Interactive TUI (default)

交互式TUI(默认模式)

sh
undefined
sh
undefined

Launch interactive prompt

启动交互式提示符

quien
quien

Open TUI directly for a domain

直接为某个域名打开TUI

quien example.com
quien example.com

Open TUI for an IP address

为某个IP地址打开TUI

quien 8.8.8.8
undefined
quien 8.8.8.8
undefined

JSON output (scriptable)

JSON输出(支持脚本化)

sh
undefined
sh
undefined

Full JSON output for all tabs

所有标签页的完整JSON输出

quien --json example.com
quien --json example.com

Individual subcommands (always output JSON)

独立子命令(始终输出JSON)

quien dns example.com quien mail example.com quien tls example.com quien http example.com quien stack example.com quien all example.com # all data in one JSON object

---
quien dns example.com quien mail example.com quien tls example.com quien http example.com quien stack example.com quien all example.com # 所有数据整合为一个JSON对象

---

TUI Tab Overview

TUI标签页概览

TabData shown
WHOISRDAP-first registration data, registrar, dates, nameservers
DNSA, AAAA, MX, TXT, NS, CNAME, SOA records
MailMX, SPF, DMARC, DKIM, BIMI + VMC chain validation
TLSCertificate chain, validity, SANs, cipher info
HTTPResponse headers, redirects, status codes
StackWordPress plugins, JS/CSS frameworks, external services
IPReverse DNS, network info, abuse contacts, ASN via RDAP/BGP

标签页展示的数据
WHOIS优先显示RDAP注册数据、注册商、日期、域名服务器
DNSA、AAAA、MX、TXT、NS、CNAME、SOA记录
邮件MX、SPF、DMARC、DKIM、BIMI + VMC证书链验证
TLS证书链、有效期、SANs、加密套件信息
HTTP响应头、重定向、状态码
技术栈WordPress插件、JS/CSS框架、外部服务
IP反向DNS、网络信息、滥用联系信息、通过RDAP/BGP获取的ASN

JSON Subcommand Examples

JSON子命令示例

DNS records

DNS记录

sh
quien dns github.com
sh
quien dns github.com

Output:

输出:

{

{

"domain": "github.com",

"domain": "github.com",

"a": ["140.82.121.4"],

"a": ["140.82.121.4"],

"aaaa": [],

"aaaa": [],

"mx": [{"host": "aspmx.l.google.com", "priority": 1}],

"mx": [{"host": "aspmx.l.google.com", "priority": 1}],

"ns": ["dns1.p08.nsone.net", "dns2.p08.nsone.net"],

"ns": ["dns1.p08.nsone.net", "dns2.p08.nsone.net"],

"txt": ["v=spf1 ip4:... ~all"],

"txt": ["v=spf1 ip4:... ~all"],

...

...

}

}

undefined
undefined

Mail configuration audit

邮件配置审计

sh
quien mail example.com
sh
quien mail example.com

Returns SPF record, DMARC policy, DKIM selectors found,

返回SPF记录、DMARC策略、检测到的DKIM选择器、

BIMI record, VMC certificate chain validation

BIMI记录、VMC证书链验证结果

undefined
undefined

TLS/SSL inspection

TLS/SSL检测

sh
quien tls example.com
sh
quien tls example.com

Returns certificate subject, issuer, validity dates,

返回证书主体、颁发者、有效期、

SANs, chain depth, protocol version, cipher suite

SANs、证书链深度、协议版本、加密套件

undefined
undefined

HTTP headers

HTTP头信息

sh
quien http example.com
sh
quien http example.com

Returns status code, redirect chain, all response headers

返回状态码、重定向链、所有响应头

(Content-Security-Policy, HSTS, X-Frame-Options, etc.)

(Content-Security-Policy、HSTS、X-Frame-Options等)

undefined
undefined

Tech stack detection

技术栈识别

sh
quien stack example.com
sh
quien stack example.com

Parses HTML for:

解析HTML内容以识别:

- WordPress version + active plugins

- WordPress版本及激活的插件

- JavaScript frameworks (React, Vue, Angular, Next.js, etc.)

- JavaScript框架(React、Vue、Angular、Next.js等)

- CSS frameworks (Tailwind, Bootstrap, etc.)

- CSS框架(Tailwind、Bootstrap等)

- External services (analytics, CDNs, payment providers)

- 外部服务(分析工具、CDN、支付提供商)

undefined
undefined

IP address lookup

IP地址查询

sh
quien 8.8.8.8
quien --json 8.8.8.8
sh
quien 8.8.8.8
quien --json 8.8.8.8

Returns:

返回:

- Reverse DNS (PTR record)

- 反向DNS(PTR记录)

- RDAP network block info

- RDAP网络块信息

- Abuse contact

- 滥用联系信息

- Origin ASN + prefix (RDAP with BGP fallback)

- 源ASN + 前缀(RDAP为主,BGP为备选)

- PeeringDB enrichment: org, peering policy, IX/facility counts,

- PeeringDB增强信息:组织、对等策略、IX/设施数量、

traffic profile, peering locations

流量概况、对等位置

undefined
undefined

All data at once

一次性获取所有数据

sh
quien all example.com | jq '.dns.a'
quien all example.com | jq '.mail.spf'
quien all example.com | jq '.tls.valid_until'

sh
quien all example.com | jq '.dns.a'
quien all example.com | jq '.mail.spf'
quien all example.com | jq '.tls.valid_until'

Scripting Patterns

脚本使用模式

Pipe JSON into jq

将JSON输出传入jq处理

sh
undefined
sh
undefined

Get all A records

获取所有A记录

quien dns example.com | jq '.a[]'
quien dns example.com | jq '.a[]'

Check if DMARC policy is reject

检查DMARC策略是否为reject

quien mail example.com | jq '.dmarc.policy == "reject"'
quien mail example.com | jq '.dmarc.policy == "reject"'

Get certificate expiry

获取证书过期时间

quien tls example.com | jq '.certificates[0].not_after'
quien tls example.com | jq '.certificates[0].not_after'

List detected JS frameworks

列出检测到的JS框架

quien stack example.com | jq '.javascript_frameworks[]'
quien stack example.com | jq '.javascript_frameworks[]'

Get ASN number for an IP

获取IP对应的ASN编号

quien --json 1.1.1.1 | jq '.asn.number'
undefined
quien --json 1.1.1.1 | jq '.asn.number'
undefined

Shell script: bulk domain audit

Shell脚本:批量域名审计

sh
#!/bin/bash
domains=("example.com" "github.com" "golang.org")

for domain in "${domains[@]}"; do
  echo "=== $domain ==="
  
  spf=$(quien mail "$domain" | jq -r '.spf.record // "MISSING"')
  dmarc=$(quien mail "$domain" | jq -r '.dmarc.policy // "MISSING"')
  tls_expiry=$(quien tls "$domain" | jq -r '.certificates[0].not_after // "N/A"')
  
  echo "SPF:   $spf"
  echo "DMARC: $dmarc"
  echo "TLS expires: $tls_expiry"
  echo
done
sh
#!/bin/bash
domains=("example.com" "github.com" "golang.org")

for domain in "${domains[@]}"; do
  echo "=== $domain ==="
  
  spf=$(quien mail "$domain" | jq -r '.spf.record // "MISSING"')
  dmarc=$(quien mail "$domain" | jq -r '.dmarc.policy // "MISSING"')
  tls_expiry=$(quien tls "$domain" | jq -r '.certificates[0].not_after // "N/A"')
  
  echo "SPF:   $spf"
  echo "DMARC: $dmarc"
  echo "TLS过期时间: $tls_expiry"
  echo
done

Shell script: check domain expiry

Shell脚本:检查域名过期时间

sh
#!/bin/bash
DOMAIN="${1:?Usage: $0 <domain>}"

expiry=$(quien --json "$DOMAIN" | jq -r '.whois.expires // .rdap.expires // empty')

if [ -z "$expiry" ]; then
  echo "Could not determine expiry for $DOMAIN"
  exit 1
fi

echo "$DOMAIN expires: $expiry"
sh
#!/bin/bash
DOMAIN="${1:?用法: $0 <域名>}"

expiry=$(quien --json "$DOMAIN" | jq -r '.whois.expires // .rdap.expires // empty')

if [ -z "$expiry" ]; then
  echo "无法确定$DOMAIN的过期时间"
  exit 1
fi

echo "$DOMAIN过期时间: $expiry"

Go integration — run quien as subprocess

Go语言集成——将quien作为子进程运行

go
package main

import (
    "encoding/json"
    "fmt"
    "os/exec"
)

type DNSResult struct {
    Domain string   `json:"domain"`
    A      []string `json:"a"`
    MX     []struct {
        Host     string `json:"host"`
        Priority int    `json:"priority"`
    } `json:"mx"`
    TXT []string `json:"txt"`
}

func lookupDNS(domain string) (*DNSResult, error) {
    out, err := exec.Command("quien", "dns", domain).Output()
    if err != nil {
        return nil, fmt.Errorf("quien dns failed: %w", err)
    }
    var result DNSResult
    if err := json.Unmarshal(out, &result); err != nil {
        return nil, fmt.Errorf("parse error: %w", err)
    }
    return &result, nil
}

func main() {
    dns, err := lookupDNS("example.com")
    if err != nil {
        panic(err)
    }
    fmt.Printf("A records for %s: %v\n", dns.Domain, dns.A)
    for _, mx := range dns.MX {
        fmt.Printf("MX %d: %s\n", mx.Priority, mx.Host)
    }
}
go
package main

import (
    "encoding/json"
    "fmt"
    "os/exec"
)

type DNSResult struct {
    Domain string   `json:"domain"`
    A      []string `json:"a"`
    MX     []struct {
        Host     string `json:"host"`
        Priority int    `json:"priority"`
    } `json:"mx"`
    TXT []string `json:"txt"`
}

func lookupDNS(domain string) (*DNSResult, error) {
    out, err := exec.Command("quien", "dns", domain).Output()
    if err != nil {
        return nil, fmt.Errorf("quien dns执行失败: %w", err)
    }
    var result DNSResult
    if err := json.Unmarshal(out, &result); err != nil {
        return nil, fmt.Errorf("解析错误: %w", err)
    }
    return &result, nil
}

func main() {
    dns, err := lookupDNS("example.com")
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s的A记录: %v\n", dns.Domain, dns.A)
    for _, mx := range dns.MX {
        fmt.Printf("MX优先级%d: %s\n", mx.Priority, mx.Host)
    }
}

Go integration — full audit struct

Go语言集成——完整审计结构体

go
package main

import (
    "encoding/json"
    "os/exec"
)

type FullAudit struct {
    WHOIS struct {
        Registrar string `json:"registrar"`
        Created   string `json:"created"`
        Expires   string `json:"expires"`
        Updated   string `json:"updated"`
    } `json:"whois"`
    DNS struct {
        A   []string `json:"a"`
        NS  []string `json:"ns"`
        TXT []string `json:"txt"`
    } `json:"dns"`
    Mail struct {
        SPF struct {
            Record string `json:"record"`
            Valid  bool   `json:"valid"`
        } `json:"spf"`
        DMARC struct {
            Record string `json:"record"`
            Policy string `json:"policy"`
        } `json:"dmarc"`
    } `json:"mail"`
    TLS struct {
        Certificates []struct {
            Subject  string `json:"subject"`
            NotAfter string `json:"not_after"`
        } `json:"certificates"`
    } `json:"tls"`
    Stack struct {
        JavascriptFrameworks []string `json:"javascript_frameworks"`
        CSSFrameworks        []string `json:"css_frameworks"`
        ExternalServices     []string `json:"external_services"`
    } `json:"stack"`
}

func auditDomain(domain string) (*FullAudit, error) {
    out, err := exec.Command("quien", "all", domain).Output()
    if err != nil {
        return nil, err
    }
    var audit FullAudit
    return &audit, json.Unmarshal(out, &audit)
}

go
package main

import (
    "encoding/json"
    "os/exec"
)

type FullAudit struct {
    WHOIS struct {
        Registrar string `json:"registrar"`
        Created   string `json:"created"`
        Expires   string `json:"expires"`
        Updated   string `json:"updated"`
    } `json:"whois"`
    DNS struct {
        A   []string `json:"a"`
        NS  []string `json:"ns"`
        TXT []string `json:"txt"`
    } `json:"dns"`
    Mail struct {
        SPF struct {
            Record string `json:"record"`
            Valid  bool   `json:"valid"`
        } `json:"spf"`
        DMARC struct {
            Record string `json:"record"`
            Policy string `json:"policy"`
        } `json:"dmarc"`
    } `json:"mail"`
    TLS struct {
        Certificates []struct {
            Subject  string `json:"subject"`
            NotAfter string `json:"not_after"`
        } `json:"certificates"`
    } `json:"tls"`
    Stack struct {
        JavascriptFrameworks []string `json:"javascript_frameworks"`
        CSSFrameworks        []string `json:"css_frameworks"`
        ExternalServices     []string `json:"external_services"`
    } `json:"stack"`
}

func auditDomain(domain string) (*FullAudit, error) {
    out, err := exec.Command("quien", "all", domain).Output()
    if err != nil {
        return nil, err
    }
    var audit FullAudit
    return &audit, json.Unmarshal(out, &audit)
}

Agent Skill Integration

Agent Skill集成

Install quien as an agent skill so AI coding agents automatically use it for domain/IP lookups:
sh
npx skills add retlehs/quien

将quien安装为agent技能,让AI编码代理自动使用它进行域名/IP查询:
sh
npx skills add retlehs/quien

Key Behaviors to Know

需要了解的关键特性

  • RDAP-first: Uses RDAP protocol before falling back to raw WHOIS. Broader TLD coverage via IANA referral.
  • Automatic retry: All network lookups use exponential backoff — transient failures are retried automatically.
  • BGP fallback: If RDAP does not return ASN data for an IP, quien queries BGP routing tables for origin ASN/prefix.
  • PeeringDB enrichment: ASN lookups are enriched with PeeringDB data (peering policy, IX presence, traffic profile).
  • VMC validation: BIMI lookups validate the full VMC certificate chain, not just the record presence.
  • Tech stack from HTML: Stack detection fetches and parses the actual HTML of the target, not just HTTP headers.

  • 优先使用RDAP:先使用RDAP协议,再回退到原始WHOIS。通过IANA引用支持更广泛的TLD。
  • 自动重试:所有网络查询使用指数退避策略——临时失败会自动重试。
  • BGP备选方案:如果RDAP未返回IP的ASN数据,quien会查询BGP路由表获取源ASN/前缀。
  • PeeringDB增强:ASN查询会结合PeeringDB数据(对等策略、IX存在情况、流量概况)。
  • VMC验证:BIMI查询会验证完整的VMC证书链,而不仅仅是记录是否存在。
  • 从HTML识别技术栈:技术栈检测会获取并解析目标的实际HTML内容,而不仅仅是HTTP头。

Troubleshooting

故障排除

quien: command not found
sh
undefined
quien: command not found
sh
undefined

If installed via go install, ensure GOPATH/bin is in PATH

如果通过go install安装,请确保GOPATH/bin在PATH中

export PATH="$PATH:$(go env GOPATH)/bin"

**TUI doesn't render correctly**
```sh
export PATH="$PATH:$(go env GOPATH)/bin"

**TUI无法正确渲染**
```sh

Ensure your terminal supports true color and UTF-8

确保你的终端支持真彩色和UTF-8

echo $TERM # should be xterm-256color or similar echo $LANG # should include UTF-8

**Rate limiting / lookup failures**
- RDAP and WHOIS servers may rate-limit. quien retries with backoff automatically.
- For bulk scripting, add `sleep 1` between calls to avoid hitting rate limits.

**No DKIM results**
- DKIM requires knowing the selector. quien probes common selectors (google, default, mail, etc.) but custom selectors won't be discovered automatically.

**IP lookup shows no ASN**
- Some IP blocks are not in RDAP. quien falls back to BGP; if both fail, the block may be unrouted or private.

**JSON output is empty / malformed**
```sh
echo $TERM # 应为xterm-256color或类似值 echo $LANG # 应包含UTF-8

**速率限制/查询失败**
- RDAP和WHOIS服务器可能会限制速率。quien会自动使用退避策略重试。
- 批量脚本执行时,在两次调用之间添加`sleep 1`以避免触发速率限制。

**无DKIM结果**
- DKIM需要知道选择器。quien会探测常见选择器(google、default、mail等),但自定义选择器无法自动发现。

**IP查询未显示ASN**
- 某些IP块未收录在RDAP中。quien会回退到BGP查询;如果两者都失败,该IP块可能未路由或为私有IP。

**JSON输出为空/格式错误**
```sh

Confirm the subcommand syntax — subcommands always output JSON

确认子命令语法——子命令始终输出JSON

quien dns example.com # correct quien --json dns example.com # incorrect - --json is for top-level only
undefined
quien dns example.com # 正确 quien --json dns example.com # 错误——--json仅适用于顶层命令
undefined