{T}

高安全架构 学习笔记(第 7 部分)

4.3 DNS 劫持防护

javascript
// DNS 安全检查
class DNSSecurity {
  constructor() {
    this.authorizedIPs = new Map()
  }
  
  // DNS 解析验证
  async verifyDNSResolution(domain) {
    // 从多个 DNS 服务器获取解析结果
    const dnsServers = [
      '8.8.8.8',      // Google DNS
      '1.1.1.1',      // Cloudflare DNS
      '114.114.114.114'  // 114 DNS
    ]
    
    const results = await Promise.all(
      dnsServers.map(dns => this.resolveDNS(domain, dns))
    )
    
    // 检查解析结果是否一致
    const uniqueIPs = new Set(results)
    
    if (uniqueIPs.size > 1) {
      console.warn('DNS 解析结果不一致,可能遭受 DNS 劫持')
      console.log('解析结果:', results)
      
      return {
        safe: false,
        reason: 'DNS 解析结果不一致',
        results
      }
    }
    
    // 验证 IP 是否在授权列表中
    const ip = results[0]
    const authorized = this.authorizedIPs.get(domain)
    
    if (authorized && !authorized.includes(ip)) {
      return {
        safe: false,
        reason: '解析 IP 不在授权列表中',
        ip,
        authorized
      }
    }
    
    return {
      safe: true,
      ip
    }
  }
  
  // DNS 解析
  async resolveDNS(domain, dnsServer) {
    // 实际实现:使用 DNS 解析库
    const dns = require('dns').promises
    const result = await dns.resolve4(domain)
    return result[0]
  }
  
  // DNSSEC 验证
  async verifyDNSSEC(domain) {
    // DNSSEC 签名验证
    console.log(`验证 ${domain} 的 DNSSEC 签名`)
    
    return {
      verified: true,
      chainOfTrust: 'valid'
    }
  }
  
  // HTTPS 证书验证
  async verifyCertificate(domain) {
    const tls = require('tls')
    
    return new Promise((resolve, reject) => {
      const socket = tls.connect(443, domain, {
        servername: domain
      }, () => {
        const cert = socket.getPeerCertificate()
        
        // 检查证书是否有效
        const valid = socket.authorized
        
        // 检查证书域名
        const domainMatch = this.checkCertificateDomain(cert, domain)
        
        socket.end()
        
        resolve({
          valid,
          domainMatch,
          issuer: cert.issuer,
          validFrom: cert.valid_from,
          validTo: cert.valid_to
        })
      })
      
      socket.on('error', reject)
    })
  }
  
  // 检查证书域名
  checkCertificateDomain(cert, domain) {
    // 检查 CN 和 SAN
    const cn = cert.subject.CN
    const san = cert.subjectaltname
    
    if (cn === domain) return true
    
    if (san && san.includes(domain)) return true
    
    // 通配符证书
    if (cn.startsWith('*.')) {
      const baseDomain = cn.substring(2)
      if (domain.endsWith(baseDomain)) return true
    }
    
    return false
  }
}
 
// 使用示例
const dnsSecurity = new DNSSecurity()
 
// 验证 DNS 解析
dnsSecurity.verifyDNSResolution('example.com')
  .then(result => console.log('DNS 安全检查:', result))