forked from Snider/Poindexter
feat: Add extended DNS record types (ClouDNS compatible)
- Add support for 13 additional record types: ALIAS, RP, SSHFP, TLSA, DS, DNSKEY, NAPTR, LOC, HINFO, CERT, SMIMEA, WR (Web Redirect), SPF - Add GetDNSRecordTypeInfo() for metadata with RFC references - Add GetCommonDNSRecordTypes() for commonly used types - Add structured types for CAA, SSHFP, TLSA, DS, DNSKEY, NAPTR, RP, LOC, ALIAS, and WebRedirect records - Export new functions in WASM bindings - Update TypeScript definitions and loader.js - Add comprehensive tests for new record types
This commit is contained in:
parent
d96c9f266c
commit
298791ef95
5 changed files with 573 additions and 7 deletions
156
dns_tools.go
156
dns_tools.go
|
|
@ -21,6 +21,7 @@ import (
|
|||
type DNSRecordType string
|
||||
|
||||
const (
|
||||
// Standard record types
|
||||
DNSRecordA DNSRecordType = "A"
|
||||
DNSRecordAAAA DNSRecordType = "AAAA"
|
||||
DNSRecordMX DNSRecordType = "MX"
|
||||
|
|
@ -31,6 +32,21 @@ const (
|
|||
DNSRecordPTR DNSRecordType = "PTR"
|
||||
DNSRecordSRV DNSRecordType = "SRV"
|
||||
DNSRecordCAA DNSRecordType = "CAA"
|
||||
|
||||
// Additional record types (ClouDNS and others)
|
||||
DNSRecordALIAS DNSRecordType = "ALIAS" // Virtual ANAME record (ClouDNS, Route53, etc.)
|
||||
DNSRecordRP DNSRecordType = "RP" // Responsible Person
|
||||
DNSRecordSSHFP DNSRecordType = "SSHFP" // SSH Fingerprint
|
||||
DNSRecordTLSA DNSRecordType = "TLSA" // DANE TLS Authentication
|
||||
DNSRecordDS DNSRecordType = "DS" // DNSSEC Delegation Signer
|
||||
DNSRecordDNSKEY DNSRecordType = "DNSKEY" // DNSSEC Key
|
||||
DNSRecordNAPTR DNSRecordType = "NAPTR" // Naming Authority Pointer
|
||||
DNSRecordLOC DNSRecordType = "LOC" // Geographic Location
|
||||
DNSRecordHINFO DNSRecordType = "HINFO" // Host Information
|
||||
DNSRecordCERT DNSRecordType = "CERT" // Certificate record
|
||||
DNSRecordSMIMEA DNSRecordType = "SMIMEA" // S/MIME Certificate Association
|
||||
DNSRecordWR DNSRecordType = "WR" // Web Redirect (ClouDNS specific)
|
||||
DNSRecordSPF DNSRecordType = "SPF" // Sender Policy Framework (legacy, use TXT)
|
||||
)
|
||||
|
||||
// DNSRecord represents a generic DNS record
|
||||
|
|
@ -66,6 +82,146 @@ type SOARecord struct {
|
|||
MinTTL uint32 `json:"minTtl"`
|
||||
}
|
||||
|
||||
// CAARecord represents a CAA record
|
||||
type CAARecord struct {
|
||||
Flag uint8 `json:"flag"`
|
||||
Tag string `json:"tag"` // "issue", "issuewild", "iodef"
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// SSHFPRecord represents an SSHFP record
|
||||
type SSHFPRecord struct {
|
||||
Algorithm uint8 `json:"algorithm"` // 1=RSA, 2=DSA, 3=ECDSA, 4=Ed25519
|
||||
FPType uint8 `json:"fpType"` // 1=SHA-1, 2=SHA-256
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
}
|
||||
|
||||
// TLSARecord represents a TLSA (DANE) record
|
||||
type TLSARecord struct {
|
||||
Usage uint8 `json:"usage"` // 0-3: CA constraint, Service cert, Trust anchor, Domain-issued
|
||||
Selector uint8 `json:"selector"` // 0=Full cert, 1=SubjectPublicKeyInfo
|
||||
MatchingType uint8 `json:"matchingType"` // 0=Exact, 1=SHA-256, 2=SHA-512
|
||||
CertData string `json:"certData"`
|
||||
}
|
||||
|
||||
// DSRecord represents a DS (DNSSEC Delegation Signer) record
|
||||
type DSRecord struct {
|
||||
KeyTag uint16 `json:"keyTag"`
|
||||
Algorithm uint8 `json:"algorithm"`
|
||||
DigestType uint8 `json:"digestType"`
|
||||
Digest string `json:"digest"`
|
||||
}
|
||||
|
||||
// DNSKEYRecord represents a DNSKEY record
|
||||
type DNSKEYRecord struct {
|
||||
Flags uint16 `json:"flags"`
|
||||
Protocol uint8 `json:"protocol"`
|
||||
Algorithm uint8 `json:"algorithm"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
}
|
||||
|
||||
// NAPTRRecord represents a NAPTR record
|
||||
type NAPTRRecord struct {
|
||||
Order uint16 `json:"order"`
|
||||
Preference uint16 `json:"preference"`
|
||||
Flags string `json:"flags"`
|
||||
Service string `json:"service"`
|
||||
Regexp string `json:"regexp"`
|
||||
Replacement string `json:"replacement"`
|
||||
}
|
||||
|
||||
// RPRecord represents an RP (Responsible Person) record
|
||||
type RPRecord struct {
|
||||
Mailbox string `json:"mailbox"` // Email as DNS name (user.domain.com)
|
||||
TxtDom string `json:"txtDom"` // Domain with TXT record containing more info
|
||||
}
|
||||
|
||||
// LOCRecord represents a LOC (Location) record
|
||||
type LOCRecord struct {
|
||||
Latitude float64 `json:"latitude"`
|
||||
Longitude float64 `json:"longitude"`
|
||||
Altitude float64 `json:"altitude"`
|
||||
Size float64 `json:"size"`
|
||||
HPrecis float64 `json:"hPrecision"`
|
||||
VPrecis float64 `json:"vPrecision"`
|
||||
}
|
||||
|
||||
// ALIASRecord represents an ALIAS/ANAME record (provider-specific)
|
||||
type ALIASRecord struct {
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
// WebRedirectRecord represents a Web Redirect record (ClouDNS specific)
|
||||
type WebRedirectRecord struct {
|
||||
URL string `json:"url"`
|
||||
RedirectType int `json:"redirectType"` // 301, 302, etc.
|
||||
Frame bool `json:"frame"` // Frame redirect vs HTTP redirect
|
||||
}
|
||||
|
||||
// DNSRecordTypeInfo provides metadata about a DNS record type
|
||||
type DNSRecordTypeInfo struct {
|
||||
Type DNSRecordType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
RFC string `json:"rfc,omitempty"`
|
||||
Common bool `json:"common"` // Commonly used record type
|
||||
}
|
||||
|
||||
// GetDNSRecordTypeInfo returns metadata for all supported DNS record types
|
||||
func GetDNSRecordTypeInfo() []DNSRecordTypeInfo {
|
||||
return []DNSRecordTypeInfo{
|
||||
// Common record types
|
||||
{DNSRecordA, "A", "IPv4 address record - maps hostname to IPv4", "RFC 1035", true},
|
||||
{DNSRecordAAAA, "AAAA", "IPv6 address record - maps hostname to IPv6", "RFC 3596", true},
|
||||
{DNSRecordCNAME, "CNAME", "Canonical name - alias to another domain", "RFC 1035", true},
|
||||
{DNSRecordMX, "MX", "Mail exchanger - specifies mail servers", "RFC 1035", true},
|
||||
{DNSRecordTXT, "TXT", "Text record - stores arbitrary text (SPF, DKIM, etc.)", "RFC 1035", true},
|
||||
{DNSRecordNS, "NS", "Nameserver - delegates DNS zone to nameservers", "RFC 1035", true},
|
||||
{DNSRecordSOA, "SOA", "Start of Authority - zone administration data", "RFC 1035", true},
|
||||
{DNSRecordPTR, "PTR", "Pointer - reverse DNS lookup (IP to hostname)", "RFC 1035", true},
|
||||
{DNSRecordSRV, "SRV", "Service - locates services (port, priority, weight)", "RFC 2782", true},
|
||||
{DNSRecordCAA, "CAA", "Certification Authority Authorization", "RFC 6844", true},
|
||||
|
||||
// Additional/specialized record types
|
||||
{DNSRecordALIAS, "ALIAS", "Virtual A record - CNAME-like for apex domain", "", true},
|
||||
{DNSRecordRP, "RP", "Responsible Person - contact info for domain", "RFC 1183", false},
|
||||
{DNSRecordSSHFP, "SSHFP", "SSH Fingerprint - SSH host key verification", "RFC 4255", false},
|
||||
{DNSRecordTLSA, "TLSA", "DANE TLS Authentication - certificate pinning", "RFC 6698", false},
|
||||
{DNSRecordDS, "DS", "Delegation Signer - DNSSEC chain of trust", "RFC 4034", false},
|
||||
{DNSRecordDNSKEY, "DNSKEY", "DNSSEC public key", "RFC 4034", false},
|
||||
{DNSRecordNAPTR, "NAPTR", "Naming Authority Pointer - ENUM, SIP routing", "RFC 2915", false},
|
||||
{DNSRecordLOC, "LOC", "Location - geographic coordinates", "RFC 1876", false},
|
||||
{DNSRecordHINFO, "HINFO", "Host Information - CPU and OS type", "RFC 1035", false},
|
||||
{DNSRecordCERT, "CERT", "Certificate - stores certificates", "RFC 4398", false},
|
||||
{DNSRecordSMIMEA, "SMIMEA", "S/MIME Certificate Association", "RFC 8162", false},
|
||||
{DNSRecordSPF, "SPF", "Sender Policy Framework (legacy, use TXT)", "RFC 4408", false},
|
||||
{DNSRecordWR, "WR", "Web Redirect - HTTP redirect (ClouDNS specific)", "", false},
|
||||
}
|
||||
}
|
||||
|
||||
// GetCommonDNSRecordTypes returns only commonly used record types
|
||||
func GetCommonDNSRecordTypes() []DNSRecordType {
|
||||
info := GetDNSRecordTypeInfo()
|
||||
result := make([]DNSRecordType, 0)
|
||||
for _, r := range info {
|
||||
if r.Common {
|
||||
result = append(result, r.Type)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAllDNSRecordTypes returns all supported record types
|
||||
func GetAllDNSRecordTypes() []DNSRecordType {
|
||||
return []DNSRecordType{
|
||||
DNSRecordA, DNSRecordAAAA, DNSRecordCNAME, DNSRecordMX, DNSRecordTXT,
|
||||
DNSRecordNS, DNSRecordSOA, DNSRecordPTR, DNSRecordSRV, DNSRecordCAA,
|
||||
DNSRecordALIAS, DNSRecordRP, DNSRecordSSHFP, DNSRecordTLSA, DNSRecordDS,
|
||||
DNSRecordDNSKEY, DNSRecordNAPTR, DNSRecordLOC, DNSRecordHINFO, DNSRecordCERT,
|
||||
DNSRecordSMIMEA, DNSRecordSPF, DNSRecordWR,
|
||||
}
|
||||
}
|
||||
|
||||
// DNSLookupResult contains the results of a DNS lookup
|
||||
type DNSLookupResult struct {
|
||||
Domain string `json:"domain"`
|
||||
|
|
|
|||
|
|
@ -156,6 +156,136 @@ func TestDNSRecordTypes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDNSRecordTypesExtended(t *testing.T) {
|
||||
// Test all ClouDNS record types are defined
|
||||
types := []DNSRecordType{
|
||||
DNSRecordALIAS,
|
||||
DNSRecordRP,
|
||||
DNSRecordSSHFP,
|
||||
DNSRecordTLSA,
|
||||
DNSRecordDS,
|
||||
DNSRecordDNSKEY,
|
||||
DNSRecordNAPTR,
|
||||
DNSRecordLOC,
|
||||
DNSRecordHINFO,
|
||||
DNSRecordCERT,
|
||||
DNSRecordSMIMEA,
|
||||
DNSRecordWR,
|
||||
DNSRecordSPF,
|
||||
}
|
||||
|
||||
expected := []string{"ALIAS", "RP", "SSHFP", "TLSA", "DS", "DNSKEY", "NAPTR", "LOC", "HINFO", "CERT", "SMIMEA", "WR", "SPF"}
|
||||
|
||||
for i, typ := range types {
|
||||
if string(typ) != expected[i] {
|
||||
t.Errorf("expected type %s, got %s", expected[i], typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDNSRecordTypeInfo(t *testing.T) {
|
||||
info := GetDNSRecordTypeInfo()
|
||||
|
||||
if len(info) == 0 {
|
||||
t.Error("GetDNSRecordTypeInfo should return non-empty list")
|
||||
}
|
||||
|
||||
// Check that common types exist
|
||||
commonFound := 0
|
||||
for _, r := range info {
|
||||
if r.Common {
|
||||
commonFound++
|
||||
}
|
||||
// Each entry should have type, name, and description
|
||||
if r.Type == "" {
|
||||
t.Error("Record type should not be empty")
|
||||
}
|
||||
if r.Name == "" {
|
||||
t.Error("Record name should not be empty")
|
||||
}
|
||||
if r.Description == "" {
|
||||
t.Error("Record description should not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
if commonFound < 10 {
|
||||
t.Errorf("Expected at least 10 common record types, got %d", commonFound)
|
||||
}
|
||||
|
||||
// Check for specific types
|
||||
typeMap := make(map[DNSRecordType]DNSRecordTypeInfo)
|
||||
for _, r := range info {
|
||||
typeMap[r.Type] = r
|
||||
}
|
||||
|
||||
if _, ok := typeMap[DNSRecordA]; !ok {
|
||||
t.Error("A record type should be in info")
|
||||
}
|
||||
if _, ok := typeMap[DNSRecordALIAS]; !ok {
|
||||
t.Error("ALIAS record type should be in info")
|
||||
}
|
||||
if _, ok := typeMap[DNSRecordTLSA]; !ok {
|
||||
t.Error("TLSA record type should be in info")
|
||||
}
|
||||
if _, ok := typeMap[DNSRecordWR]; !ok {
|
||||
t.Error("WR (Web Redirect) record type should be in info")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCommonDNSRecordTypes(t *testing.T) {
|
||||
types := GetCommonDNSRecordTypes()
|
||||
|
||||
if len(types) == 0 {
|
||||
t.Error("GetCommonDNSRecordTypes should return non-empty list")
|
||||
}
|
||||
|
||||
// Check that standard types are present
|
||||
typeSet := make(map[DNSRecordType]bool)
|
||||
for _, typ := range types {
|
||||
typeSet[typ] = true
|
||||
}
|
||||
|
||||
if !typeSet[DNSRecordA] {
|
||||
t.Error("A record should be in common types")
|
||||
}
|
||||
if !typeSet[DNSRecordAAAA] {
|
||||
t.Error("AAAA record should be in common types")
|
||||
}
|
||||
if !typeSet[DNSRecordMX] {
|
||||
t.Error("MX record should be in common types")
|
||||
}
|
||||
if !typeSet[DNSRecordTXT] {
|
||||
t.Error("TXT record should be in common types")
|
||||
}
|
||||
if !typeSet[DNSRecordALIAS] {
|
||||
t.Error("ALIAS record should be in common types")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllDNSRecordTypes(t *testing.T) {
|
||||
types := GetAllDNSRecordTypes()
|
||||
|
||||
if len(types) < 20 {
|
||||
t.Errorf("GetAllDNSRecordTypes should return at least 20 types, got %d", len(types))
|
||||
}
|
||||
|
||||
// Check for ClouDNS-specific types
|
||||
typeSet := make(map[DNSRecordType]bool)
|
||||
for _, typ := range types {
|
||||
typeSet[typ] = true
|
||||
}
|
||||
|
||||
if !typeSet[DNSRecordWR] {
|
||||
t.Error("WR (Web Redirect) should be in all types")
|
||||
}
|
||||
if !typeSet[DNSRecordNAPTR] {
|
||||
t.Error("NAPTR should be in all types")
|
||||
}
|
||||
if !typeSet[DNSRecordDS] {
|
||||
t.Error("DS should be in all types")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSLookupResultStructure(t *testing.T) {
|
||||
result := DNSLookupResult{
|
||||
Domain: "example.com",
|
||||
|
|
@ -400,6 +530,141 @@ func TestSOARecordStructure(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Extended Record Type Structure Tests
|
||||
// ============================================================================
|
||||
|
||||
func TestCAARecordStructure(t *testing.T) {
|
||||
caa := CAARecord{
|
||||
Flag: 0,
|
||||
Tag: "issue",
|
||||
Value: "letsencrypt.org",
|
||||
}
|
||||
|
||||
if caa.Tag != "issue" {
|
||||
t.Error("Tag should be 'issue'")
|
||||
}
|
||||
if caa.Value != "letsencrypt.org" {
|
||||
t.Error("Value should be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSSHFPRecordStructure(t *testing.T) {
|
||||
sshfp := SSHFPRecord{
|
||||
Algorithm: 4, // Ed25519
|
||||
FPType: 2, // SHA-256
|
||||
Fingerprint: "abc123def456",
|
||||
}
|
||||
|
||||
if sshfp.Algorithm != 4 {
|
||||
t.Error("Algorithm should be 4 (Ed25519)")
|
||||
}
|
||||
if sshfp.FPType != 2 {
|
||||
t.Error("FPType should be 2 (SHA-256)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTLSARecordStructure(t *testing.T) {
|
||||
tlsa := TLSARecord{
|
||||
Usage: 3, // Domain-issued certificate
|
||||
Selector: 1, // SubjectPublicKeyInfo
|
||||
MatchingType: 1, // SHA-256
|
||||
CertData: "abcd1234",
|
||||
}
|
||||
|
||||
if tlsa.Usage != 3 {
|
||||
t.Error("Usage should be 3")
|
||||
}
|
||||
if tlsa.Selector != 1 {
|
||||
t.Error("Selector should be 1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDSRecordStructure(t *testing.T) {
|
||||
ds := DSRecord{
|
||||
KeyTag: 12345,
|
||||
Algorithm: 13, // ECDSAP256SHA256
|
||||
DigestType: 2, // SHA-256
|
||||
Digest: "deadbeef",
|
||||
}
|
||||
|
||||
if ds.KeyTag != 12345 {
|
||||
t.Error("KeyTag should be 12345")
|
||||
}
|
||||
if ds.Algorithm != 13 {
|
||||
t.Error("Algorithm should be 13")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNAPTRRecordStructure(t *testing.T) {
|
||||
naptr := NAPTRRecord{
|
||||
Order: 100,
|
||||
Preference: 10,
|
||||
Flags: "U",
|
||||
Service: "E2U+sip",
|
||||
Regexp: "!^.*$!sip:info@example.com!",
|
||||
Replacement: ".",
|
||||
}
|
||||
|
||||
if naptr.Order != 100 {
|
||||
t.Error("Order should be 100")
|
||||
}
|
||||
if naptr.Service != "E2U+sip" {
|
||||
t.Error("Service should be E2U+sip")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRPRecordStructure(t *testing.T) {
|
||||
rp := RPRecord{
|
||||
Mailbox: "admin.example.com",
|
||||
TxtDom: "info.example.com",
|
||||
}
|
||||
|
||||
if rp.Mailbox != "admin.example.com" {
|
||||
t.Error("Mailbox should be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLOCRecordStructure(t *testing.T) {
|
||||
loc := LOCRecord{
|
||||
Latitude: 51.5074,
|
||||
Longitude: -0.1278,
|
||||
Altitude: 11,
|
||||
Size: 10,
|
||||
HPrecis: 10,
|
||||
VPrecis: 10,
|
||||
}
|
||||
|
||||
if loc.Latitude < 51.5 || loc.Latitude > 51.6 {
|
||||
t.Error("Latitude should be near 51.5074")
|
||||
}
|
||||
}
|
||||
|
||||
func TestALIASRecordStructure(t *testing.T) {
|
||||
alias := ALIASRecord{
|
||||
Target: "target.example.com",
|
||||
}
|
||||
|
||||
if alias.Target != "target.example.com" {
|
||||
t.Error("Target should be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebRedirectRecordStructure(t *testing.T) {
|
||||
wr := WebRedirectRecord{
|
||||
URL: "https://www.example.com",
|
||||
RedirectType: 301,
|
||||
Frame: false,
|
||||
}
|
||||
|
||||
if wr.URL != "https://www.example.com" {
|
||||
t.Error("URL should be set")
|
||||
}
|
||||
if wr.RedirectType != 301 {
|
||||
t.Error("RedirectType should be 301")
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Function Tests
|
||||
// ============================================================================
|
||||
|
|
|
|||
116
npm/poindexter-wasm/index.d.ts
vendored
116
npm/poindexter-wasm/index.d.ts
vendored
|
|
@ -193,8 +193,118 @@ export interface InitOptions {
|
|||
// DNS Tools Types
|
||||
// ============================================================================
|
||||
|
||||
/** DNS record types */
|
||||
export type DNSRecordType = 'A' | 'AAAA' | 'MX' | 'TXT' | 'NS' | 'CNAME' | 'SOA' | 'PTR' | 'SRV' | 'CAA';
|
||||
/** DNS record types - standard and extended (ClouDNS compatible) */
|
||||
export type DNSRecordType =
|
||||
// Standard record types
|
||||
| 'A'
|
||||
| 'AAAA'
|
||||
| 'MX'
|
||||
| 'TXT'
|
||||
| 'NS'
|
||||
| 'CNAME'
|
||||
| 'SOA'
|
||||
| 'PTR'
|
||||
| 'SRV'
|
||||
| 'CAA'
|
||||
// Additional record types (ClouDNS and others)
|
||||
| 'ALIAS' // Virtual A record - CNAME-like for apex domain
|
||||
| 'RP' // Responsible Person
|
||||
| 'SSHFP' // SSH Fingerprint
|
||||
| 'TLSA' // DANE TLS Authentication
|
||||
| 'DS' // DNSSEC Delegation Signer
|
||||
| 'DNSKEY' // DNSSEC Key
|
||||
| 'NAPTR' // Naming Authority Pointer
|
||||
| 'LOC' // Geographic Location
|
||||
| 'HINFO' // Host Information
|
||||
| 'CERT' // Certificate record
|
||||
| 'SMIMEA' // S/MIME Certificate Association
|
||||
| 'WR' // Web Redirect (ClouDNS specific)
|
||||
| 'SPF'; // Sender Policy Framework (legacy)
|
||||
|
||||
/** DNS record type metadata */
|
||||
export interface DNSRecordTypeInfo {
|
||||
type: DNSRecordType;
|
||||
name: string;
|
||||
description: string;
|
||||
rfc?: string;
|
||||
common: boolean;
|
||||
}
|
||||
|
||||
/** CAA record */
|
||||
export interface CAARecord {
|
||||
flag: number;
|
||||
tag: string; // "issue", "issuewild", "iodef"
|
||||
value: string;
|
||||
}
|
||||
|
||||
/** SSHFP record */
|
||||
export interface SSHFPRecord {
|
||||
algorithm: number; // 1=RSA, 2=DSA, 3=ECDSA, 4=Ed25519
|
||||
fpType: number; // 1=SHA-1, 2=SHA-256
|
||||
fingerprint: string;
|
||||
}
|
||||
|
||||
/** TLSA (DANE) record */
|
||||
export interface TLSARecord {
|
||||
usage: number; // 0-3: CA constraint, Service cert, Trust anchor, Domain-issued
|
||||
selector: number; // 0=Full cert, 1=SubjectPublicKeyInfo
|
||||
matchingType: number; // 0=Exact, 1=SHA-256, 2=SHA-512
|
||||
certData: string;
|
||||
}
|
||||
|
||||
/** DS (DNSSEC Delegation Signer) record */
|
||||
export interface DSRecord {
|
||||
keyTag: number;
|
||||
algorithm: number;
|
||||
digestType: number;
|
||||
digest: string;
|
||||
}
|
||||
|
||||
/** DNSKEY record */
|
||||
export interface DNSKEYRecord {
|
||||
flags: number;
|
||||
protocol: number;
|
||||
algorithm: number;
|
||||
publicKey: string;
|
||||
}
|
||||
|
||||
/** NAPTR record */
|
||||
export interface NAPTRRecord {
|
||||
order: number;
|
||||
preference: number;
|
||||
flags: string;
|
||||
service: string;
|
||||
regexp: string;
|
||||
replacement: string;
|
||||
}
|
||||
|
||||
/** RP (Responsible Person) record */
|
||||
export interface RPRecord {
|
||||
mailbox: string; // Email as DNS name (user.domain.com)
|
||||
txtDom: string; // Domain with TXT record containing more info
|
||||
}
|
||||
|
||||
/** LOC (Location) record */
|
||||
export interface LOCRecord {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
altitude: number;
|
||||
size: number;
|
||||
hPrecision: number;
|
||||
vPrecision: number;
|
||||
}
|
||||
|
||||
/** ALIAS record (provider-specific) */
|
||||
export interface ALIASRecord {
|
||||
target: string;
|
||||
}
|
||||
|
||||
/** Web Redirect record (ClouDNS specific) */
|
||||
export interface WebRedirectRecord {
|
||||
url: string;
|
||||
redirectType: number; // 301, 302, etc.
|
||||
frame: boolean; // Frame redirect vs HTTP redirect
|
||||
}
|
||||
|
||||
/** External tool links for domain/IP/email analysis */
|
||||
export interface ExternalToolLinks {
|
||||
|
|
@ -429,6 +539,8 @@ export interface PxAPI {
|
|||
buildRDAPIPURL(ip: string): Promise<string>;
|
||||
buildRDAPASNURL(asn: string): Promise<string>;
|
||||
getDNSRecordTypes(): Promise<DNSRecordType[]>;
|
||||
getDNSRecordTypeInfo(): Promise<DNSRecordTypeInfo[]>;
|
||||
getCommonDNSRecordTypes(): Promise<DNSRecordType[]>;
|
||||
}
|
||||
|
||||
export function init(options?: InitOptions): Promise<PxAPI>;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,9 @@ export async function init(options = {}) {
|
|||
buildRDAPDomainURL: async (domain) => call('pxBuildRDAPDomainURL', domain),
|
||||
buildRDAPIPURL: async (ip) => call('pxBuildRDAPIPURL', ip),
|
||||
buildRDAPASNURL: async (asn) => call('pxBuildRDAPASNURL', asn),
|
||||
getDNSRecordTypes: async () => call('pxGetDNSRecordTypes')
|
||||
getDNSRecordTypes: async () => call('pxGetDNSRecordTypes'),
|
||||
getDNSRecordTypeInfo: async () => call('pxGetDNSRecordTypeInfo'),
|
||||
getCommonDNSRecordTypes: async () => call('pxGetCommonDNSRecordTypes')
|
||||
};
|
||||
|
||||
return api;
|
||||
|
|
|
|||
39
wasm/main.go
39
wasm/main.go
|
|
@ -664,10 +664,39 @@ func buildRDAPASNURL(_ js.Value, args []js.Value) (any, error) {
|
|||
}
|
||||
|
||||
func getDNSRecordTypes(_ js.Value, _ []js.Value) (any, error) {
|
||||
// Returns available DNS record types
|
||||
return []string{
|
||||
"A", "AAAA", "MX", "TXT", "NS", "CNAME", "SOA", "PTR", "SRV", "CAA",
|
||||
}, nil
|
||||
// Returns all available DNS record types
|
||||
types := pd.GetAllDNSRecordTypes()
|
||||
result := make([]string, len(types))
|
||||
for i, t := range types {
|
||||
result[i] = string(t)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getDNSRecordTypeInfo(_ js.Value, _ []js.Value) (any, error) {
|
||||
// Returns detailed info about all DNS record types
|
||||
info := pd.GetDNSRecordTypeInfo()
|
||||
result := make([]any, len(info))
|
||||
for i, r := range info {
|
||||
result[i] = map[string]any{
|
||||
"type": string(r.Type),
|
||||
"name": r.Name,
|
||||
"description": r.Description,
|
||||
"rfc": r.RFC,
|
||||
"common": r.Common,
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getCommonDNSRecordTypes(_ js.Value, _ []js.Value) (any, error) {
|
||||
// Returns only commonly used DNS record types
|
||||
types := pd.GetCommonDNSRecordTypes()
|
||||
result := make([]string, len(types))
|
||||
for i, t := range types {
|
||||
result[i] = string(t)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
@ -709,6 +738,8 @@ func main() {
|
|||
export("pxBuildRDAPIPURL", buildRDAPIPURL)
|
||||
export("pxBuildRDAPASNURL", buildRDAPASNURL)
|
||||
export("pxGetDNSRecordTypes", getDNSRecordTypes)
|
||||
export("pxGetDNSRecordTypeInfo", getDNSRecordTypeInfo)
|
||||
export("pxGetCommonDNSRecordTypes", getCommonDNSRecordTypes)
|
||||
|
||||
// Keep running
|
||||
select {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue