MCPcopy Index your code
hub / github.com/KincaidYang/whois

github.com/KincaidYang/whois @v1.0.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.0.0 ↗ · + Follow
387 symbols 1,479 edges 61 files 251 documented · 65%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Go Reference Go CodeQL

中文文档

Introduction

A domain WHOIS query tool implemented in Golang, supporting WHOIS information queries for all publicly queryable TLD domains, IPv4/v6, and ASN.

In compliance with ICANN's "Temporary Specification for gTLD Registration Data" and the EU's "General Data Protection Regulation" (GDPR), when querying domain information, the program only returns essential information (see response examples below) and does not return the owner's contact information, address, phone number, email, and other personal fields.

Demo Sites: - https://whois.ddnsip.cn - https://whois.mmoke.com By immoke

Usage

Docker Deployment

# Install Redis
docker run -d --name redis -p 6379:6379 redis:latest
# Run whois
docker run -d --name whois -p 8043:8043 --link redis:redis jinzeyang/whois

Download

Using Binary Files

You can download the binary files for your platform from the Release page.

Build from Source

git clone https://github.com/KincaidYang/whois.git
cd whois
go build

Install Dependencies

This program requires Redis service support. You can refer to https://redis.io/docs/install/install-redis/install-redis-on-linux/ for installation.

Edit Configuration File

vim config.yaml

⚠️ Configuration keys are grouped by function and use camelCase (matching the API response field style). Unknown keys and the pre-v0.9 flat keys fail at startup with a migration hint instead of being silently ignored.

server:
  port: 8043                   # Server listening port
  rateLimit: 60                # Concurrency limit for upstream WHOIS server requests

log:
  level: "info"                # Log level: debug, info, warn, error (default: info)

cache:
  expiration: 3600             # Cache expiration time in seconds (default: 3600)
  negativeExpiration: 60       # How long "not found / denied" results are cached, in seconds (default: 60; set negative to disable)
  requireRedis: false          # false=allow fallback to memory cache when Redis fails, true=Redis must be available or program exits
  memoryMaxSize: 10000         # Maximum entries in memory cache; least-recently-used entries are evicted past this (default: 10000)
  memoryCleanInterval: 300     # Memory cache cleanup interval in seconds (default: 300)

redis:
  addr: "redis:6379"           # Redis server address
  password: ""                 # Redis password, leave empty if none
  db: 0                        # Redis database number
  tls: false                   # Enable TLS when Redis is reached over an untrusted network
  tlsSkipVerify: false         # Skip certificate verification (not recommended; self-signed certs only)

proxy:
  server: ""                   # Proxy server address; empty disables proxying
  username: ""                 # Proxy server username (if authentication required)
  password: ""                 # Proxy server password (if authentication required)
  suffixes: []                 # TLD suffixes that use the proxy; ["all"] routes everything through the proxy

bootstrap:
  interval: 86400              # RDAP server list refresh interval in seconds; 0 disables fetching (recommended: 86400)

auth:
  keys: []                     # Accepted API keys. Empty (the default) leaves the service open; one or more keys protect every endpoint except /health and /ready. Clients send a key as "Authorization: Bearer <key>" or "X-API-Key: <key>"
  # Entries are bare strings or objects (named, optionally rate-limited):
  # keys:
  #   - "plain-secret"         # anonymous key, auto-named key1/key2/...
  #   - key: "another-secret"
  #     name: "ci"             # display name: appears in the log "client" field and Prometheus metrics
  #     rateLimit: 120         # per-key rate limit (requests/minute); 0 or omitted = unlimited

batch:
  enabled: false               # POST /batch bulk-query endpoint (and the MCP batch tool); off by default, best enabled together with auth.keys
  maxItems: 10                 # maximum queries per batch request

mcp:
  localhostProtection: false   # DNS-rebinding protection for /mcp: only accept requests whose Host header is localhost. Keep false behind a reverse proxy; set true for direct localhost deployments

Environment Variables

Every configuration option can be overridden via environment variables (which take precedence over the config file) — handy for Docker/Kubernetes deployments where mounting a config file is inconvenient:

Variable Config key Default Description
WHOIS_PORT server.port 8043 HTTP listen port
WHOIS_RATE_LIMIT server.rateLimit 100 Maximum concurrent requests
WHOIS_LOG_LEVEL log.level info Log level: debug, info, warn, error
WHOIS_CACHE_EXPIRATION cache.expiration 3600 Cache TTL in seconds
WHOIS_NEGATIVE_CACHE_EXPIRATION cache.negativeExpiration 60 Negative-cache TTL in seconds; negative value disables
WHOIS_REQUIRE_REDIS cache.requireRedis false true/1 makes startup fail when Redis is unavailable
WHOIS_MEMORY_MAX_SIZE cache.memoryMaxSize 10000 Max entries in the in-memory cache
WHOIS_MEMORY_CLEAN_INTERVAL cache.memoryCleanInterval 300 In-memory cache cleanup interval in seconds
WHOIS_REDIS_ADDR redis.addr empty Redis address; the service falls back to the in-memory cache when unreachable (unless requireRedis)
WHOIS_REDIS_PASSWORD redis.password empty Redis password
WHOIS_REDIS_DB redis.db 0 Redis database number
WHOIS_REDIS_TLS redis.tls false true/1 enables TLS for Redis
WHOIS_REDIS_TLS_SKIP_VERIFY redis.tlsSkipVerify false true/1 skips certificate verification (not recommended)
WHOIS_PROXY_SERVER proxy.server empty Proxy URL; empty disables proxying
WHOIS_PROXY_USERNAME proxy.username empty Proxy username
WHOIS_PROXY_PASSWORD proxy.password empty Proxy password
WHOIS_PROXY_SUFFIXES proxy.suffixes empty TLDs queried through the proxy, comma-separated (all proxies everything)
WHOIS_BOOTSTRAP_INTERVAL bootstrap.interval 0 (disabled) IANA RDAP list refresh interval in seconds; the sample config ships 86400
WHOIS_AUTH_KEYS auth.keys empty API keys, comma-separated (bare keys only; naming / per-key limits need the config file)
WHOIS_BATCH_ENABLED batch.enabled false true/1 enables the bulk-query endpoint
WHOIS_BATCH_MAX_ITEMS batch.maxItems 10 Maximum queries per batch request
WHOIS_MCP_LOCALHOST_PROTECTION mcp.localhostProtection false true/1 enables DNS-rebinding protection for /mcp

Boolean variables accept only true and 1; anything else is treated as false. Numeric variables that fail to parse are silently ignored, leaving the config-file/default value in place.

Environment-only deployment example (no config file mounted):

docker run -d --name whois -p 8043:8043 \
  -e WHOIS_REDIS_ADDR=redis:6379 \
  -e WHOIS_BOOTSTRAP_INTERVAL=86400 \
  -e WHOIS_AUTH_KEYS=secret1,secret2 \
  --link redis:redis jinzeyang/whois

Configuration Notes: - Redis Configuration: Redis is recommended for better performance and multi-instance cache sharing - Cache Expiration: Adjust based on query frequency, 3600 seconds recommended - Memory Cache: Fallback when Redis is unavailable; evicts least-recently-used (LRU) entries once full - Negative Cache: Briefly caches "not found / denied" results to avoid repeatedly hitting upstream for missing resources; defaults to 60 seconds - Concurrency Limit: Controls request frequency to upstream servers to avoid rate limiting - Proxy Configuration: Some TLDs may require proxy access - Log Level: debug logs every cache hit and upstream query dispatch — noisy under load; info is recommended for production - Bootstrap Interval: On startup the service immediately fetches the latest RDAP server list from IANA, then refreshes on this interval; compiled-in data serves as fallback if the fetch fails - API Authentication: Disabled by default. Configuring auth.keys enables it; requests without a valid key get a 401 (RFC 9457 problem+json). Only /health and /ready are exempt so liveness/readiness probes keep working - Key naming and per-key rate limits: The object form of auth.keys gives each key a display name and a rate limit. The name labels the caller in the request logs (client field) and in the whois_client_requests_total{client,status_code} Prometheus metric; the limit is a token bucket (requests/minute, a full minute's budget may be spent at once) answering over-budget requests with 429 + Retry-After. Batches are charged per item: a batch of N queries costs N tokens - Batch queries: Off by default. Best enabled together with auth.keys — an open instance offering bulk queries multiplies how fast it can be abused against upstream registries

⚠️ Warning: The rate limit applies to requests from this program to WHOIS servers, not requests from users to this program. For example, if you set the limit to 50, the program will not exceed 50 requests/second to registry WHOIS servers, but user requests to this program are unlimited. Please use Nginx or other tools to rate-limit this program, or configure a per-key rateLimit, to prevent malicious requests.

Run

./whois

Note: The program listens on port 8043 by default.

Health Check Endpoints

The service provides the following health check endpoints:

Endpoint Description
GET /health Liveness probe - returns 200 if service is running
GET /ready Readiness probe - checks cache and capacity status
GET /info Runtime information - version, uptime, Go version, etc.
GET /metrics Prometheus metrics - request count, latency, cache hit rate, upstream query duration
GET /openapi.json OpenAPI 3.1 specification - machine-readable description of all endpoints and response schemas
POST /mcp MCP Streamable HTTP endpoint - for AI assistant integration
POST /batch Bulk queries - multiple domains/IPs/ASNs in one request (off by default, see batch.enabled)

Process Daemon (Optional)

You can use systemd or other tools to set up this program as a daemon process to auto-start after system reboot.

vim /etc/systemd/system/whois.service
[Unit]
Description=whois
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
ExecStart=/path/to/whois/whois
WorkingDirectory=/path/to/whois
Restart=on-failure

[Install]
WantedBy=multi-user.target

API Usage

GET requests

Browser Access

After deployment, access http://ip:port/domain-or-ip-or-asn via browser. Default port is 8043, e.g., http://1.2.3.4:8043/example.com

Typed Query Paths

Besides the auto-detecting root path, RFC 9082-style typed paths are available, suited to programmatic use — a resource of the wrong type returns 400 instead of being interpreted as another type:

curl http://localhost:8043/domain/example.com
curl http://localhost:8043/ip/192.0.2.1
curl http://localhost:8043/autnum/205794    # as205794 / AS205794 also accepted

IP queries accept CIDR prefixes (on both the root path and /ip/):

curl http://localhost:8043/ip/192.0.2.0/24
curl http://localhost:8043/2001:db8::/32

OpenAPI Specification

An OpenAPI 3.1 description of the service is available at /openapi.json, covering every endpoint, the response schemas (RDAP vocabulary) and the error format. It can be imported directly into Postman, Swagger UI and similar tools.

Caching and CORS

  • Successful responses carry an X-Cache header describing the cache outcome: HIT (served from the server cache), MISS (fetched upstream), or REFRESH (forced upstream by ?refresh), plus Cache-Control: public, max-age=<cache seconds> for client/CDN caching.
  • Successful (200) responses carry a strong ETag; send it back as If-None-Match: <etag> for conditional revalidation — unchanged content is answered with 304 Not Modified and no body. /openapi.json supports this too.
  • Every response carries Access-Control-Allow-Origin: *, so the API can be called cross-origin from browser frontends directly.

Internationalized domain names (IDN, including Unicode domains with non-ASCII characters) can be queried directly; the program converts them to Punycode automatically, e.g. http://1.2.3.4:8043/例子.cn.

Query Domain WHOIS Information

curl http://localhost:8043/example.com

Response: ```json { "objectClassName": "domain", "ldhName": "example.com", "registrar": "RESERVED-Internet Assigned Numbers Authority", "registrarIanaId": "376", "status": [ "client delete prohibited", "client transfer prohibited", "client update prohibited" ], "registrationDate": "1995-08-14T04:00:00Z", "expirationDate": "2026-08-13T04:00:00Z", "lastChangedDate": "2025-08-14T07:01:34Z", "nameservers": [ "a.iana-servers.net", "b.iana-servers.net" ], "secureDNS": { "delegationSigned": true, "dsData": [ { "keyTa

Extension points exported contracts — how you extend this code

Cache (Interface)
Cache defines the interface for cache operations [3 implementers]
internal/utils/cache_interface.go

Core symbols most depended-on inside this repo

Set
called by 83
internal/utils/cache_interface.go
Header
called by 76
internal/handlers/batch.go
Get
called by 54
internal/utils/cache_interface.go
normDate
called by 37
internal/whois/whois_parsers.go
HandleHTTPError
called by 16
internal/utils/response.go
writeProblem
called by 15
internal/utils/response.go
CleanStatus
called by 15
internal/model/normalize.go
matchFirstGroup
called by 15
internal/whois/whois_parsers.go

Shape

Function 295
Struct 50
Method 39
TypeAlias 2
Interface 1

Languages

Go100%

Modules by API surface

internal/whois/whois_parsers_test.go31 symbols
internal/whois/whois_parsers.go22 symbols
internal/utils/cache_interface.go22 symbols
internal/config/config.go18 symbols
internal/rdap/rdap_parse.go17 symbols
internal/config/config_test.go17 symbols
main_auth_test.go14 symbols
main.go14 symbols
internal/handlers/batch.go14 symbols
internal/utils/response.go13 symbols
internal/serverlist/lookup.go12 symbols
main_routes_test.go10 symbols

For agents

$ claude mcp add whois \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact