<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>El hilo del laberinto (Publicaciones sobre Privacidad)</title><link>https://blog.jcea.es/</link><description></description><atom:link href="https://blog.jcea.es/categories/privacidad.xml" rel="self" type="application/rss+xml"></atom:link><language>es</language><lastBuildDate>Mon, 01 Jun 2026 23:08:25 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Thunderbird "habla demasiado" (respecto a tu configuración)</title><link>https://blog.jcea.es/posts/20241113-version_thunderbird.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;El otro día estaba mirando las &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Protocolo_para_transferencia_simple_de_correo#Formato_del_mensaje"&gt;cabeceras SMTP&lt;/a&gt; de mis correos
electrónicos y me he llevado una sorpresa:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
            Thunderbird/102.15.1
&lt;/pre&gt;
&lt;p&gt;Mi cliente de correo, &lt;a class="reference external" href="https://www.mozilla.org/thunderbird/"&gt;Thunderbird&lt;/a&gt;, filtra la versión que estoy
utilizando y que estoy usando &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Linux"&gt;Linux&lt;/a&gt; sobre &lt;a class="reference external" href="https://es.wikipedia.org/wiki/X86-64"&gt;x86-64&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Y esto no lo hace solo en los correos electrónicos salientes sino
también en las conexiones &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Protocolo_de_transferencia_de_hipertexto"&gt;HTTP&lt;/a&gt; que se generen al visualizar
mensajes en formato &lt;a class="reference external" href="https://es.wikipedia.org/wiki/HTML"&gt;HTML&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Esto me parece algo innecesario y un peligro de privacidad y de
seguridad.&lt;/p&gt;
&lt;p&gt;Afortunadamente podemos irnos al editor de configuración de
&lt;a class="reference external" href="https://www.mozilla.org/thunderbird/"&gt;Thunderbird&lt;/a&gt; y editar (o crear, si no existe) la preferencia
&lt;span class="kbd"&gt;general.useragent.override&lt;/span&gt;. Ahí ponemos el texto que nos de
la gana.&lt;/p&gt;
&lt;p&gt;En versiones modernas de &lt;a class="reference external" href="https://www.mozilla.org/thunderbird/"&gt;Thunderbird&lt;/a&gt; podemos indicarle
directamente al programa que sólo envie &lt;span class="kbd"&gt;Thunderbird&lt;/span&gt; como
identificación, sin referencias de plataforma o versiones. Para
ello hay que entrar en el editor de configuración y poner (o
crear) la preferencia &lt;span class="kbd"&gt;mailnews.headers.useMinimalUserAgent&lt;/span&gt;
a &lt;strong&gt;True&lt;/strong&gt;. Si no queremos enviar una identificación de usuario en
absoluto, podemos poner a &lt;strong&gt;False&lt;/strong&gt; la preferencia
&lt;span class="kbd"&gt;mailnews.headers.sendUserAgent&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Podeis ver los detalles por vosotros mismos en el &lt;a class="reference external" href="https://hg-edge.mozilla.org/comm-central/rev/627eda4cbefc"&gt;código fuente&lt;/a&gt; de
&lt;a class="reference external" href="https://www.mozilla.org/thunderbird/"&gt;Thunderbird&lt;/a&gt;, en su servidor &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Mercurial"&gt;Mercurial&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><category>Configuración</category><category>Privacidad</category><category>Thunderbird</category><guid>https://blog.jcea.es/posts/20241113-version_thunderbird.html</guid><pubDate>Wed, 13 Nov 2024 22:07:00 GMT</pubDate></item><item><title>Automatización y mantenimiento de NSEC3PARAM en DNSSEC</title><link>https://blog.jcea.es/posts/20240219-nsec3params.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;La solución propuesta en &lt;a class="reference external" href="https://blog.jcea.es/posts/20170622-dnssec_nsec3.html"&gt;Por qué es conveniente usar NSEC3 en vez de NSEC en un dominio DNSSEC&lt;/a&gt; define
&lt;strong&gt;NSEC3PARAM&lt;/strong&gt; ya sea en el fichero de zona o utilizando
&lt;span class="kbd"&gt;rndc signing -nsec3param&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Este enfoque tiene un problema serio: ocasionalmente el
&lt;span class="kbd"&gt;signed&lt;/span&gt; o el &lt;em&gt;journal&lt;/em&gt; de &lt;a class="reference external" href="https://www.isc.org/downloads/BIND/"&gt;BIND&lt;/a&gt; se corrompen y hay que
borrarlos. No parece grave porque &lt;a class="reference external" href="https://www.isc.org/downloads/BIND/"&gt;BIND&lt;/a&gt; vuelve a regenerar esos
ficheros pero... la configuración &lt;strong&gt;NSEC3PARAM&lt;/strong&gt; se pierde. Y si
&lt;a class="reference external" href="https://www.isc.org/downloads/BIND/"&gt;BIND&lt;/a&gt; pierde la configuración &lt;strong&gt;NSEC3PARAM&lt;/strong&gt; deja de servir &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC3&lt;/a&gt;
y la zona pasa a ser &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt;... y no te enteras.&lt;/p&gt;
&lt;p&gt;Tras ocurrirme un par de veces decidí ver qué estaba haciendo mal.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20240219-nsec3params.html"&gt;Leer más…&lt;/a&gt; (quedan 2 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>DNSSEC</category><category>Privacidad</category><category>Seguridad</category><guid>https://blog.jcea.es/posts/20240219-nsec3params.html</guid><pubDate>Mon, 19 Feb 2024 14:55:00 GMT</pubDate></item><item><title>Mejoras a la hora de generar un email diario a partir de un feed RSS (Slashdot)</title><link>https://blog.jcea.es/posts/20200330-slashdot.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;En &lt;a class="reference external" href="https://blog.jcea.es/posts/20191011-slashdot.html"&gt;Generar un email diario a partir de un feed RSS (Slashdot)&lt;/a&gt; publico un pequeño programa en &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Python"&gt;Python&lt;/a&gt;
para enviarme un correo electrónico diario con los artículos
publicados en &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; desde la última notificación.&lt;/p&gt;
&lt;p&gt;Este programa me ha servido bien durante años, pero había un
problema desconcertante: El programa se ejecuta por &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Cron_(Unix)"&gt;cron&lt;/a&gt; una vez
por hora y se supone que tendría que enviarme el resumen diario
entre las cuatro y cinco de la tarde. Normalmente era así, pero no
siempre. A veces el email se enviaba horas más tarde.&lt;/p&gt;
&lt;p&gt;La cosa no era grave, solo molesta, y nunca tenía tiempo para
investigarla. Cuando por fin me metí en harina, tardé un buen
ratillo en localizar el problema:&lt;/p&gt;
&lt;p&gt;El programa hace una petición &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Protocolo_de_transferencia_de_hipertexto"&gt;HTTP&lt;/a&gt; condicional al &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt; de
&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; para no machacar el servidor y no trabajar nosotros
tampoco en vano si no ha habido cambios. La cuestión es que, si no
hay nada nuevo que procesar, el programa termina inmediatamente.
Es decir, no llega a la parte de "es hora de mandar el email". En
resumen, el correo electrónico se enviaba solo cuando era más
tarde de las 16:00 y, además, había entrado algún artículo nuevo
en el &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Una vez determinada la causa última, la solución es simple:
procesar el &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt; aunque no haya novedades. La cosa parecía
sencilla, pero al final no lo fue tanto. No guardo el &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt;
original así que tengo que hacer chanchullos para que mi programa
no considere que ha perdido datos. La lógica es innecesariamente
compleja, el programa exige una refactorización urgente. Durante
el proceso detecté otro problema: si en un momento dado el
programa detecta que se han perdido datos, pero no ha llegado aún
el momento de enviar el correo electrónico, no nos enteramos.
Compliqué el código una vez más para que el estado "pérdida de
datos" sea persistente y solo se limpie cuando se ha enviado el
correo electrónico notificándolo.&lt;/p&gt;
&lt;p&gt;El resultado es un programa que funciona correctamente, pero
innecesariamente complejo y bastante frágil. Cuando se llega a
este estado urge refactorizar o, con un programa tan corto,
directamente reescribirlo por completo.&lt;/p&gt;
&lt;p&gt;Las diferencias respecto a la versión anterior son:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://blog.jcea.es/listings/slashdot-20181015-ddeb027b3f1c.diff.html"&gt;slashdot-20181015-ddeb027b3f1c.diff&lt;/a&gt;  &lt;a class="reference external" href="https://blog.jcea.es/listings/slashdot-20181015-ddeb027b3f1c.diff"&gt;(Código fuente)&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code diff"&gt;&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-1"&gt;&lt;/a&gt;&lt;span class="gd"&gt;--- slashdot-20181015.py        2019-10-12 02:28:46.020075954 +0200&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-2"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+++ slashdot-ddeb027b3f1c.py    2021-02-11 20:18:38.341490217 +0100&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-3"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -1,7 +1,7 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-4"&gt;&lt;/a&gt; #!/usr/bin/env python3
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-7"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-# (c) 2018 Jesús Cea Avión - jcea@jcea.es - https://www.jcea.es/&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-8"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+# (c) 2018-2020 Jesús Cea Avión - jcea@jcea.es - https://www.jcea.es/&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-9"&gt;&lt;/a&gt; # This code is licensed under AGPLv3.
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-12"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -28,6 +28,7 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-13"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-14"&gt;&lt;/a&gt;         self._procesados = data['procesados']
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-15"&gt;&lt;/a&gt;         self._buckets = data['buckets']
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-16"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        self._solapamiento = data.get('solapamiento', True)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-17"&gt;&lt;/a&gt;         self._procesados_nuevos = set()
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-18"&gt;&lt;/a&gt;         self.etag = data['etag']
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-19"&gt;&lt;/a&gt;         self.modified = data['modified']
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-20"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -41,10 +42,14 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-21"&gt;&lt;/a&gt;             v['modified'] = self.modified
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-22"&gt;&lt;/a&gt;         return v
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-23"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-24"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    def notificado(self):&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-25"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        self._solapamiento = True&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-26"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        self.cambiado = True&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-27"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-28"&gt;&lt;/a&gt;     def solapamiento(self):
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-29"&gt;&lt;/a&gt;         if self.saved:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-30"&gt;&lt;/a&gt;             return self._solapamiento
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-31"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        return not self._procesados.isdisjoint(self._procesados_nuevos)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-32"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        return self._solapamiento and not self._procesados.isdisjoint(self._procesados_nuevos)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-33"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-34"&gt;&lt;/a&gt;     def update(self, guid, ts, title, link, summary):
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-35"&gt;&lt;/a&gt;         self._procesados_nuevos.add(guid)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-36"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -65,6 +70,10 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-37"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-38"&gt;&lt;/a&gt;         return self.update(guid, ts, title, link, summary)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-39"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-40"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    def feed304(self):&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-41"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        self._procesados_nuevos.update(self._procesados)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-42"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        return self.etag, self.modified&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-43"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-44"&gt;&lt;/a&gt;     def itera_antiguos(self, horas=16):
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-45"&gt;&lt;/a&gt;         ts_antiguo = datetime.datetime.now()
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-46"&gt;&lt;/a&gt;         ts_antiguo -= datetime.timedelta(seconds=horas * 60 * 60)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-47"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -99,6 +108,8 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-48"&gt;&lt;/a&gt;         if not self.cambiado:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-49"&gt;&lt;/a&gt;             return
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-50"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-51"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        self._solapamiento = self.solapamiento()&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-52"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-53"&gt;&lt;/a&gt;         procesados = self._procesados_nuevos
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-54"&gt;&lt;/a&gt;         if not purga:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-55"&gt;&lt;/a&gt;             procesados.update(self._procesados)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-56"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -106,6 +117,7 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-57"&gt;&lt;/a&gt;         with open(path + '.NEW', 'wb') as f:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-58"&gt;&lt;/a&gt;             data = {'procesados': procesados,
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-59"&gt;&lt;/a&gt;                     'buckets': self._buckets,
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-60"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+                    'solapamiento': self._solapamiento,&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-61"&gt;&lt;/a&gt;                     'etag': etag, 'modified': modified,
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-62"&gt;&lt;/a&gt;                     }
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-63"&gt;&lt;/a&gt;             pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-64"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -115,7 +127,6 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-65"&gt;&lt;/a&gt;         self.cambiado = False
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-66"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-67"&gt;&lt;/a&gt;         # Tras el save no deberíamos usar más este objeto
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-68"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        self._solapamiento = self.solapamiento()&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-69"&gt;&lt;/a&gt;         self.saved = True
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-70"&gt;&lt;/a&gt;         del self._procesados
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-71"&gt;&lt;/a&gt;         del self._procesados_nuevos
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-72"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -136,20 +147,21 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-73"&gt;&lt;/a&gt;     finally:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-74"&gt;&lt;/a&gt;         socket.setdefaulttimeout(timeout)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-75"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-76"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    if feed.status == 304:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-77"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        # print("Sin cambios")&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-78"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        return&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-79"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-80"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    for entry in feed.entries:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-81"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        summary = BeautifulSoup(entry["summary"], 'html.parser')&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-82"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        summary = list(summary.children)[0]&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-83"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        entradas.new(entry['id'], entry.updated_parsed,&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-84"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-                     entry['title'], entry['link'], summary)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-85"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-86"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    no_solapamiento = ''&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-87"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    if not entradas.solapamiento():&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-88"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        no_solapamiento = '&amp;lt;font size=+2&amp;gt;&amp;lt;b&amp;gt;HEMOS PERDIDO ENTRADAS&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;'&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-89"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-        no_solapamiento += '&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;\n'&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-90"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    if feed.status == 200:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-91"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        etag, modified = feed.get('etag'), feed.get('modified')&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-92"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        for entry in feed.entries:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-93"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+            summary = BeautifulSoup(entry["summary"], 'html.parser')&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-94"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+            summary = list(summary.children)[0]&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-95"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+            entradas.new(entry['id'], entry.updated_parsed,&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-96"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+                         entry['title'], entry['link'], summary)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-97"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    elif feed.status == 304:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-98"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        # En el 304 no se manda ETAG ni Modified, así que coge los que comprobamos&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-99"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        # en la petición condicional.&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-100"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        etag, modified = entradas.feed304()&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-101"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    else:&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-102"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        raise RuntimeError(f'Estado: {feed.status}')&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-103"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-104"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    # Si es 304, procesamos lo viejo por si tiene que salir el email.&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-105"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-106"&gt;&lt;/a&gt;     html_desc = html_links = ''
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-107"&gt;&lt;/a&gt;     entradas_a_borrar = []
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-108"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -164,9 +176,14 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-109"&gt;&lt;/a&gt;     # lo cierto es que queremos actualizar el etag y el modified AUNQUE
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-110"&gt;&lt;/a&gt;     # no haya habido cambios en el feed. Esto es algo a mejorar en el futuro.
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-111"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-112"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    entradas.save(feed.get('etag'), feed.get('modified'))&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-113"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    entradas.save(etag, modified)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-114"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-115"&gt;&lt;/a&gt;     if html_desc:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-116"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        no_solapamiento = ''&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-117"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        if not entradas.solapamiento():&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-118"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+            no_solapamiento = '&amp;lt;font size=+2&amp;gt;&amp;lt;b&amp;gt;HEMOS PERDIDO ENTRADAS&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;'&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-119"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+            no_solapamiento += '&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;\n'&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-120"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-121"&gt;&lt;/a&gt;         html_links = f'&amp;lt;ul&amp;gt;\n{html_links}\n&amp;lt;/ul&amp;gt;\n'
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-122"&gt;&lt;/a&gt;         html = f'''&amp;lt;html&amp;gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-123"&gt;&lt;/a&gt; &amp;lt;head&amp;gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-124"&gt;&lt;/a&gt;&lt;span class="gu"&gt;@@ -196,14 +213,17 @@&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-125"&gt;&lt;/a&gt;                        stdout=subprocess.PIPE,
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-126"&gt;&lt;/a&gt;                        stderr=subprocess.PIPE)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-127"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-128"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+        entradas.notificado()&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-129"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-130"&gt;&lt;/a&gt;     # XXX: Lo suyo sería grabar solo si hay cambios de verdad, pero
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-131"&gt;&lt;/a&gt;     # lo cierto es que queremos actualizar el etag y el modified AUNQUE
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-132"&gt;&lt;/a&gt;     # no haya habido cambios en el feed. Esto es algo a mejorar en el futuro.
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-133"&gt;&lt;/a&gt;     entradas = items()
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-134"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    etag, modified = entradas.feed304()  # XXX: Para evitar "no solapamiento"&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-135"&gt;&lt;/a&gt;     for guid, ts in entradas_a_borrar:
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-136"&gt;&lt;/a&gt;         entradas.borrar(guid, ts)
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-137"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-138"&gt;&lt;/a&gt;&lt;span class="gd"&gt;-    entradas.save(feed.get('etag'), feed.get('modified'), purga=False)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-139"&gt;&lt;/a&gt;&lt;span class="gi"&gt;+    entradas.save(etag, modified, purga=False)&lt;/span&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-140"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-141"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc66038f25654613a8e9f88cd161359e-142"&gt;&lt;/a&gt; if __name__ == '__main__':
&lt;/pre&gt;&lt;p&gt;El código completo es el siguiente:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20200330-slashdot.html"&gt;Leer más…&lt;/a&gt; (quedan 5 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>Código Fuente</category><category>Feed RSS</category><category>Privacidad</category><category>Python</category><category>Scraping web</category><category>Slashdot</category><guid>https://blog.jcea.es/posts/20200330-slashdot.html</guid><pubDate>Mon, 30 Mar 2020 16:52:00 GMT</pubDate></item><item><title>Audio de la entrevista radiofónica "Edward Snowden, ética frente a vigilancia masiva"</title><link>https://blog.jcea.es/posts/20191205-Snowden.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;El 22 de noviembre de 2019 me entrevistaron en el programa de
radio &lt;a class="reference external" href="https://fr.ivoox.com/es/podcast-olvida-tu-equipaje_sq_f11079_1.html"&gt;Olvida tu equipaje&lt;/a&gt; de &lt;a class="reference external" href="http://www.radioutopia.es/"&gt;Radio Utopía&lt;/a&gt; para hablar de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Edward_Snowden"&gt;Edward Snowden&lt;/a&gt; y
su libro &lt;a class="reference external" href="https://www.planetadelibros.com/libro-vigilancia-permanente/299867"&gt;Vigilancia permanente&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Se trata de una autobiografía que describe con detalle su juventud
vinculada a la informática e Internet, su trabajo posterior en la
comunidad de inteligencia, sus dudas crecientes sobre la ética en
juego y su determinación final de sacar los abusos ilegales a la
luz, aun con las consecuencias que sabría que le acarrearían.&lt;/p&gt;
&lt;p&gt;El libro vale mucho la pena y, además, es divertido y fácil de
leer y entender.&lt;/p&gt;
&lt;p&gt;La verdad es que en la entrevista hablamos poco de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Edward_Snowden"&gt;Snowden&lt;/a&gt; y de
&lt;a class="reference external" href="https://www.planetadelibros.com/libro-vigilancia-permanente/299867"&gt;Vigilancia permanente&lt;/a&gt; y la cosa se centra más en mis opiniones,
pero creo que puede resultar interesante.&lt;/p&gt;
&lt;p&gt;Acceso a la entrevista de una hora y veinte minutos de duración:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fr.ivoox.com/es/22-11-19-edward-snowden-etica-frente-a-vigilancia-masiva-audios-mp3_rf_44634129_1.html"&gt;ivoox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://archive.org/details/olvidatuequipajesnowden221119"&gt;archive.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gracias a &lt;a class="reference external" href="https://armandosilles.blogspot.com/"&gt;Armando Silles&lt;/a&gt; por esta oportunidad. Por cierto, que
ha publicado &lt;a class="reference external" href="https://armandosilles.blogspot.com/p/blog-page_8.html"&gt;Aire verdadero&lt;/a&gt;, un
libro de poesía bastante interesante que igual te apetece.&lt;/p&gt;&lt;/div&gt;</description><category>Hacking</category><category>Opinión</category><category>Personal</category><category>Podcast</category><category>Presentaciones Públicas</category><category>Privacidad</category><category>Seguridad</category><category>Señores Feudales</category><category>Snowden</category><category>Tor</category><guid>https://blog.jcea.es/posts/20191205-Snowden.html</guid><pubDate>Thu, 05 Dec 2019 16:19:00 GMT</pubDate></item><item><title>Generar un email diario a partir de un feed RSS (Slashdot)</title><link>https://blog.jcea.es/posts/20191011-slashdot.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;Llevo décadas, literalmente, siguiendo &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt;. Es una de mis
fuentes de noticias de revisión diaria obligada. Se puede seguir a
través del &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt;, pero el tráfico diario es alto y es fácil
perder noticias si pasas un par de días desconectado, porque, por
ejemplo, estás de vacaciones o de viaje. Afortunadamente,
&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; proporciona la opción de recibir un único mensaje diario
con la recopilación de noticias del día anterior. Esto es muy
conveniente para leerlas cuando te va bien, no preocuparte de
perder noticias y, además, poder archivarlas en tu sistema de
correo para futuras búsquedas o referencias.&lt;/p&gt;
&lt;p&gt;Todo fue bien hasta el 23 de septiembre de 2018. Ese día me
dejaron de llegar los mensajes diarios de noticias sin ningún
motivo aparente &lt;a class="footnote-reference" href="https://blog.jcea.es/posts/20191011-slashdot.html#vuelve-a-funcionar" id="id1"&gt;[1]&lt;/a&gt;. Curiosamente, sí me
llegaban los emails de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; sobre promociones y publicidad.&lt;/p&gt;
&lt;p&gt;Revisé mi configuración &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Antispam"&gt;antispam&lt;/a&gt;, por si acaso mi servidor de
correo electrónico se estaba comiendo los mensajes, los &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Log_(inform%C3%A1tica)"&gt;logs&lt;/a&gt; del
servidor, etc., sin éxito. Preguntar online y revisar foros para
ver si alguien más tenía problemas fue infructuoso. Intentar
ponerme en contacto con la gente de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; fue imposible.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt;, sencillamente, ya no me enviaba los mensajes.&lt;/p&gt;
&lt;p&gt;Durante un tiempo aguanté leyendo el &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt; de forma diaria,
pero los fines de semana eran problemáticos porque tenía apagado
el ordenador un par de días y algunas noticias ya no entraban en
el último &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Rss"&gt;&lt;em&gt;feed&lt;/em&gt; RSS&lt;/a&gt;. Los lunes tocaba revisar noticias a mano.&lt;/p&gt;
&lt;p&gt;Tras pensarlo un poco y evaluar el coste/beneficio, decidí crear
un programa simple y mínimo para reemplazar el email de noticias
que me enviaba &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; a diario. El programa me costó una tarde
de trabajo y ha estado funcionando desde entonces sin ningún tipo
de problema.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="vuelve-a-funcionar" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label"&gt;&lt;col&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="https://blog.jcea.es/posts/20191011-slashdot.html#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt; empezó a enviarme las noticias diarias de nuevo el 6
de abril de 2019. Así, sin más. ¿Qué ocurrió? Imagino que nunca
lo sabré. La cuestión es que ya tenía este reemplazo
funcionando durante meses, sin publicidad, sin depender de
terceros, sin comprometer mi privacidad...&lt;/p&gt;
&lt;p class="last"&gt;Sigo suscrito a las notificaciones diarias de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Slashdot"&gt;Slashdot&lt;/a&gt;, pero
ya ni siquiera abro esos emails. Tengo las mías y son mejores.&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;El código completo es el siguiente:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20191011-slashdot.html"&gt;Leer más…&lt;/a&gt; (quedan 17 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>Código Fuente</category><category>Feed RSS</category><category>Privacidad</category><category>Python</category><category>Scraping web</category><category>Slashdot</category><guid>https://blog.jcea.es/posts/20191011-slashdot.html</guid><pubDate>Thu, 10 Oct 2019 23:43:00 GMT</pubDate></item><item><title>Audio de la participación radiofónica "Privacidad en Internet"</title><link>https://blog.jcea.es/posts/20190828-olvida_tu_equipaje.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;El 17 de noviembre de 2017 participé en el programa de radio
&lt;a class="reference external" href="https://fr.ivoox.com/es/podcast-olvida-tu-equipaje_sq_f11079_1.html"&gt;Olvida tu equipaje&lt;/a&gt; de &lt;a class="reference external" href="http://www.radioutopia.es/"&gt;Radio Utopía&lt;/a&gt; para hablar sobre &lt;strong&gt;"Privacidad en
Internet"&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Se trataron varios temas:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Artículo 12 de la &lt;a class="reference external" href="https://dudh.es/"&gt;Declaración Universal de los Derechos Humanos&lt;/a&gt;: Nadie será objeto de injerencias
arbitrarias en su vida privada, su familia, su domicilio o su
correspondencia, ni de ataques a su honra o a su reputación.
Toda persona tiene derecho a la protección de la ley contra
tales injerencias o ataques.&lt;/li&gt;
&lt;li&gt;¿A la gente le importa la privacidad? Todo lo que te dan
gratis... es a cambio de algo.&lt;/li&gt;
&lt;li&gt;La novela &lt;a class="reference external" href="https://es.wikipedia.org/wiki/1984_(novela)"&gt;1984&lt;/a&gt;
se ha quedado pequeña.&lt;/li&gt;
&lt;li&gt;Vigilancia masiva e indiscriminada.&lt;/li&gt;
&lt;li&gt;¿Qué cosas podemos y no podemos controlar?&lt;/li&gt;
&lt;li&gt;Para las organizaciones es más fácil guardarlo todo que elegir.&lt;/li&gt;
&lt;li&gt;Todo el mundo es persona de interés de forma retroactiva.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Yo no tengo nada que ocultar"&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Influencias en el día a dia que no son evidentes.&lt;/li&gt;
&lt;li&gt;Autocensura.&lt;/li&gt;
&lt;li&gt;Cuando tú no pagas, tú eres el producto.&lt;/li&gt;
&lt;li&gt;La gente acepta términos legales sin leerlos.&lt;/li&gt;
&lt;li&gt;Permisos abusivos de aplicaciones &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Android"&gt;Android&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Las empresas como defensa ante los estados.&lt;/li&gt;
&lt;li&gt;¿Qué ordenador comprar?&lt;/li&gt;
&lt;li&gt;¿Qué móvil comprar?&lt;/li&gt;
&lt;li&gt;La nube. La mensajería instantánea.&lt;/li&gt;
&lt;li&gt;Geolocalización.&lt;/li&gt;
&lt;li&gt;Usar &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Wifi"&gt;WIFIs&lt;/a&gt; que no son
de confianza. &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Secuestro_de_sesi%C3%B3n#Firesheep"&gt;Firesheep&lt;/a&gt;
y como un cambio decidido en una habitación con media docena de
personas afecta a la seguridad de millones de usuarios.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://maadix.net/"&gt;https://maadix.net/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://blog.jcea.es/posts/20191205-Snowden.html"&gt;Edward Snowden&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Acceso a la grabación, de una hora y treinta y dos  minutos de duración:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fr.ivoox.com/es/17-11-17-privacidad-internet-039-si-no-he-hecho-audios-mp3_rf_22143773_1.html"&gt;ivoox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://archive.org/details/17-11-17PrivacidadEnInternet.siNoHeHechoNadaMaloporQueSeEst"&gt;archive.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gracias a &lt;a class="reference external" href="https://armandosilles.blogspot.com/"&gt;Armando Silles&lt;/a&gt; por esta oportunidad. Por cierto, que
ha publicado &lt;a class="reference external" href="https://armandosilles.blogspot.com/p/blog-page_8.html"&gt;Aire verdadero&lt;/a&gt;, un
libro de poesía bastante interesante que igual te apetece.&lt;/p&gt;&lt;/div&gt;</description><category>Hacking</category><category>Opinión</category><category>Personal</category><category>Podcast</category><category>Presentaciones Públicas</category><category>Privacidad</category><category>Seguridad</category><category>Señores Feudales</category><category>Tor</category><guid>https://blog.jcea.es/posts/20190828-olvida_tu_equipaje.html</guid><pubDate>Wed, 28 Aug 2019 13:00:00 GMT</pubDate></item><item><title>Detección de presencia por ARP, o cómo saber si tu hijo está en casa (II): Ahora con AsyncIO</title><link>https://blog.jcea.es/posts/20180927-presencia_arp.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;En &lt;a class="reference external" href="https://blog.jcea.es/posts/20180622-presencia_arp.html"&gt;Detección de presencia por ARP, o cómo saber si tu hijo está en casa&lt;/a&gt; publiqué un programa &lt;a class="reference external" href="https://www.python.org/"&gt;Python&lt;/a&gt; que
notifica por &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Telegram"&gt;Telegram&lt;/a&gt; cuando un dispositivo concreto se conecta o
desconecta de tu red. Antes de seguir leyendo, te recomiendo que
repases &lt;a class="reference external" href="https://blog.jcea.es/posts/20180622-presencia_arp.html"&gt;ese artículo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;El código me ha servido bien, pero tiene algunos detalles que no
me acaban de gustar:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Una vez por minuto se lanzan cientos de procesos &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Ping"&gt;Ping&lt;/a&gt; para
sondear la red. Aunque la &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Raspberry_pi"&gt;Raspberry PI&lt;/a&gt; donde está funcionando
este sensor va sobrada de recursos y no he tenido problemas con
esas avalanchas, resulta algo poco elegante.&lt;/li&gt;
&lt;li&gt;Lanzo un proceso externo para leer la tabla &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Protocolo_de_resoluci%C3%B3n_de_direcciones"&gt;ARP&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Publico aquí una nueva versión del código &lt;a class="reference external" href="https://www.python.org/"&gt;Python&lt;/a&gt;, esta vez usando
la biblioteca &lt;a class="reference external" href="https://docs.python.org/3/library/asyncio.html"&gt;asyncio&lt;/a&gt; de &lt;a class="reference external" href="https://www.python.org/"&gt;Python&lt;/a&gt; 3:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20180927-presencia_arp.html"&gt;Leer más…&lt;/a&gt; (quedan 5 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>AsyncIO</category><category>Código Fuente</category><category>Internet of Things</category><category>Linux</category><category>Privacidad</category><category>Python</category><category>Raspberry PI</category><category>Redes</category><guid>https://blog.jcea.es/posts/20180927-presencia_arp.html</guid><pubDate>Thu, 27 Sep 2018 21:01:00 GMT</pubDate></item><item><title>Detección de presencia por ARP, o cómo saber si tu hijo está en casa</title><link>https://blog.jcea.es/posts/20180622-presencia_arp.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;Los adolescentes prefieren morir antes que salir de casa sin su
móvil y la condenación eterna antes que permitir que se quede sin
batería, así que comprobar si el móvil de tu hijo está conectado a
tu red &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Wifi"&gt;WIFI&lt;/a&gt; es una buena forma de saber si está o no en casa.&lt;/p&gt;
&lt;p&gt;El siguiente programa te avisa por &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Telegram"&gt;Telegram&lt;/a&gt; cuando tu hijo entra
o sale de casa. De modo general, te avisa cuando un determinado
dispositivo pasa a estar presente o desaparece de tu red
doméstica.&lt;/p&gt;
&lt;p&gt;Este programa puede ejecutarse en cualquier máquina &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Unix"&gt;&lt;em&gt;Unix-like&lt;/em&gt;&lt;/a&gt;
de nuestra red local que esté encendida permanentemente. En mi
caso utilizo una &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Raspberry_pi"&gt;Raspberry PI&lt;/a&gt; que tiene otros usos adicionales.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20180622-presencia_arp.html"&gt;Leer más…&lt;/a&gt; (quedan 8 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>Código Fuente</category><category>Internet of Things</category><category>Linux</category><category>Privacidad</category><category>Python</category><category>Raspberry PI</category><category>Redes</category><guid>https://blog.jcea.es/posts/20180622-presencia_arp.html</guid><pubDate>Fri, 22 Jun 2018 20:52:00 GMT</pubDate></item><item><title>Usar NSEC3 en vez de NSEC en un dominio DNSSEC con gestión de DNS dinámico</title><link>https://blog.jcea.es/posts/20170624-dnssec_dns_dinamico_nsec3.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;En la configuración que describo en
&lt;a class="reference external" href="https://blog.jcea.es/posts/20170528-dnssec_dns_dinamico.html"&gt;Activación de DNSSEC en BIND con DNS dinámico&lt;/a&gt;, el servidor &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt; &lt;a class="reference external" href="https://www.isc.org/downloads/BIND/"&gt;BIND&lt;/a&gt; genera
registros &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt; en vez de &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC3&lt;/a&gt;. ¿Y qué? ¿Por qué importa eso?.Lo
explico clarito (creo) en &lt;a class="reference external" href="https://blog.jcea.es/posts/20170622-dnssec_nsec3.html"&gt;Por qué es conveniente usar NSEC3 en vez de NSEC en un dominio DNSSEC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Con todo esto ya entendemos por qué es conveniente mejorar la
receta descrita en &lt;a class="reference external" href="https://blog.jcea.es/posts/20170528-dnssec_dns_dinamico.html"&gt;Activación de DNSSEC en BIND con DNS dinámico&lt;/a&gt; y pasar a
usar &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nada más simple:&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_bdb881a2eec84aaab90b2ddaa2a56239-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; rndc signing -nsec3param &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; auto example.org
&lt;/pre&gt;&lt;p&gt;El primer parámetro es el &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Funci%C3%B3n_hash"&gt;hash&lt;/a&gt; a emplear (en este caso &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Sha1#SHA-1"&gt;SHA1&lt;/a&gt;). El
cero indica los &lt;em&gt;flags&lt;/em&gt; a aplicar que, en este caso, no nos
interesan. El 10 es el número de iteraciones. La &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Sal_(criptograf%C3%ADa)"&gt;sal&lt;/a&gt; en sí es el
siguiente campo. Si indicamos &lt;span class="kbd"&gt;auto&lt;/span&gt;, el programa
proporcionará 64 bits aleatorios. Personalmente eso me parece
poco, prefiero 160 bits, aunque eso incrementará el tamaño de la
respuesta &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_03502d59f03644969beec5a66f9e06ad-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; python3 -c &lt;span class="s2"&gt;"import secrets; print(secrets.token_hex(40))"&lt;/span&gt;
&lt;a name="rest_code_03502d59f03644969beec5a66f9e06ad-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;611a1cf6aa1b891b4909ed9d5ebe9d11b452368b642ca7a73b4e96a7ae54639a589c4bef8afc651d&lt;/span&gt;
&lt;a name="rest_code_03502d59f03644969beec5a66f9e06ad-3"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; rndc signing -nsec3param &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; 611a1cf6aa1b891b4909ed9d5ebe9d11b452368b642ca7a73b4e96a7ae54639a589c4bef8afc651d example.org
&lt;/pre&gt;&lt;p&gt;A partir de este momento la zona usará &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC3&lt;/a&gt;. Veamos el mismo
ejemplo propuesto en &lt;a class="reference external" href="https://blog.jcea.es/posts/20170528-dnssec_dns_dinamico.html"&gt;Activación de DNSSEC en BIND con DNS dinámico&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_aed188a738034319b15ab2501e9bb927-1"&gt;&lt;/a&gt;51PKTFM618079E60H7F0Q6IF0VT6P0D1.z.bt.jcea.es. 30 IN NSEC3 1 0 10 673A6224876B0486 OEPHDNT06U7U9UURA3UAPV240OVO88SP A RRSIG
&lt;a name="rest_code_aed188a738034319b15ab2501e9bb927-2"&gt;&lt;/a&gt;51PKTFM618079E60H7F0Q6IF0VT6P0D1.z.bt.jcea.es. 30 IN RRSIG NSEC3 8 5 30 20170620071663 ...
&lt;/pre&gt;&lt;p&gt;Como vemos, la respuesta es similar al caso &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt;, pero ahora la
cadena indica el rango de &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Funci%C3%B3n_hash"&gt;hashes&lt;/a&gt; cubierto por la respuesta &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Si por algún motivo queremos volver a usar &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt; en la zona,
haremos:&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_67f650540a5c4897b525e12196253b9b-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; rndc-signing -nsec3param none example.org
&lt;/pre&gt;&lt;div class="section" id="mantenimiento"&gt;
&lt;h2&gt;Mantenimiento&lt;/h2&gt;
&lt;p&gt;El valor de la &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Sal_(criptograf%C3%ADa)"&gt;sal&lt;/a&gt; hay que cambiarla de vez en cuando, tal y como
se describe en &lt;a class="reference external" href="https://blog.jcea.es/posts/20170528-dnssec_dns_dinamico.html"&gt;Activación de DNSSEC en BIND con DNS dinámico&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="referencias"&gt;
&lt;h2&gt;Referencias&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions"&gt;Domain Name System Security Extensions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://kb.isc.org/docs/aa-01311"&gt;DNSSEC Quick Reference Guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://blog.webernetz.net/dnssec-with-nsec3/"&gt;DNSSEC with NSEC3&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>BIND</category><category>DNSSEC</category><category>Privacidad</category><category>Seguridad</category><guid>https://blog.jcea.es/posts/20170624-dnssec_dns_dinamico_nsec3.html</guid><pubDate>Sat, 24 Jun 2017 00:36:00 GMT</pubDate></item><item><title>Por qué es conveniente usar NSEC3 en vez de NSEC en un dominio DNSSEC</title><link>https://blog.jcea.es/posts/20170622-dnssec_nsec3.html</link><dc:creator>Jesús Cea Avión</dc:creator><description>&lt;div&gt;&lt;p&gt;Para empezar con los principios básicos, puedes leer
&lt;a class="reference external" href="https://blog.jcea.es/posts/20140618-introduccion_dnssec.html"&gt;Introducción a DNSSEC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gracias a &lt;a class="reference external" href="https://es.wikipedia.org/wiki/DNSSEC"&gt;DNSSEC&lt;/a&gt; un atacante malicioso no podrá manipular un
registro &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt; porque su firma digital &lt;a class="reference external" href="http://blog.dest-unreach.be/2010/01/17/dnssec-the-rrsig-record"&gt;RRSIG&lt;/a&gt; no puede ser
falsificada. Pero, ¿puede falsificar la no existencia de un
registro? Es decir, ¿puede negar falsamente que un registro &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt;
dado no exista?.&lt;/p&gt;
&lt;p&gt;La respuesta es que no. Cuando &lt;a class="reference external" href="https://es.wikipedia.org/wiki/DNSSEC"&gt;DNSSEC&lt;/a&gt; gestiona una zona, añade
multitud de registros propios. Los más evidentes son las firmas
digitales &lt;a class="reference external" href="http://blog.dest-unreach.be/2010/01/17/dnssec-the-rrsig-record"&gt;RRSIG&lt;/a&gt;, pero hay más. Por ejemplo, los registros &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Los registros &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt; proporcionan &lt;em&gt;authenticated denial of
existence&lt;/em&gt;. Es decir, una prueba criptográfica de que un registro
&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt; no existe.&lt;/p&gt;
&lt;p&gt;Su funcionamiento se describe en el &lt;a class="reference external" href="https://www.rfc-archive.org/getrfc?rfc=4034"&gt;RFC 4034&lt;/a&gt; y el &lt;a class="reference external" href="https://www.rfc-archive.org/getrfc?rfc=4035"&gt;RFC 4035&lt;/a&gt;. Simplificando
mucho, &lt;a class="reference external" href="https://es.wikipedia.org/wiki/DNSSEC"&gt;DNSSEC&lt;/a&gt; ordena todos los registros de la zona de forma
canónica y genera registros &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt; para cubrir los huecos.&lt;/p&gt;
&lt;p&gt;Por ejemplo, si una zona tiene los registros &lt;span class="kbd"&gt;registro1&lt;/span&gt; y
&lt;span class="kbd"&gt;registro3&lt;/span&gt;, pero &lt;strong&gt;NO&lt;/strong&gt; &lt;span class="kbd"&gt;registro2&lt;/span&gt;, una petición de
&lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt; de &lt;span class="kbd"&gt;registro2&lt;/span&gt; se responderá indicando que el registro
no existe y, además, aportará una prueba criptográfica de ello.
Dicha prueba consiste en el registro &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions#Authenticating_NXDOMAIN_responses_and_NSEC"&gt;NSEC&lt;/a&gt; asociado al nombre
&lt;span class="kbd"&gt;registro1&lt;/span&gt; en el campo &lt;em&gt;authority&lt;/em&gt; de la respuesta &lt;a class="reference external" href="https://es.wikipedia.org/wiki/Dns"&gt;DNS&lt;/a&gt;,
indicando que el siguiente nombre de la zona es &lt;span class="kbd"&gt;registro3&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.jcea.es/posts/20170622-dnssec_nsec3.html"&gt;Leer más…&lt;/a&gt; (quedan 3 minutos de lectura)&lt;/p&gt;&lt;/div&gt;</description><category>DNSSEC</category><category>Privacidad</category><category>Seguridad</category><guid>https://blog.jcea.es/posts/20170622-dnssec_nsec3.html</guid><pubDate>Thu, 22 Jun 2017 21:06:00 GMT</pubDate></item></channel></rss>