diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,17 @@
+# Output files
+dns_records.csv
+dns_records.json
+dns_records.txt
+dns_records_root_domains.csv
+*.log
+
+# Windows
+Thumbs.db
+Desktop.ini
+
+# IDE
+.vscode/
+.idea/
+
+# Claude Code
+.claude/
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
@@ -0,0 +1,184 @@
+# UDFX - Ultimate Domain Finder X 개발 명세서
+
+## 프로젝트 정보
+
+| 항목 | 내용 |
+|------|------|
+| 프로젝트명 | UDFX (Ultimate Domain Finder X) |
+| 버전 | 1.0.0 |
+| 개발일 | 2025-02-06 |
+| 개발언어 | PowerShell |
+| 대상환경 | Windows Server / Windows 10+ |
+
+## 개발 배경
+
+- 에어갭(Air-Gap) 환경에서 사용 가능한 도메인 탐색 도구 필요
+- 기존 도구(usfx 등)는 인터넷 연결 또는 DNS 브루트포스 방식에 의존
+- AD 통합 DNS의 경우 LDAP을 통해 직접 레코드 조회 가능
+
+## 아키텍처
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ UDFX (Get-ADDnsRecords.ps1) │
+├─────────────────────────────────────────────────────────┤
+│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
+│ │ Zone 검색 │→ │ Record 수집 │→ │ 결과 출력 │ │
+│ │ (LDAP) │ │ (dnsRecord) │ │ (CSV/JSON/TXT) │ │
+│ └─────────────┘ └─────────────┘ └─────────────────┘ │
+└─────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌────────────────────────┐
+ │ Active Directory │
+ │ DC=DomainDnsZones │
+ │ (LDAP Query) │
+ └────────────────────────┘
+```
+
+## 핵심 함수
+
+### Get-RootDomain
+
+루트 도메인 추출 함수
+
+```powershell
+function Get-RootDomain {
+ param([string]$domain)
+ # .co.kr, .or.kr 등 3단계 TLD 처리
+ # 일반 도메인: example.com → example.com
+ # 한국 도메인: example.co.kr → example.co.kr
+}
+```
+
+**지원 TLD:**
+- 일반: .com, .net, .org, .io 등
+- 한국: .co.kr, .or.kr, .go.kr, .ac.kr 등
+- 영국: .co.uk, .org.uk 등
+- 일본: .co.jp, .or.jp 등
+
+### Get-DnsNameFromRecord
+
+AD DNS 바이너리 레코드에서 도메인명 추출
+
+```powershell
+function Get-DnsNameFromRecord {
+ param(
+ [byte[]]$data,
+ [int]$offset
+ )
+ # DNS wire format (길이-프리픽스) 파싱
+ # 라벨별로 분리 후 점(.)으로 결합
+}
+```
+
+**DNS 레코드 바이너리 구조:**
+```
+Offset | Size | Field
+--------|------|------------------
+0-1 | 2 | Data Length
+2-3 | 2 | Record Type
+4-7 | 4 | Version/Serial
+8-11 | 4 | TTL
+12-15 | 4 | Reserved
+16-19 | 4 | Timestamp
+20-23 | 4 | Reserved
+24+ | N | Record Data
+```
+
+### Convert-DNSRecord
+
+바이너리 DNS 레코드를 파싱하여 구조화된 데이터로 변환
+
+```powershell
+function Convert-DNSRecord {
+ param([byte[]]$RecordData)
+ # Record Type에 따라 적절한 파싱 수행
+ # A: IPv4 (4 bytes)
+ # AAAA: IPv6 (16 bytes)
+ # NS/CNAME: DNS Name
+ # MX: Priority(2) + DNS Name
+ # SRV: Priority(2) + Weight(2) + Port(2) + DNS Name
+}
+```
+
+## 레코드 타입 코드
+
+| 타입 | 코드 | 데이터 형식 |
+|------|------|-------------|
+| A | 1 | 4 bytes (IPv4) |
+| NS | 2 | DNS Name |
+| CNAME | 5 | DNS Name |
+| SOA | 6 | DNS Name + Serial 등 |
+| PTR | 12 | DNS Name |
+| MX | 15 | 2 bytes (Priority) + DNS Name |
+| TXT | 16 | Length-prefixed string |
+| AAAA | 28 | 16 bytes (IPv6) |
+| SRV | 33 | 6 bytes (Pri/Wt/Port) + DNS Name |
+
+## LDAP 쿼리 구조
+
+### DNS Zone 검색
+
+```
+Base DN: DC=DomainDnsZones,DC=corp,DC=example,DC=com
+Filter: (objectClass=dnsZone)
+```
+
+### DNS Record 검색
+
+```
+Base DN: DC=<ZoneName>,CN=MicrosoftDNS,DC=DomainDnsZones,...
+Filter: (objectClass=dnsNode)
+Attributes: name, dnsRecord
+```
+
+## 알려진 이슈
+
+### 1. NS/SRV 레코드 이름 파싱
+
+**현상**: NS, SRV 레코드의 대상 호스트명이 점(.) 없이 출력됨
+
+```
+예: hq-dc-01corpexamplecom (실제: hq-dc-01.corp.example.com)
+```
+
+**원인**: AD DNS 바이너리 포맷의 첫 바이트(전체 이름 길이)와 라벨 구분 처리 문제
+
+**상태**: 미해결 (A 레코드 IP는 정상 동작)
+
+### 2. SRV 레코드 포트/우선순위 값
+
+**현상**: 포트, 우선순위, 가중치 값이 비정상적으로 표시됨
+
+**원인**: 빅엔디안/리틀엔디안 바이트 순서 문제
+
+**상태**: 부분 해결
+
+## 향후 개선 사항
+
+1. [ ] NS/SRV 레코드 이름 파싱 정확도 개선
+2. [ ] Excel 다중 시트 출력 지원 (COM 또는 ImportExcel 모듈)
+3. [ ] 역방향 DNS (PTR) 대역 스캔 기능 추가
+4. [ ] 결과 비교 기능 (이전 스캔과 차이점 분석)
+5. [ ] HTML 리포트 생성 기능
+
+## 파일 구조
+
+```
+UDFX/
+├── Get-ADDnsRecords.ps1 # 메인 스크립트
+├── README.md # 사용자 매뉴얼
+├── DEVELOPMENT.md # 개발 명세서
+└── [출력 파일]
+ ├── dns_records.csv
+ ├── dns_records_root_domains.csv
+ ├── dns_records.json
+ └── dns_records.txt
+```
+
+## 참고 자료
+
+- [MS-DNSP: Domain Name Service Protocol](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/)
+- [AD DNS Record Binary Format](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/f97756c9-3783-428b-9451-b376f877f238)
+- [USFX - Ultimate Subdomain Finder X](https://github.com/devastator-x/usfx)
diff --git a/Get-ADDnsRecords.ps1 b/Get-ADDnsRecords.ps1
@@ -0,0 +1,378 @@
+<#
+.SYNOPSIS
+ UDFX - Ultimate Domain Finder X
+ AD 통합 DNS 레코드를 LDAP으로 직접 조회하는 에어갭 환경용 도구
+.DESCRIPTION
+ 도메인 사용자 권한으로 Active Directory에 저장된 DNS 레코드를 조회합니다.
+ 인터넷 연결 없이 에어갭 환경에서 사용 가능합니다.
+.EXAMPLE
+ .\Get-ADDnsRecords.ps1 -Domain corp.example.com
+ .\Get-ADDnsRecords.ps1 -Domain corp.example.com -Output results
+.NOTES
+ Version: 1.0.0
+ Author: UDFX Project
+#>
+
+param(
+ [Parameter(Mandatory=$true)]
+ [string]$Domain,
+
+ [string]$Output = "dns_records",
+
+ [switch]$ShowDebug
+)
+
+$banner = @"
+
+ __ ______ _________ __
+ / / / / __ \/ ____/ |/ /
+ / / / / / / / /_ | /
+ / /_/ / /_/ / __/ / |
+ \____/_____/_/ /_/|_|
+
+ ╔═══════════════════════════════════════════════════╗
+ ║ Ultimate Domain Finder X ║
+ ║ Air-Gap AD DNS Enumeration Tool v1.0 ║
+ ╠═══════════════════════════════════════════════════╣
+ ║ [*] LDAP-based AD DNS Record Extraction ║
+ ║ [*] No Internet Connection Required ║
+ ║ [*] Domain User Privileges Only ║
+ ╚═══════════════════════════════════════════════════╝
+
+"@
+
+Write-Host $banner -ForegroundColor Cyan
+
+# 루트 도메인 추출 함수
+function Get-RootDomain {
+ param([string]$domain)
+
+ $parts = $domain.Split(".")
+ if ($parts.Count -lt 2) { return $domain }
+
+ # .co.kr, .or.kr, .go.kr, .ac.kr 등 3단계 TLD 처리
+ if ($parts.Count -ge 3) {
+ $sld = $parts[-2]
+ $tld = $parts[-1]
+ if ($tld -eq "kr" -and $sld -match "^(co|or|go|ac|ne|re|pe|hs|ms|es|sc|kg)$") {
+ return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+ }
+ if ($tld -eq "uk" -and $sld -match "^(co|org|ac|gov)$") {
+ return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+ }
+ if ($tld -eq "jp" -and $sld -match "^(co|or|ac|go|ne)$") {
+ return "$($parts[-3]).$($parts[-2]).$($parts[-1])"
+ }
+ }
+
+ # 일반 도메인: example.com, example.io
+ return "$($parts[-2]).$($parts[-1])"
+}
+
+# DNS 이름 파싱 함수
+function Get-DnsNameFromRecord {
+ param(
+ [byte[]]$data,
+ [int]$offset
+ )
+
+ $nameParts = @()
+ $pos = $offset
+
+ try {
+ while ($pos -lt $data.Length) {
+ $len = $data[$pos]
+ if ($len -eq 0) { break }
+ if ($len -gt 63) { break }
+ if (($pos + 1 + $len) -gt $data.Length) { break }
+
+ $label = [System.Text.Encoding]::ASCII.GetString($data, $pos + 1, $len)
+ $nameParts += $label
+ $pos += $len + 1
+ }
+ } catch {
+ return "unknown"
+ }
+
+ if ($nameParts.Count -eq 0) { return "" }
+ return ($nameParts -join ".")
+}
+
+# DNS 레코드 변환 함수
+function Convert-DNSRecord {
+ param([byte[]]$RecordData)
+
+ if ($RecordData.Length -lt 24) { return $null }
+
+ $recordType = [BitConverter]::ToUInt16($RecordData, 2)
+
+ $typeName = switch ($recordType) {
+ 1 { "A" }
+ 2 { "NS" }
+ 5 { "CNAME" }
+ 6 { "SOA" }
+ 12 { "PTR" }
+ 15 { "MX" }
+ 16 { "TXT" }
+ 28 { "AAAA" }
+ 33 { "SRV" }
+ default { "TYPE$recordType" }
+ }
+
+ $result = @{
+ Type = $typeName
+ TypeId = $recordType
+ Data = ""
+ }
+
+ try {
+ switch ($recordType) {
+ 1 { # A Record
+ if ($RecordData.Length -ge 28) {
+ $ip = "{0}.{1}.{2}.{3}" -f $RecordData[24], $RecordData[25], $RecordData[26], $RecordData[27]
+ $result.Data = $ip
+ }
+ }
+ 28 { # AAAA Record
+ if ($RecordData.Length -ge 40) {
+ $ipv6Bytes = $RecordData[24..39]
+ $ip = [System.Net.IPAddress]::new($ipv6Bytes).ToString()
+ $result.Data = $ip
+ }
+ }
+ 2 { # NS Record
+ $result.Data = Get-DnsNameFromRecord $RecordData 24
+ }
+ 5 { # CNAME Record
+ $result.Data = Get-DnsNameFromRecord $RecordData 24
+ }
+ 12 { # PTR Record
+ $result.Data = Get-DnsNameFromRecord $RecordData 24
+ }
+ 15 { # MX Record
+ if ($RecordData.Length -ge 28) {
+ $priority = [BitConverter]::ToUInt16($RecordData, 24)
+ $exchange = Get-DnsNameFromRecord $RecordData 26
+ $result.Data = "[$priority] $exchange"
+ }
+ }
+ 6 { # SOA Record
+ $result.Data = Get-DnsNameFromRecord $RecordData 24
+ }
+ 16 { # TXT Record
+ if ($RecordData.Length -gt 24) {
+ $txtLen = $RecordData[24]
+ if ($txtLen -gt 0 -and $RecordData.Length -ge (25 + $txtLen)) {
+ $result.Data = [System.Text.Encoding]::ASCII.GetString($RecordData, 25, $txtLen)
+ }
+ }
+ }
+ 33 { # SRV Record
+ if ($RecordData.Length -ge 32) {
+ $priority = [BitConverter]::ToUInt16($RecordData, 24)
+ $weight = [BitConverter]::ToUInt16($RecordData, 26)
+ $port = [BitConverter]::ToUInt16($RecordData, 28)
+ $target = Get-DnsNameFromRecord $RecordData 30
+ $result.Data = "${target}:$port (pri:$priority wt:$weight)"
+ }
+ }
+ default {
+ $result.Data = "Binary (type:$recordType)"
+ }
+ }
+ } catch {
+ $result.Data = "Parse error"
+ }
+
+ return $result
+}
+
+# 메인 실행
+Write-Host "[*] Target Domain: $Domain" -ForegroundColor White
+Write-Host ""
+
+# 도메인 DN 생성
+$domainParts = $Domain.Split(".")
+$domainDN = ($domainParts | ForEach-Object { "DC=$_" }) -join ","
+
+Write-Host "[*] Searching for DNS Zones in Active Directory..." -ForegroundColor Cyan
+
+# DNS 영역 검색
+$zones = @()
+$searchBase = "LDAP://DC=DomainDnsZones,$domainDN"
+
+try {
+ $searcher = New-Object DirectoryServices.DirectorySearcher
+ $searcher.SearchRoot = [ADSI]$searchBase
+ $searcher.Filter = "(objectClass=dnsZone)"
+ $searcher.PageSize = 1000
+
+ $results = $searcher.FindAll()
+ foreach ($result in $results) {
+ $zoneName = $result.Properties["name"][0]
+ if ($zoneName -and $zoneName -ne "RootDNSServers") {
+ $zones += @{
+ Name = $zoneName
+ Path = $result.Path
+ }
+ }
+ }
+} catch {
+ Write-Host "[!] Error accessing DNS zones: $_" -ForegroundColor Red
+ exit 1
+}
+
+if ($zones.Count -eq 0) {
+ Write-Host "[!] No DNS zones found." -ForegroundColor Red
+ exit 1
+}
+
+Write-Host "[+] Found $($zones.Count) DNS zone(s)" -ForegroundColor Green
+Write-Host ""
+
+# 모든 레코드 수집
+$allRecords = @()
+
+foreach ($zone in $zones) {
+ Write-Host "[*] Dumping: $($zone.Name)" -ForegroundColor Cyan
+
+ try {
+ $zoneSearcher = New-Object DirectoryServices.DirectorySearcher
+ $zoneSearcher.SearchRoot = [ADSI]$zone.Path
+ $zoneSearcher.Filter = "(objectClass=dnsNode)"
+ $zoneSearcher.PageSize = 1000
+ $zoneSearcher.PropertiesToLoad.AddRange(@("name", "dnsRecord"))
+
+ $nodeResults = $zoneSearcher.FindAll()
+ $zoneRecordCount = 0
+
+ foreach ($node in $nodeResults) {
+ $nodeName = $node.Properties["name"][0]
+ $dnsRecords = $node.Properties["dnsRecord"]
+
+ if ($nodeName -eq "@") {
+ $fqdn = $zone.Name
+ } else {
+ $fqdn = "$nodeName.$($zone.Name)"
+ }
+
+ foreach ($recordData in $dnsRecords) {
+ $parsed = Convert-DNSRecord -RecordData $recordData
+ if ($parsed -and $parsed.Data -and $parsed.Type -ne "SOA") {
+ # Zone 유형 분류
+ $zoneType = "External"
+ if ($zone.Name -eq $Domain) {
+ $zoneType = "Primary"
+ } elseif ($zone.Name.EndsWith(".$Domain")) {
+ $zoneType = "Subdomain"
+ }
+
+ # 루트 도메인 추출
+ $rootDomain = Get-RootDomain $zone.Name
+
+ $record = [PSCustomObject]@{
+ Domain = $fqdn
+ RecordType = $parsed.Type
+ Value = $parsed.Data
+ Zone = $zone.Name
+ ZoneType = $zoneType
+ RootDomain = $rootDomain
+ }
+ $allRecords += $record
+ $zoneRecordCount++
+
+ if ($ShowDebug) {
+ Write-Host " [$($parsed.Type)] $fqdn -> $($parsed.Data)" -ForegroundColor Gray
+ }
+ }
+ }
+ }
+
+ Write-Host " Found $zoneRecordCount records" -ForegroundColor Gray
+
+ } catch {
+ Write-Host " [!] Error: $_" -ForegroundColor Red
+ }
+}
+
+Write-Host ""
+Write-Host "[*] Saving results..." -ForegroundColor Cyan
+
+# JSON 출력
+$jsonOutput = @{
+ Target = $Domain
+ ScanTime = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
+ TotalRecords = $allRecords.Count
+ ZoneCount = $zones.Count
+ Zones = $zones | ForEach-Object { $_.Name }
+ Records = $allRecords
+} | ConvertTo-Json -Depth 10
+$jsonOutput | Out-File -FilePath "$Output.json" -Encoding UTF8
+
+# CSV 출력
+$allRecords | Export-Csv -Path "$Output.csv" -NoTypeInformation -Encoding UTF8
+
+# Root Domain CSV 출력 (중복 제거)
+$uniqueRootDomains = $allRecords | Select-Object -ExpandProperty RootDomain -Unique | Sort-Object | ForEach-Object {
+ [PSCustomObject]@{
+ RootDomain = $_
+ }
+}
+$uniqueRootDomains | Export-Csv -Path "${Output}_root_domains.csv" -NoTypeInformation -Encoding UTF8
+
+# TXT 출력
+$txtContent = @"
+# AD DNS Record Dump
+# Target: $Domain
+# Time: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
+# Total Records: $($allRecords.Count)
+# Zones: $($zones.Count)
+#
+# Format: RootDomain | ZoneType | Type | Domain | Value | Zone
+# =============================================================
+
+"@
+foreach ($record in $allRecords) {
+ $txtContent += "$($record.RootDomain) | $($record.ZoneType) | $($record.RecordType) | $($record.Domain) | $($record.Value) | $($record.Zone)`n"
+}
+$txtContent | Out-File -FilePath "$Output.txt" -Encoding UTF8
+
+Write-Host ""
+Write-Host "========== SCAN COMPLETE ==========" -ForegroundColor Green
+Write-Host "Total Zones: $($zones.Count)" -ForegroundColor White
+Write-Host "Total Records: $($allRecords.Count)" -ForegroundColor White
+Write-Host ""
+Write-Host "Results saved to:" -ForegroundColor White
+Write-Host " - $Output.json" -ForegroundColor Cyan
+Write-Host " - $Output.csv" -ForegroundColor Cyan
+Write-Host " - ${Output}_root_domains.csv (unique root domains)" -ForegroundColor Cyan
+Write-Host " - $Output.txt" -ForegroundColor Cyan
+Write-Host "===================================" -ForegroundColor Green
+
+# 루트 도메인 목록
+Write-Host ""
+Write-Host "Root Domains Found:" -ForegroundColor White
+$allRecords | Select-Object -ExpandProperty RootDomain -Unique | Sort-Object | ForEach-Object {
+ Write-Host " $_" -ForegroundColor Gray
+}
+
+# Zone 유형별 통계
+Write-Host ""
+Write-Host "Records by Zone Type:" -ForegroundColor White
+$allRecords | Group-Object ZoneType | Sort-Object Count -Descending | ForEach-Object {
+ Write-Host " $($_.Name): $($_.Count)" -ForegroundColor Gray
+}
+
+# 레코드 타입별 통계
+Write-Host ""
+Write-Host "Records by Record Type:" -ForegroundColor White
+$allRecords | Group-Object RecordType | Sort-Object Count -Descending | ForEach-Object {
+ Write-Host " $($_.Name): $($_.Count)" -ForegroundColor Gray
+}
+
+# 상위 도메인 출력
+Write-Host ""
+Write-Host "Sample Records (first 20):" -ForegroundColor White
+$allRecords | Select-Object -First 20 | ForEach-Object {
+ Write-Host " [$($_.RecordType)] $($_.Domain) -> $($_.Value)" -ForegroundColor Gray
+}
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 UDFX Project
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
@@ -0,0 +1,119 @@
+# UDFX - Ultimate Domain Finder X
+
+Active Directory 통합 DNS에서 도메인 및 DNS 레코드를 수집하는 에어갭 환경용 도구입니다.
+
+## 개요
+
+- **목적**: AD DNS에 등록된 모든 도메인/서브도메인 및 레코드 수집
+- **환경**: Windows 도메인 환경 (에어갭 지원)
+- **권한**: 일반 도메인 사용자 권한으로 실행 가능
+- **방식**: LDAP을 통한 AD DNS 직접 조회
+
+## 요구사항
+
+- Windows PowerShell 5.1 이상
+- Active Directory 도메인 가입된 시스템
+- 도메인 사용자 계정
+
+## 사용법
+
+### 기본 실행
+
+```powershell
+.\Get-ADDnsRecords.ps1 -Domain <도메인명>
+```
+
+### 예시
+
+```powershell
+# 기본 실행
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com
+
+# 출력 파일명 지정
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com -Output scan_results
+
+# 디버그 모드 (상세 출력)
+.\Get-ADDnsRecords.ps1 -Domain corp.example.com -ShowDebug
+```
+
+### 파라미터
+
+| 파라미터 | 필수 | 설명 | 기본값 |
+|----------|------|------|--------|
+| `-Domain` | O | 대상 AD 도메인명 | - |
+| `-Output` | X | 출력 파일 기본명 | dns_records |
+| `-ShowDebug` | X | 상세 출력 활성화 | False |
+
+## 출력 파일
+
+| 파일 | 설명 |
+|------|------|
+| `dns_records.csv` | 전체 DNS 레코드 (CSV) |
+| `dns_records_root_domains.csv` | 루트 도메인 목록 (중복 제거) |
+| `dns_records.json` | 전체 DNS 레코드 (JSON) |
+| `dns_records.txt` | 전체 DNS 레코드 (텍스트) |
+
+## 출력 필드
+
+| 필드 | 설명 | 예시 |
+|------|------|------|
+| Domain | FQDN | vcsa.example.com |
+| RecordType | DNS 레코드 타입 | A, NS, CNAME, MX, SRV, TXT |
+| Value | 레코드 값 | 10.1.10.100 |
+| Zone | DNS 영역명 | vcsa.example.com |
+| ZoneType | 영역 분류 | Primary, Subdomain, External |
+| RootDomain | 루트 도메인 | example.com |
+
+### ZoneType 분류
+
+| 타입 | 설명 |
+|------|------|
+| Primary | 메인 AD 도메인 |
+| Subdomain | 메인 도메인의 서브도메인 |
+| External | 외부 도메인 |
+
+## 지원 레코드 타입
+
+- **A**: IPv4 주소
+- **AAAA**: IPv6 주소
+- **NS**: 네임서버
+- **CNAME**: 별칭
+- **MX**: 메일 서버
+- **SRV**: 서비스 레코드
+- **TXT**: 텍스트 레코드
+- **PTR**: 역방향 DNS
+
+## 활용 예시
+
+### 내부 IP 호스트만 필터링
+
+```powershell
+Import-Csv .\dns_records.csv | Where-Object {
+ $_.RecordType -eq "A" -and
+ ($_.Value -match "^10\." -or $_.Value -match "^172\.(1[6-9]|2[0-9]|3[01])\." -or $_.Value -match "^192\.168\.")
+} | Export-Csv .\internal_hosts.csv -NoTypeInformation
+```
+
+### 특정 도메인만 필터링
+
+```powershell
+Import-Csv .\dns_records.csv | Where-Object {
+ $_.RootDomain -eq "example.com"
+} | Export-Csv .\filtered_records.csv -NoTypeInformation
+```
+
+### 루트 도메인 목록 확인
+
+```powershell
+Import-Csv .\dns_records_root_domains.csv
+```
+
+## 제한사항
+
+- AD 통합 DNS만 지원 (독립 DNS 서버 미지원)
+- NS, SRV 레코드의 대상 호스트명에 점(.)이 누락될 수 있음
+- Zone Transfer가 허용되지 않은 환경에서는 LDAP 방식으로 대체
+
+## 라이선스
+
+MIT License
|