Guía de defensa contra la huella digital del navegador: desde Canvas Fingerprinting hasta estrategias antirrastreo centradas en la privacidad

前端工程

Huella digital del navegador: rastreo sin cookies

Incluso con las cookies deshabilitadas y el modo incógnito activado, los sitios web pueden identificarte de manera única a través de la huella digital del navegador, con una tasa de precisión de hasta el 99,1%.

Tipo de huella digital Estabilidad Singularidad Dificultad de defensa
User-Agent Baja (cambia con actualizaciones) Media Baja
Canvas Alta Alta Media
WebGL Alta Alta Media
AudioContext Alta Media Media
Enumeración de fuentes Alta Alta Alta
Resolución de pantalla Alta Media Baja
Zona horaria/Idioma Alta Baja Baja

1. Huella digital Canvas

Cómo funciona

Diferentes GPU, controladores y algoritmos de suavizado en diferentes dispositivos producen diferencias sutiles en la misma salida de renderizado Canvas:

function getCanvasFingerprint() {
  const canvas = document.createElement('canvas');
  canvas.width = 200;
  canvas.height = 50;
  const ctx = canvas.getContext('2d');

  // Renderizar texto y formas
  ctx.textBaseline = 'top';
  ctx.font = '14px Arial';
  ctx.fillStyle = '#f60';
  ctx.fillRect(125, 1, 62, 20);
  ctx.fillStyle = '#069';
  ctx.fillText('Hello, world! 🌍', 2, 15);
  ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
  ctx.fillText('Hello, world! 🌍', 4, 17);

  // Extraer datos de píxeles y hash
  const data = canvas.toDataURL();
  return hash(data); // ej., "a1b2c3d4..."
}

Métodos de defensa

Método 1: Inyectar ruido

// Sobrescribir toDataURL para añadir ruido aleatorio sutil
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;

HTMLCanvasElement.prototype.toDataURL = function (...args) {
  const ctx = this.getContext('2d');
  if (ctx) {
    // Añadir píxeles aleatorios en posiciones inconspicuas
    const imageData = ctx.getImageData(0, 0, this.width, this.height);
    const noise = Math.random() * 0.01;
    imageData.data[0] = Math.min(255, imageData.data[0] + noise);
    ctx.putImageData(imageData, 0, 0);
  }
  return originalToDataURL.apply(this, args);
};

Método 2: Devolver valores fijos

// Todos los canvas devuelven la misma imagen en blanco
HTMLCanvasElement.prototype.toDataURL = function () {
  return 'data:image/png;base64,...'; // Imagen en blanco fija
};

2. Huella digital WebGL

Cómo funciona

WebGL expone información del renderizador y proveedor de la GPU, y diferentes GPU producen diferentes resultados de renderizado:

function getWebGLFingerprint() {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl');

  const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
  const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
  const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);

  // Renderizar escena de prueba
  // ... Diferentes GPU producen diferentes resultados de píxeles

  return { vendor, renderer, renderHash };
}

Información comúnmente filtrada

Información Ejemplo
Proveedor de GPU "NVIDIA Corporation", "Intel", "AMD"
Renderizador de GPU "GeForce RTX 4090", "Apple M2"
Tamaño máximo de textura 16384, 8192
Atributos máximos de vértice 16
Lista de extensiones soportadas 30+ nombres de extensiones

Método de defensa

// Ocultar información de la GPU
const getParameter = WebGLRenderingContext.prototype.getParameter;

WebGLRenderingContext.prototype.getParameter = function (param) {
  if (param === 37445) return 'Intel Inc.';    // UNMASKED_VENDOR
  if (param === 37446) return 'Intel Iris';    // UNMASKED_RENDERER
  return getParameter.call(this, param);
};

3. Huella digital AudioContext

Cómo funciona

Las unidades de procesamiento de audio (DSP) de diferentes dispositivos producen diferencias sutiles al procesar la misma señal:

function getAudioFingerprint() {
  const context = new OfflineAudioContext(1, 44100, 44100);

  const oscillator = context.createOscillator();
  oscillator.type = 'triangle';
  oscillator.frequency.setValueAtTime(10000, context.currentTime);

  const compressor = context.createDynamicsCompressor();
  compressor.threshold.setValueAtTime(-50, context.currentTime);
  compressor.knee.setValueAtTime(40, context.currentTime);
  compressor.ratio.setValueAtTime(12, context.currentTime);

  oscillator.connect(compressor);
  compressor.connect(context.destination);
  oscillator.start(0);

  return context.startRendering().then(buffer => {
    const data = buffer.getChannelData(0);
    return hash(data.slice(4500, 5000));
  });
}

Método de defensa

// Añadir ruido a la salida de AudioContext
const originalStartRendering = OfflineAudioContext.prototype.startRendering;

OfflineAudioContext.prototype.startRendering = function () {
  return originalStartRendering.call(this).then(buffer => {
    const data = buffer.getChannelData(0);
    for (let i = 0; i < data.length; i++) {
      data[i] += (Math.random() - 0.5) * 1e-7;
    }
    return buffer;
  });
};

4. Huella digital por enumeración de fuentes

Cómo funciona

Al medir el ancho de renderizado de diferentes nombres de fuentes, se puede determinar qué fuentes están instaladas en el sistema del usuario:

function detectFonts() {
  const testFonts = [
    'Arial', 'Helvetica', 'Times New Roman',
    'Courier', 'Verdana', 'Georgia',
    'Comic Sans MS', 'Impact', 'Tahoma',
    'Microsoft YaHei', 'PingFang SC',
  ];

  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  const baseFonts = ['monospace', 'serif', 'sans-serif'];
  const results = {};

  for (const font of testFonts) {
    for (const base of baseFonts) {
      ctx.font = `72px ${base}`;
      const baseWidth = ctx.measureText('mmmmmmmmll').width;
      ctx.font = `72px "${font}", ${base}`;
      const testWidth = ctx.measureText('mmmmmmmmll').width;
      if (baseWidth !== testWidth) {
        results[font] = true;
        break;
      }
    }
  }

  return results;
}

Métodos de defensa

La enumeración de fuentes es la más difícil de defender porque aprovecha las capacidades normales de renderizado de texto del navegador. Estrategias clave:

  1. Limitar la carga de fuentes: Solo permitir fuentes del sistema
  2. CSS font-display: block: Retrasar fuentes no esenciales
  3. Configuración de privacidad del navegador: privacy.resistFingerprinting de Firefox

5. Análisis integral de entropía de huella digital

Dimensión de información Entropía (bits) Singularidad acumulativa
User-Agent ~10 2^10 = 1.024
Resolución de pantalla ~5 2^15
Zona horaria ~5 2^20
Fuentes instaladas ~15 2^35
Canvas ~15 2^50
WebGL ~10 2^60
AudioContext ~5 2^65

2^65 ≈ 3,7 × 10^19, suficiente para identificar de manera única cada dispositivo en la Tierra.


6. Arquitectura de aplicación centrada en la privacidad

Estrategia de privacidad de ToolsKu

Archivos del usuario → Procesamiento local en el navegador → Descarga directa del resultado
         ↑
    Sin tránsito por servidor
    Sin almacenamiento de datos
    Sin cookies de rastreo
    Sin recopilación de huella digital del navegador

Lista de verificación de implementación

Estrategia Implementación Prioridad
Sin rastreo de terceros Eliminar scripts como Google Analytics P0
CSP restringe recursos externos default-src 'self' P0
Sin cookies establecidas Sitio estático no necesita cookies P0
Referrer-Policy strict-origin-when-cross-origin P1
Permissions-Policy Restringir acceso a API P1
Declaración de privacidad Divulgar claramente el manejo de datos P1
Arquitectura de procesamiento local Todo el cálculo se realiza en el navegador P0

Configuración de encabezados de seguridad HTTP

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

7. Prueba tu propia huella digital

Recomendamos usar las siguientes herramientas para probar la singularidad de la huella digital de tu navegador:

  • AmIUnique (amiunique.org): Detección integral de huella digital
  • BrowserLeaks (browserleaks.com): Análisis detallado de Canvas/WebGL/Audio
  • FingerprintJS (fingerprintjs.com): Demo de la biblioteca de huella digital de código abierto

Consejos para reducir tu huella digital:

  1. Usa Firefox + privacy.resistFingerprinting = true
  2. Usa Tor Browser (huella digital uniforme)
  3. Usa extensiones de privacidad (Privacy Badger, uBlock Origin)
  4. Evita instalar fuentes raras
  5. Usa resoluciones y proporciones de escala estándar

Prueba estas herramientas que se ejecutan en tu navegador — no requieren registro →

#浏览器指纹#隐私安全#Canvas#WebGL#反追踪