
새벽에 로그인 실패가 몰린 IP를 받았습니다. 유료 평판 API를 부르기 전에, 공짜로 알 수 있는 것부터 봅니다. 이 대역은 누가 빌렸나, 어느 망에 속하나, 스스로 붙인 이름이 있나, 대략 어느 나라인가, 클라우드 서버인가. 이 다섯 질문에 답하는 데는 키도 돈도 들지 않습니다. 그리고 유료 서비스도 결국 이 위에 자기 데이터를 얹습니다. 이번 편은 그 바닥을 직접 조회해 봅니다.

여섯 칸은 각각 다른 질문에 답합니다. 위치 DB만 노란색인 이유는 그 칸만 추정값이기 때문입니다. 맨 아래 빨간 상자가 이 편의 결론입니다. 공개 정보는 모두 "주소"에 대한 정보이고, 지금 그 주소를 쓰는 "사람"은 알려 주지 않습니다.
| 질문 | 정보 | 어디서 |
|---|---|---|
| 누가 빌렸나 | 등록 기록(RDAP·WHOIS) | 지역 인터넷 등록 기관(RIR) |
| 어느 망에 속하나 | AS 번호(ASN) | RIR 기록, BGP |
| 누가 경로를 알리나 | BGP 경로 | 라우팅 정보 |
| 스스로 붙인 이름 | 역방향 DNS(PTR) | 대역 주인이 운영하는 DNS |
| 어디쯤일까 | 위치(나라·도시·정확도 반경) | 위치 DB(MaxMind 등) |
| 데이터센터인가 | 클라우드 공개 대역 | AWS·Google Cloud·Azure의 JSON 파일 |
차례로 봅니다.

위에서 아래로 주소가 내려갑니다. 맨 아래 노란 상자가 중요합니다. 등록 기록은 대개 셋째 줄(통신사·클라우드·기업)에서 멈춥니다.
IANA(Internet Assigned Numbers Authority)는 아직 쓰지 않은 주소 덩어리를 RIR(Regional Internet Registry, 지역 인터넷 등록 기관)에 나눠 줍니다. IANA 설명에 따르면 RIR이 주소가 더 필요할 때 추가로 나눠 주고, 멀티캐스트 같은 특수한 경우를 빼면 ISP나 최종 사용자에게 직접 주지 않습니다.
RIR은 다섯 곳입니다(IANA 기준).
| RIR | 담당 지역 |
|---|---|
| AFRINIC | 아프리카 |
| APNIC | 아시아·태평양(한국 포함) |
| ARIN | 캐나다, 미국, 일부 카리브해 섬 |
| LACNIC | 중남미, 일부 카리브해 섬 |
| RIPE NCC | 유럽, 중동, 중앙아시아 |
RIR은 다시 통신사·클라우드·기업·대학에 주소를 할당(allocation)합니다. 통신사는 가입자에게, 클라우드는 고객 서버에 다시 나눠 줍니다. 이 마지막 단계는 대개 RIR 기록에 남지 않습니다. 그래서 등록 정보로 알 수 있는 것은 "통신사 X의 대역"까지입니다. "오늘 그 주소를 쓰는 가입자"는 알 수 없습니다.
평판에서 이 구조가 중요한 이유는 둘입니다.
WHOIS는 오래된 조회 방식입니다. 43번 포트로 글자를 보내면 글자로 답이 옵니다. 형식이 RIR마다 달라서 프로그램으로 읽기 어렵습니다.
RDAP(Registration Data Access Protocol)은 그 후속입니다. HTTPS로 묻고 JSON으로 답합니다. 질의 형식은 RFC 9082, 응답 형식은 RFC 9083에 정해져 있습니다(둘 다 2021년 6월, 각각 RFC 7482·7483을 대체). 응답 미디어 타입은 application/rdap+json입니다.

①에서 "어느 RIR에 물을지"를 로컬에서 찾고, ②에서 그 RIR에 한 번 묻고, ③에서 JSON의 몇 칸만 읽습니다. 그림 아래 줄은 문서용 주소를 물었을 때의 결과입니다.
RDAP 서버는 RIR마다 따로 있습니다. 그래서 먼저 "이 주소는 어느 RIR 담당인가"를 알아야 합니다. IANA는 이 표를 JSON 파일로 공개합니다(RFC 9224, RDAP 부트스트랩). IPv4용, IPv6용, AS 번호용 파일이 따로 있습니다. RFC 9224는 클라이언트가 이 파일을 받아 두고(캐시), 매 조회마다 받지 말라고 적습니다.
lab/ip-basics/rdap_lookup.py는 부트스트랩 파일로 RIR을 찾고, /ip/<주소>와 /autnum/<번호>를 한 번씩 묻습니다. 대상은 공개 리졸버 두 개와 문서용 주소 두 개, AS 번호 두 개입니다. 요청은 모두 여섯 건입니다.
cd lab/ip-basics
../.venv/bin/python -I rdap_lookup.py
실제 출력(2026-10-31, macOS · 지연 시간은 매번 다름):
부트스트랩 iana-rdap-ipv4.json: publication=2019-06-07T19:00:02Z
부트스트랩 iana-rdap-ipv6.json: publication=2024-11-01T22:00:01Z
부트스트랩 iana-rdap-asn.json: publication=2026-06-01T20:00:01Z
### IP 8.8.8.8
IANA 부트스트랩: 8.0.0.0/8 → https://rdap.arin.net/registry/
GET https://rdap.arin.net/registry/ip/8.8.8.8 → 200 application/rdap+json (684ms, 매번 다름)
handle : NET-8-8-8-0-2
startAddress : 8.8.8.0
endAddress : 8.8.8.255
ipVersion : v4
name : GOGL
type : DIRECT ALLOCATION
parentHandle : NET-8-0-0-0-0
cidr0_cidrs : ['8.8.8.0/24']
events : {'last changed': '2023-12-28', 'registration': '2023-12-28'}
entities : ['registrant=Google LLC']
### IP 1.1.1.1
IANA 부트스트랩: 1.0.0.0/8 → https://rdap.apnic.net/
GET https://rdap.apnic.net/ip/1.1.1.1 → 200 application/rdap+json (171ms, 매번 다름)
handle : 1.1.1.0 - 1.1.1.255
startAddress : 1.1.1.0
endAddress : 1.1.1.255
ipVersion : v4
name : APNIC-LABS
type : ASSIGNED PORTABLE
country : AU
cidr0_cidrs : ['1.1.1.0/24']
events : {'registration': '2011-08-10', 'last changed': '2023-04-26'}
entities : ['technical,administrative=APNICRANDNET Infrastructure Contact', 'abuse=IRT-APNICRANDNET-AU', 'registrant=APNIC Research and Development']
읽는 법은 이렇습니다.
startAddress~endAddress: 이 주소가 속한 등록 단위입니다. 둘 다 /24(256개)입니다. 평판 서비스가 "대역"이라고 할 때 흔히 이 단위나 BGP로 광고되는 단위를 씁니다.type: ARIN은 DIRECT ALLOCATION, APNIC은 ASSIGNED PORTABLE처럼 RIR마다 값이 다릅니다. 같은 칸이라도 RIR마다 쓰는 말이 달라서 그대로 비교하면 안 됩니다.entities: 등록자(registrant), 기술·관리 담당, 남용 신고 연락처(abuse)입니다. 내 서버를 공격한 IP가 있을 때 신고할 곳이 여기 있습니다.country: 1.1.1.1에는 AU가 있고 8.8.8.8 응답에는 없었습니다. 등록 기록의 나라는 등록한 조직의 나라이지, 그 주소를 쓰는 서버가 있는 곳이 아닙니다. 1.1.1.1은 전 세계에서 같은 주소로 응답하는 서비스입니다.같은 실행에서 문서용 주소와 AS 번호도 물었습니다.
### IP 192.0.2.1
IANA 부트스트랩: 192.0.0.0/8 → https://rdap.arin.net/registry/
GET https://rdap.arin.net/registry/ip/192.0.2.1 → 200 application/rdap+json (484ms, 매번 다름)
handle : NET-192-0-2-0-1
startAddress : 192.0.2.0
endAddress : 192.0.2.255
ipVersion : v4
name : TEST-NET-1
parentHandle : NET-192-0-0-0-0
cidr0_cidrs : ['192.0.2.0/24']
events : {'last changed': '2024-05-24', 'registration': '2009-06-29'}
entities : ['registrant=Internet Assigned Numbers Authority']
### IP 2001:db8::1
IANA 부트스트랩: 2001:c00::/23 → https://rdap.apnic.net/
GET https://rdap.apnic.net/ip/2001:db8::1 → 404 application/rdap+json (199ms, 매번 다름)
### AS15169
IANA 부트스트랩: 13312-15359 → https://rdap.arin.net/registry/
GET https://rdap.arin.net/registry/autnum/15169 → 200
handle : AS15169
name : GOOGLE
entities : ['registrant=Google LLC', 'technical=Google LLC']
### AS13335
GET https://rdap.arin.net/registry/autnum/13335 → 200
name : CLOUDFLARENET
entities : ['registrant=Cloudflare, Inc.', 'abuse=Abuse', 'technical=Admin']
(404 응답의 본문 줄과 AS 쪽 startAutnum·endAutnum 줄, AS13335의 부트스트랩 줄을 줄였습니다. 원문은 lab/results/01-rdap.txt에 있습니다.)
문서용 주소 192.0.2.1은 IANA가 가진 TEST-NET-1 기록만 돌아왔습니다. type도 없고 통신사나 고객 이름도 없습니다. 누구에게도 할당되지 않은 주소라는 뜻입니다. IPv6 문서용 2001:db8::1은 404였습니다. 부트스트랩 표에서 가장 가까운 상위 대역(2001:c00::/23)이 APNIC이라 그쪽에 물었지만, APNIC에는 그 주소의 기록이 없었습니다. 로그에 이런 주소가 찍혀 있다면 공격자가 아니라 설정 실수나 테스트 데이터일 가능성이 높습니다.

왼쪽 주황 상자가 대역을 처음 광고하는 AS(origin)입니다. 화살표 방향으로 광고가 퍼집니다. 가운데 상자는 AS64502가 받은 경로이고, 맨 끝 번호가 출발 AS입니다. AS 번호는 문서용(RFC 5398, 64496~64511)이라 실제 망이 아닙니다.
AS(Autonomous System, 자율 시스템)는 한 기관이 하나의 정책으로 운영하는 망입니다. 통신사, 클라우드, 큰 회사, 대학이 저마다 AS 번호(ASN)를 받습니다. 위의 RDAP 조회에서 AS15169는 GOOGLE, AS13335는 CLOUDFLARENET으로 등록돼 있었습니다.
BGP(Border Gateway Protocol)는 AS끼리 "이 대역으로 가는 길은 나를 거쳐라"라고 알리는 규약입니다. 경로에는 거쳐 온 AS 번호 목록(AS_PATH)이 붙고, 맨 끝이 그 대역을 처음 광고한 AS입니다.
평판 서비스는 ASN을 많이 씁니다.
BGP 정보의 한계도 있습니다. 경로 광고는 잘못되거나(설정 실수) 가로채일 수 있습니다(BGP 하이재킹). 평판 서비스가 "이 대역의 AS"를 언제 기준으로 기록했는지에 따라 결과가 달라질 수 있습니다.

윗줄 세 칸을 왼쪽부터 따라갑니다. ③까지 가야 이름을 믿을 수 있습니다. 아래 두 칸은 PTR 이름을 평판에 쓸 때의 쓸모와 함정입니다.
정방향 DNS는 "이름 → 주소"이고, 역방향 DNS는 "주소 → 이름"입니다. 주소의 옥텟을 뒤집어 in-addr.arpa 아래에서 PTR 레코드를 묻습니다. RFC 1035의 예로는 10.2.0.52의 데이터가 52.0.2.10.IN-ADDR.ARPA에 있습니다. IPv6는 16진수 한 글자씩 뒤집어 ip6.arpa 아래에서 묻습니다.
같은 스크립트의 마지막 부분이 PTR과 정방향 확인입니다.
실제 출력(2026-10-31, macOS):
### 역방향 DNS(PTR)와 정방향 확인
PTR 8.8.8.8.in-addr.arpa. → ['dns.google.']
정방향 확인 dns.google. A → ['8.8.8.8', '8.8.4.4'] 일치=True
PTR 1.1.1.1.in-addr.arpa. → ['one.one.one.one.']
정방향 확인 one.one.one.one. A → ['1.0.0.1', '1.1.1.1'] 일치=True
PTR 1.2.0.192.in-addr.arpa. → 없음 (NXDOMAIN)
PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. → 없음 (NXDOMAIN)
중요한 점은 누가 PTR을 정하나입니다. 정방향 이름은 도메인 주인이 정하지만, 역방향 이름은 그 대역의 주인(통신사·클라우드, 또는 위임받은 고객)이 정합니다. 그래서 PTR에 무엇을 쓰든 막을 방법이 없습니다. 내 대역의 PTR을 dns.google이라고 써 둘 수도 있습니다. 그래서 PTR로 얻은 이름을 다시 정방향으로 풀어 같은 주소가 나오는지 확인합니다. 이것을 FCrDNS(forward-confirmed reverse DNS)라고 부릅니다. 위 출력의 일치=True가 그 확인입니다.
평판에서 PTR은 이렇게 씁니다.
203-0-113-7.dyn.isp.example처럼 주소가 들어간 이름은 가정용 동적 회선에 흔합니다. 이런 주소에서 메일 서버가 직접 메일을 보내면 메일함 제공자는 수상하게 봅니다(10편).
가운데 점이 DB가 준 위도·경도이고, 원이 정확도 반경입니다. 오른쪽 세 상자는 테스트 DB의 실제 응답입니다. 같은 "London"이라도 반경이 3km일 때와 100km일 때는 믿을 수 있는 정도가 다릅니다. 원 크기 비율은 그림용입니다.
IP 주소에는 위치가 들어 있지 않습니다. 위치 DB는 여러 데이터를 모아 "이 대역은 대략 여기"를 추정합니다(MaxMind가 무엇을 모으는지는 04편에서 봅니다). MaxMind 문서는 위도·경도를 보여 줄 때 정확도 반경(accuracy_radius)을 함께 보여 달라고 하고, 좌표가 특정 주소나 가구를 찾는 데 쓸 만큼 정확하지 않다고 적습니다. 웹 서비스 응답 문서는 이 반경을 이렇게 정의합니다. 단위는 킬로미터이고, 사용자가 그 반경 안에 있을 확률이 67%라는 뜻입니다. 셋 중 한 번은 원 밖에 있다는 말이기도 합니다.
MaxMind가 GitHub에 공개한 테스트용 DB로 조회해 봅니다. 계정이 필요 없고, 실제 데이터가 아니라 시험용으로 만든 값입니다(실데이터는 04편에서 다룹니다).
../.venv/bin/python -I geo_lookup.py
실제 출력(2026-10-31, macOS · geoip2 5.3.0, 테스트 DB 값이라 실제 위치 아님):
City 테스트 DB: database_type=GeoIP2-City build_epoch=1792695177 node_count=946
81.2.69.144 network=81.2.69.144/28 country=GB city=London lat,lon=(51.5142,-0.0931) accuracy_radius=3km
81.2.69.160 network=81.2.69.160/27 country=GB city=London lat,lon=(51.5142,-0.0931) accuracy_radius=100km
89.160.20.128 network=89.160.20.128/25 country=SE city=Linköping lat,lon=(58.4167,15.6167) accuracy_radius=76km
149.101.100.1 network=149.101.100.0/28 country=US city=None lat,lon=(37.751,-97.822) accuracy_radius=1000km
2001:480:10::1 network=2001:480:10::/48 country=US city=San Diego lat,lon=(32.7203,-117.1552) accuracy_radius=20km
192.0.2.1 위치 없음(AddressNotFoundError)
ASN 테스트 DB
1.0.0.1 network=1.0.0.0/24 AS15169 Google Inc.
12.81.92.1 network=12.81.92.0/22 AS7018 AT&T Services
38.0.0.1 network=38.0.0.0/8 AS174 Cogent Communications
192.0.2.1 ASN 없음(AddressNotFoundError)
읽을 것이 셋입니다.
network 칸이 있습니다. 위치 DB도 주소 하나가 아니라 대역 단위로 값을 줍니다. 81.2.69.144/28과 81.2.69.160/27은 이웃이지만 반경이 3km와 100km로 다릅니다.149.101.100.1은 도시가 없고 반경이 1000km입니다. 나라만 아는 경우입니다. 이때 위도·경도는 그 나라의 대략 가운데쯤입니다. 지도에 점을 찍으면 아무도 살지 않는 곳에 찍힙니다.1.0.0.1을 AS15169로 줍니다. 실제로는 위 RDAP 부트스트랩에서 보듯 1.0.0.0/8은 APNIC 담당 대역입니다. 테스트 DB는 필드 모양과 코드를 시험하는 용도일 뿐입니다.위치가 크게 틀리기 쉬운 경우도 알아 둡니다.
그래서 "해외 IP면 차단" 같은 규칙은 해외 출장자, 해외 로밍, VPN을 쓰는 직원을 함께 막습니다. 위치는 추가 인증의 재료로 쓰고, 단독 차단 근거로 쓰지 않습니다(14편).

왼쪽 파일들을 가운데 배치가 대역 표로 만들고, 오른쪽이 판별 결과입니다. 요청 경로에서는 밖으로 묻지 않습니다. 맨 아래 빨간 상자가 이 방법의 한계입니다.
큰 클라우드 사업자는 자기 IP 대역을 JSON으로 공개합니다. 원래 목적은 고객이 방화벽 규칙을 만들게 돕는 것이지만, 평판에서는 "이 요청이 클라우드 서버에서 왔나"를 판별하는 데 씁니다.
| 사업자 | 파일 | 문서에 적힌 성질 |
|---|---|---|
| AWS | https://ip-ranges.amazonaws.com/ip-ranges.json | 고객이 흔히 쓰는 서비스의 대역만 싣고 모든 서비스를 싣지는 않는다. BYOIP(고객이 가져온 대역)는 빠진다. 변경 알림을 SNS로 받을 수 있다 |
| Google Cloud | https://www.gstatic.com/ipranges/cloud.json | 고객이 쓸 수 있는 전역·리전 외부 IP 대역 |
| Azure | Service Tags JSON(Microsoft 다운로드 센터) | 매주 갱신해 공개. 새 주소는 태그에 추가되고 최소 1주일 뒤부터 쓰인다 |
AWS와 Google Cloud 파일을 2026-10-31에 한 번 받아 lab/ip-basics/data/에 두고, 로컬에서 판별합니다. 시험 IP는 파일에 적힌 대역의 첫 주소, 공개 리졸버, 문서용 주소, CGNAT 예시 주소입니다.
../.venv/bin/python -I cloud_classify.py
실제 출력(2026-10-31, macOS · 대역 개수는 파일을 받을 때마다 다름):
파일 시각: {'aws_createDate': '2026-10-30-18-27-05', 'aws_syncToken': '1793384825', 'gcp_creationTime': '2026-10-30T13:08:23.261528', 'gcp_syncToken': '1793390903261'}
AWS IPv4: 대역 10,716개
AWS IPv6: 대역 7,018개
GoogleCloud IPv4: 대역 1,040개
GoogleCloud IPv6: 대역 95개
AWS service 값 상위 5: [('AMAZON', 9351), ('EC2', 4467), ('S3', 1146), ('ROUTE53_RESOLVER', 638), ('IVS_REALTIME', 254)]
3.5.140.1 클라우드=예 AWS 3.5.140.0/22 AMAZON/ap-northeast-2 (겹친 대역 3개)
└ 같은 대역 다른 항목 3.5.140.0/22 S3/ap-northeast-2
└ 같은 대역 다른 항목 3.5.140.0/22 EC2/ap-northeast-2
34.1.208.1 클라우드=예 GoogleCloud 34.1.208.0/20 Google Cloud/africa-south1 (겹친 대역 1개)
8.8.8.8 클라우드=모름 (두 파일 어디에도 없음)
1.1.1.1 클라우드=모름 (두 파일 어디에도 없음)
192.0.2.10 클라우드=모름 (두 파일 어디에도 없음)
100.64.0.1 클라우드=모름 (두 파일 어디에도 없음)
주의: 파일에 없다고 클라우드가 아닌 것은 아니다(다른 사업자, AWS BYOIP, 목록에 안 올린 서비스).
읽을 것이 셋입니다.
3.5.140.0/22가 AMAZON, S3, EC2로 세 번 나왔습니다. AWS 문법 문서에 따르면 모든 서비스 대역은 AMAZON에도 들어 있습니다. 또 S3처럼 EC2 자원을 쓰는 서비스의 대역은 S3와 EC2 양쪽에 나오지만 S3 전용이고, EC2 고객 인스턴스 대역만 보려면 "EC2에는 있고 S3에는 없는 것"을 고르라고 안내합니다. "클라우드인가"만 볼 때는 상관없지만, "고객 서버(EC2)인가"까지 나누려면 이 겹침을 처리해야 합니다.is_hosting_provider 등).운영에서는 이 파일을 주기적으로 받아 메모리나 로컬 DB에 올리고, 파일 안의 시각 칸(createDate, creationTime, Azure의 changeNumber)이 바뀌었을 때만 다시 만듭니다. 요청마다 파일을 받거나 외부 API를 부르지 않습니다.
country는 등록 조직 기준입니다. 위치가 필요하면 위치 DB를 쓰고, 그것도 반경을 함께 봅니다.모든 링크는 2026-10-31에 확인했습니다.
/ip/·/autnum/): https://www.rfc-editor.org/rfc/rfc9082.htmlapplication/rdap+json): https://www.rfc-editor.org/rfc/rfc9083.htmlaccuracy_radius 킬로미터, 67% 신뢰): https://dev.maxmind.com/geoip/docs/web-services/responsesAMAZON 포함 관계, S3·EC2 겹침): https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-syntax.htmllab/results/01-rdap.txt, 01-cloud-classify.txt, 01-geo-test-mmdb.txt이전 글 소개: IP 평판 점수는 판정이 아니라 재료다
다음 글 평판 데이터는 어디서 오나: 수집 방식 여섯 가지와 공통 구조
시리즈 전체 목록 IP 평판은 어떻게 만들어지고, 어떻게 써야 하나 전체 목록