리눅스 whois 명령어 사용법 - 도메인 만료일과 공격 IP 소유자 확인
이 명령어를 언제 쓰는가
두 가지 상황에서 손이 간다.
첫째, 도메인 만료일 확인이다. 서비스가 통째로 죽는 사고 중 가장 허무한 것이 도메인 갱신을 놓치는 경우다. 카드가 만료됐거나 담당자가 퇴사해 안내 메일이 아무도 안 보는 주소로 갔거나 하는 식으로 실제로 일어난다. whois로 만료일을 뽑아 감시 스크립트에 넣어두면 이 사고는 없어진다.
둘째, 낯선 IP의 정체 확인이다. 로그에 수천 건씩 찍히는 접속 시도가 어느 대역인지, 어느 나라·어느 사업자 소유인지, 신고할 abuse 연락처가 어디인지를 본다. 차단 정책을 IP 하나가 아니라 대역 단위로 세울 근거도 여기서 나온다.
이름 해석이나 경로와는 무관한 도구다. 접속 장애의 원인을 찾는 흐름 밖에 있지만, 도메인 자체가 만료돼 DNS가 통째로 사라지는 유형의 장애에서는 여기가 시작점이다.
기본 형식
whois [-h 서버] 도메인_또는_IP
- 대상 — 도메인이면 등록 정보를, IP나 대역이면 할당 정보를 조회한다. AS 번호(
AS15169)도 된다. - -h — 물어볼 whois 서버 지정. 최상위 도메인마다 담당 서버가 다르다(
.kr은whois.kr). - DNS와 달리 whois는 단순 텍스트 프로토콜(43/tcp)이다. 응답 형식이 서버마다 제각각이라 파싱할 때 주의가 필요하다.
Ubuntu/Debian은 apt install whois, RHEL/Rocky는 dnf install whois로 설치한다. 기본 설치되는 배포판은 드물다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
-h | whois 서버 직접 지정 | whois -h whois.kr devin.kr |
-p | 포트 지정(기본 43) | whois -h whois.kr -p 43 devin.kr |
-H | 법적 고지 문구를 생략(Debian whois) | whois -H devin.kr |
-a / -A | ARIN 등 특정 레지스트리 강제(BSD whois) | whois -a 8.8.8.8 |
| 없음 | 대상만 주면 담당 서버를 자동으로 찾는다 | whois devin.kr |
실전 예제
1. 도메인 만료일을 확인한다. 분기마다 한 번은 눈으로 봐야 하는 값이다.
whois -h whois.kr devin.kr
도메인이름 : devin.kr
등록인 : Domain Privacy Services
등록일 : 2022. 09. 22.
최근 정보 변경일 : 2025. 06. 27.
사용 종료일 : 2027. 09. 22.
등록대행자 : 메가존(주)(http://HOSTING.KR)
DNSSEC : 미서명
등록정보 보호 : clientTransferProhibited
사용 종료일이 만료일이다. 등록정보 보호의 clientTransferProhibited는 무단 이관을 막는 잠금 상태로, 켜져 있는 것이 정상이다. 이게 풀려 있으면 도메인 탈취 위험이 있으니 등록대행사에서 잠가둔다.
영문 gTLD(.com, .net 등)는 필드 이름이 다르다.
whois example.com | grep -iE 'expir|registrar:|name server'
2. 만료 임박을 자동 감시한다. 사람이 기억하는 대신 스크립트에 맡긴다.
#!/bin/bash
DOMAIN="$1"
EXP=$(whois "$DOMAIN" | awk -F': *' '/Registry Expiry Date|Expiration Date/ {print $2; exit}')
[ -z "$EXP" ] && { echo "expiry not found for $DOMAIN" >&2; exit 1; }
LEFT=$(( ( $(date -d "$EXP" +%s) - $(date +%s) ) / 86400 ))
echo "$DOMAIN expires in $LEFT days"
[ "$LEFT" -lt 30 ] && exit 2
exit 0
date -d는 GNU date 문법이다. macOS/BSD의 date는 -d가 다른 의미이므로, 맥에서 돌리려면 gdate(coreutils)를 설치하거나 date -j -f를 써야 한다. 이런 스크립트는 리눅스 서버의 cron에 두는 것이 맞다.
3. 공격 IP의 소유 대역과 신고처를 찾는다. 로그에 반복되는 IP를 그대로 넣는다.
whois -h whois.arin.net 8.8.8.8
NetRange: 8.8.8.0 - 8.8.8.255
CIDR: 8.8.8.0/24
NetName: GOGL
NetType: Direct Allocation
Organization: Google LLC (GOGL)
RegDate: 2023-12-28
CIDR이 핵심이다. 이 값으로 차단 정책을 대역 단위로 세운다. 다만 대역 차단은 신중해야 한다. 클라우드 사업자 대역을 통째로 막으면 정상 이용자와 연동 서비스까지 함께 끊긴다.
4. 신고할 abuse 연락처만 뽑는다.
whois 8.8.8.8 | grep -i abuse
이 주소로 시각(타임존 포함), 출발지 IP, 대상 포트, 로그 원문을 정리해 보내면 상대 사업자가 조치할 수 있다.
5. 도메인이 어느 네임서버를 쓰는지 등록 단계에서 확인한다. 이관 직후 dig 결과와 대조할 때 쓴다.
whois -h whois.kr devin.kr | grep -A1 '네임서버'
dig +short devin.kr NS
whois는 등록기관에 등록된 값이고 dig는 실제 DNS에서 응답하는 값이다. 이 둘이 다르면 이관이 아직 반영되지 않은 것이다.
6. 여러 도메인의 만료일을 한 번에 훑는다.
for d in $(cat domains.txt); do
printf '%-25s %s\n' "$d" "$(whois "$d" | awk -F': *' '/Registry Expiry Date/ {print $2; exit}')"
sleep 2
done
sleep이 들어간 이유는 아래 함정 절에 있다.
함정과 주의점
연속 조회하면 차단당한다. whois 서버는 대부분 IP당 조회 속도 제한을 둔다. 반복문으로 수십 개를 연달아 던지면 몇 시간 동안 query rate exceeded만 받는다. 스크립트에는 반드시 sleep을 넣고, 결과를 파일에 캐시해 같은 도메인을 하루에 여러 번 조회하지 않게 만든다.
GDPR 이후 개인정보는 대부분 가려져 있다. 2018년 이후 유럽 관련 도메인은 등록자 이름·메일·주소가 REDACTED FOR PRIVACY로 나온다. 한국 .kr도 정보공개여부: N이면 등록인이 프라이버시 대행 이름으로만 표시된다. whois로 실제 소유자를 알아내겠다는 기대는 접는 것이 맞다. 만료일, 등록대행사, 네임서버, 상태 플래그는 여전히 보이므로 운영 목적에는 충분하다.
출력 형식이 서버마다 다르다. Registry Expiry Date, Expiration Date, expires, 한글 사용 종료일이 전부 같은 항목이다. 하나의 정규식으로 전 세계 TLD를 파싱할 수 없다. 스크립트를 쓴다면 취급하는 TLD를 한정하고, 값을 못 찾았을 때 조용히 0으로 처리하지 말고 명시적으로 실패 처리한다. 만료 감시 스크립트가 파싱 실패를 성공으로 처리하는 바람에 아무 경고 없이 도메인이 만료되는 사고가 실제로 있다.
macOS와 리눅스의 동작이 다르다. 이 맥에서 whois devin.kr을 그냥 치면 IANA 서버의 안내(refer: whois.kr)만 나오고 실제 등록 정보는 안 나온다. BSD whois는 위임을 자동으로 따라가지 않는 경우가 있어 -h whois.kr을 직접 줘야 한다. Debian/Ubuntu의 whois는 내부 TLD 매핑 표를 갖고 있어 대개 자동으로 담당 서버까지 찾아간다. 스크립트를 옮길 때 이 차이 때문에 결과가 비는 일이 잦다.
whois는 사양길이고 RDAP이 후속이다. 형식이 제각각인 문제를 풀기 위해 JSON 기반의 RDAP 프로토콜이 표준으로 자리 잡는 중이다. 자동화를 새로 만든다면 curl -s https://rdap.org/domain/example.com | jq 쪽이 파싱이 훨씬 안정적이다. 다만 아직 whois만 지원하는 TLD도 있어서 당분간은 둘 다 쓰게 된다.
함께 보면 좋은 명령어
- dig — 등록 정보가 아니라 실제 DNS 응답을 확인한다. whois 결과와 대조한다.
- curl — RDAP JSON을 받아오는 데 쓴다.
- grep — 긴 whois 출력에서 필요한 필드만 뽑을 때 사실상 필수다.