<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:podcast="https://podcastindex.org/namespace/1.0" xmlns:rawvoice="https://blubrry.com/developer/rawvoice-rss/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Blog Profesional - Eduardo Collado</title>
	<atom:link href="https://www.eduardocollado.com/profesional/feed/" rel="self" type="application/rss+xml"/>
	<link>https://www.eduardocollado.com</link>
	<description>Redes, infraestructura y datacenter desde la experiencia operativa real.</description>
	<lastBuildDate>Tue, 07 Apr 2026 17:28:45 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.eduardocollado.com/wp-content/uploads/2026/02/cropped-podcast7_original-32x32.jpg</url>
	<title>Blog Profesional - Eduardo Collado</title>
	<link>https://www.eduardocollado.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<atom:link href="https://pubsubhubbub.appspot.com/" rel="hub"/>
	<itunes:author>Eduardo Collado</itunes:author>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="https://www.eduardocollado.com/wp-content/uploads/2026/02/podcast7_original.avif"/>
	<itunes:type>episodic</itunes:type>
	<itunes:owner>
		<itunes:name>Eduardo Collado</itunes:name>
		<itunes:email>edu@eduangi.com</itunes:email>
	</itunes:owner>
	<copyright>Eduardo Collado 2016 - 2026</copyright>
	<podcast:license>Eduardo Collado 2016 - 2026</podcast:license>
	<podcast:medium>podcast</podcast:medium>
	<image>
		<title>Blog Profesional - Eduardo Collado</title>
		<url>https://www.eduardocollado.com/wp-content/uploads/2026/02/podcast7_original.avif</url>
		<link>https://www.eduardocollado.com/profesional/</link>
	</image>
	<itunes:category text="Technology"/>
	<itunes:category text="News">
		<itunes:category text="Tech News"/>
	</itunes:category>
	<itunes:category text="Society &amp; Culture">
		<itunes:category text="Personal Journals"/>
	</itunes:category>
	<rawvoice:location>Las Rozas, Madrid, Spain</rawvoice:location>
	<podcast:location rel="subject">Las Rozas, Madrid, Spain</podcast:location>
	<rawvoice:frequency>quincenal</rawvoice:frequency>
	<podcast:podping usesPodping="true"/>
	<rawvoice:subscribe amazon_music="https://music.amazon.es/podcasts/dd25ac6d-10af-4e9a-a7d9-e97609e9f83f/Podcast-de-Eduardo-Collado" deezer="https://www.deezer.com/es/show/394242" feed="https://www.eduardocollado.com/profesional/feed/" iheart="https://www.iheart.com/podcast/256-podcast-de-eduardo-collado-31158715/" spotify="https://open.spotify.com/show/7IkjXOPXozVfUAShVLzmLq"/>
<site xmlns="com-wordpress:feed-additions:1">74150422</site>	<itunes:subtitle>Redes, infraestructura y datacenter desde la experiencia operativa real.</itunes:subtitle><item>
		<title>Nuevos Cursos</title>
		<link>https://www.eduardocollado.com/2026/04/07/nuevos-cursos/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 15:26:06 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Redes]]></category>
		<category><![CDATA[formación]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7749</guid>

					<description><![CDATA[Ahora en la web os he dejado 4 cursos, aunque irán subiendo en cantidad con el tiempo, a veces un post no es suficiente y&#8230;]]></description>
										<content:encoded><![CDATA[<p>Ahora en la web os he dejado 4 cursos, aunque irán subiendo en cantidad con el tiempo, a veces un post no es suficiente y un capítulo del podcast tampoco, así que he decidido ir dejándolo así. De momento los cursos disponibles son:</p>
<p><a href="/cursos/fundamentos-routing/"><strong>Fundamentos de Routing</strong></a><br />
Este curso recorre los principios esenciales del routing IP, desde cómo un router toma decisiones y construye su tabla de rutas hasta el direccionamiento, VLSM, CIDR y diseño de redes IP. A partir de esa base, introduce los tres grandes paradigmas del routing moderno: vector distancia, estado del enlace y path vector, profundizando en protocolos como RIP, OSPF, IS-IS, EIGRP y BGP con enfoque práctico, de diseño y de troubleshooting. El curso es básicamente el libro de Fundamentos de Routing que escribí hace 15 años pero puesto al día, por ejemplo la parte de IPv6 ha cambiado bastante desde entonces.</p>
<p><a href="/cursos/evpn/"><strong>eVPN en el Centro de Datos</strong></a><br />
Este curso explica cómo construir un fabric de centro de datos moderno con VXLAN BGP EVPN, cubriendo tanto la arquitectura física como la lógica del entorno. Recorre el diseño del underlay y del overlay, la gestión del tráfico BUM, los servicios L2 y L3 multi-tenant, la conectividad exterior mediante border leafs y, además, aborda cómo migrar desde redes Ethernet clásicas a un modelo EVPN de forma ordenada y realista.</p>
<p><a href="/cursos/scion/"><strong>SCION</strong></a><br />
Este curso presenta SCION como una arquitectura de Internet de nueva generación diseñada para aportar más seguridad, disponibilidad y control del camino extremo a extremo que el modelo basado en BGP. Explica sus fundamentos, su arquitectura por ISDs y ASes, el funcionamiento de sus planos de control y datos, sus mecanismos criptográficos, el uso de multipath y alta disponibilidad, así como su despliegue real y su posible papel en la evolución futura de Internet.</p>
<p><a href="/cursos/ultraethernet/"><strong>Ultra Ethernet</strong></a><br />
Este curso analiza Ultra Ethernet como la propuesta abierta del Ultra Ethernet Consortium para redes de IA y HPC a gran escala. Parte de los fundamentos de DMA, RDMA, DCB y RoCE, y avanza hacia el transporte UET, el spraying por paquete, la gestión de congestión, la seguridad extremo a extremo, la integración con Linux y Libfabric, y los escenarios de despliegue en infraestructuras pensadas para entrenamiento de IA y computación de altas prestaciones.</p>
<p>Los cursos están divididos en módulos, que serían lo equivalente a capítulos si fuera un libro para independizar temas.</p>
<p>Espero que lo disfrutéis y sobre todo que os sirva de ayuda.</p>
<p>Los cursos los tenéis en la sección de formación, mirad arriba en la barra del blog <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> pero si os da pereza os dejo aquí el enlace directo <a href="https://www.eduardocollado.com/cursos/" target="_blank" rel="noopener">https://www.eduardocollado.com/cursos/</a></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7749</post-id>	</item>
		<item>
		<title>Cambios de Marzo 2026 en EasyPodcast</title>
		<link>https://www.eduardocollado.com/2026/03/28/cambios-de-marzo-2026-en-easypodcast/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 28 Mar 2026 17:19:55 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[easypodcast]]></category>
		<category><![CDATA[podcasting]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7693</guid>

					<description><![CDATA[No exagero si digo que marzo ha sido el mes más intenso desde que arrancó el proyecto. Entre el 7 y el 28 han salido&#8230;]]></description>
										<content:encoded><![CDATA[<p>No exagero si digo que marzo ha sido el mes más intenso desde que arrancó el proyecto. Entre el 7 y el 28 han salido varias versiones seguidas, y no hablo de parches menores: hablo de cambios que afectan de forma real a cómo se trabaja con la herramienta.</p>
<p>El punto de partida fue algo invisible para el usuario pero bastante crítico por dentro. La forma en que EasyPodcast resolvía las URLs de los episodios era secuencial, con un coste que crece conforme crece la biblioteca. Se añadió un índice en la base de datos y se pasó a una búsqueda logarítmica. En podcasts con muchos episodios, <strong>la diferencia se nota de inmediato</strong>. De paso, se corrigió un bug con las URLs absolutas que generaba inconsistencias al resolver enlaces.</p>
<p>A mediados de mes llegó la <strong>versión 1.5.0</strong> con algo que llevaba tiempo pendiente: el panel de administración ahora habla varios idiomas. Español, inglés, alemán, catalán, gallego, francés, portugués e italiano. El selector está accesible desde el propio panel y desde configuración, y el sistema envuelve todos los textos de la interfaz. Nada de parches a medias.</p>
<p>Pero si hay una versión del mes, esa es la <strong>1.6.0</strong>. El editor Markdown desaparece y lo sustituye Jodit, un editor WYSIWYG completo que funciona tanto en episodios como en páginas. <strong>Edición visual real, sin necesidad de aprender ninguna sintaxis.</strong> Además, el contenido pasa a un campo específico y el feed RSS ahora incluye HTML completo en el campo <code>content:encoded</code>, que es como debe ser. También se introduce un campo de descripción corta pensado para SEO y para listados, separando por fin el resumen del contenido largo.</p>
<p>En esa misma versión, y en la <strong>1.6.1</strong> que vino justo después, llegaron varias cosas más. EasyPodcast ahora tiene una <strong>API REST completa</strong> que expone episodios, páginas, configuración, redes sociales, estadísticas y caché, con autenticación por Bearer token y documentación integrada en el propio panel. También se añadió un <strong>grabador de audio directo desde el navegador</strong>, con un detalle importante: si hay errores de validación al guardar, la grabación no se pierde. El 2FA gana la opción de recordar el dispositivo durante siete días, que reduce la fricción sin comprometer la seguridad. Y se añade una herramienta para detectar y eliminar audios e imágenes huérfanos que llevan tiempo ocupando espacio sin que nadie los use. Por último, cuando un episodio no existe, el servidor devuelve un <strong>404 real</strong> en lugar de fallar en silencio. Pequeño detalle, gran diferencia para el SEO.</p>
<figure id="attachment_7694" aria-describedby="caption-attachment-7694" style="width: 800px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" class="wp-image-7694 size-large" src="https://www.eduardocollado.com/wp-content/uploads/2026/03/foto9-1024x683.png" alt="Grabación desde el propio navegador" width="800" height="534" srcset="https://www.eduardocollado.com/wp-content/uploads/2026/03/foto9-1024x683.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2026/03/foto9-300x200.png 300w, https://www.eduardocollado.com/wp-content/uploads/2026/03/foto9-768x512.png 768w, https://www.eduardocollado.com/wp-content/uploads/2026/03/foto9.png 1536w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption id="caption-attachment-7694" class="wp-caption-text">Grabación desde el propio navegador</figcaption></figure>
<p>Las versiones <strong>1.6.3 y 1.6.4</strong>, ya a finales de mes, se centraron en estabilidad. La grabación de audio ya no se pierde si hay errores de validación, el actualizador en Docker deja de sobrescribir el <code>.htaccess</code>, lo que causaba bucles de redirección HTTPS en setups con reverse proxy, y tras actualizar se muestra el changelog de la versión que acaba de instalarse. Cambios pequeños, pero el tipo de cosas que <strong>en producción real marca la diferencia</strong> entre un dolor de cabeza y que todo funcione.</p>
<p>Para cerrar el mes, el 28 llegó la <strong>1.7.0</strong> con un sistema de temas visuales. Seis opciones: Default, Agua, Fuego, Invierno, Hacker y Monocromo. Se aplican en servidor, sin JavaScript de por medio, lo que significa que <strong>no hay ningún destello al cargar la página</strong>. El antiguo modo oscuro basado en localStorage desaparece y lo sustituye este sistema, bastante más sólido y coherente.</p>
<p>En resumen, marzo ha sido menos de funcionalidades aisladas y más de <strong>evolución real del producto</strong>. Mejor base técnica, mejor experiencia de edición, más control vía API y más personalización visual. EasyPodcast está empezando a comportarse más como una plataforma completa que como una herramienta de publicación simple, y este mes lo deja bastante claro.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7693</post-id>	</item>
		<item>
		<title>Bloquear el acceso a las IAs a vuestro contenido</title>
		<link>https://www.eduardocollado.com/2026/03/21/bloquear-el-acceso-a-las-ias-a-vuestro-contenido/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 21 Mar 2026 12:12:21 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[IA]]></category>
		<category><![CDATA[seguridad]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7565</guid>

					<description><![CDATA[Me han preguntado alguna vez que como se puede bloquear el acceso a vuestras páginas web en un servidor Apache a las IAs, y aunque&#8230;]]></description>
										<content:encoded><![CDATA[<p>Me han preguntado alguna vez que como se puede bloquear el acceso a vuestras páginas web en un servidor Apache a las IAs, y aunque bueno, teniendo en cuenta que los crawlers de IA son lo más desagradecido y busco del Mundo podemos pedirlo educadamente y luego bloquear por el user agent, de todos modos ya os digo que en un Mundo sin moral, muchos crawlers de IA deleznables se identifican simplemente como firefox, lamentable.</p>
<p>De todos modos os paso el contenido:</p>
<p><strong>en robots.txt (para pedirlo educadamente)</strong></p>
<pre># ── Crawlers de IA / LLM ─────────────────────────────────

# OpenAI
User-agent: GPTBot
Disallow: /

User-agent: ChatGPT-User
Disallow: /

User-agent: OAI-SearchBot
Disallow: /

# Anthropic
User-agent: anthropic-ai
Disallow: /

User-agent: ClaudeBot
Disallow: /

User-agent: Claude-Web
Disallow: /

# Google IA (Gemini / Bard training)
User-agent: Google-Extended
Disallow: /

# Meta
User-agent: FacebookBot
Disallow: /

# Perplexity
User-agent: PerplexityBot
Disallow: /

# You.com
User-agent: YouBot
Disallow: /

# Common Crawl (usado para entrenar LLMs)
User-agent: CCBot
Disallow: /

# Cohere
User-agent: cohere-ai
Disallow: /

# Diffbot
User-agent: Diffbot
Disallow: /

# ByteDance / TikTok
User-agent: Bytespider
Disallow: /

# Apple
User-agent: Applebot-Extended
Disallow: /

# Otros scrapers conocidos
User-agent: ImagesiftBot
Disallow: /

User-agent: magpie-crawler
Disallow: /

User-agent: DataForSeoBot
Disallow: /

User-agent: AI2Bot
Disallow: /

User-agent: Omgilibot
Disallow: /

User-agent: Timpibot
Disallow: /

User-agent: FriendlyCrawler
Disallow: /</pre>
<p><strong>En el .htaccess (para bloquear esos .user-agents)</strong></p>
<pre>&lt;IfModule mod_rewrite.c&gt;
RewriteCond %{HTTP_USER_AGENT} (GPTBot|ChatGPT-User|OAI-SearchBot|anthropic-ai|ClaudeBot|Claude-Web|Google-Extended|FacebookBot|PerplexityBot|YouBot|CCBot|cohere-ai|Diffbot|Bytespider|Applebot-Extended|ImagesiftBot|magpie-crawler|DataForSeoBot|AI2Bot|Omgilibot|Timpibot|FriendlyCrawler) [NC]
RewriteRule .* - [F,L]
&lt;/IfModule&gt;</pre>
<p>Foto de Markus Spiske: <a href="https://www.pexels.com/es-es/foto/hombre-policia-uniforme-de-espaldas-4682719/" target="_blank" rel="noopener">https://www.pexels.com/es-es/foto/hombre-policia-uniforme-de-espaldas-4682719/</a></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7565</post-id>	</item>
		<item>
		<title>KDE Teleprompter: un teleprompter minimalista para Linux</title>
		<link>https://www.eduardocollado.com/2026/03/11/kde-teleprompter-un-teleprompter-minimalista-para-linux/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 11 Mar 2026 19:47:49 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[kde teleprompter]]></category>
		<category><![CDATA[kdeteleprompter]]></category>
		<category><![CDATA[teleprompter]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7534</guid>

					<description><![CDATA[La historia empieza en YouTube (https://www.youtube.com/shorts/QI15CxNHSOI), como casi todo. Estaba viendo un vídeo y salió el NotchPrompter, una app de teleprompter para Mac que aprovecha&#8230;]]></description>
										<content:encoded><![CDATA[<p>La historia empieza en YouTube (<a href="https://www.youtube.com/shorts/QI15CxNHSOI">https://www.youtube.com/shorts/QI15CxNHSOI</a>), como casi todo. Estaba viendo un vídeo y salió el <a href="https://notchprompter.com/" target="_blank" rel="noopener">NotchPrompter</a>, una app de teleprompter para Mac que aprovecha el notch de los MacBook para meter el texto ahí, justo encima de la cámara. Me pareció una idea genial, con muy buena ejecución. Me enamoré de la idea al momento.</p>
<p>El problema es que yo uso Linux. Más concretamente KDE Plasma, que es mi escritorio de toda la vida. Y claro, NotchPrompter es solo para Mac.</p>
<p>Solución obvia: portarlo a Linux.</p>
<h3>Qué hace</h3>
<p>Una ventana sin marcos que se queda siempre encima de todo y va pasando el texto que tú le metas. Sin más. Lo que hace cualquier teleprompter, pero sin que te instale media internet en el proceso.</p>
<p>Cuando acercas el ratón aparece una barrilla con los controles. Cuando lo alejas, desaparece. Puedes cambiar la velocidad, el tamaño del texto, editar el guion al vuelo o cargar un .txt desde disco.</p>
<p>Los colores son del esquema Catppuccin Mocha porque soy así de friki con estas cosas.</p>
<h3>Qué no hace</h3>
<p>Pues a diferencia de la original para Mac, esta no escucha por donde vas, así que tendrás que estar un poco más atento para regular la velocidad o pausar el texto.</p>
<h3>Por qué PyQt6 y no otra cosa</h3>
<p>Porque soy usuario de KDE Plasma y quería algo que funcionara bien de verdad, no una app web disfrazada ni dependencias de GNOME. PyQt6 te da acceso directo a Qt, que es lo que usa KDE por debajo. El resultado es una ventana nativa, ligera y que se comporta como debe.</p>
<p>El script instalado pesa 25 KB. Veinticinco kilobytes. Que conste.</p>
<h3>Cómo instalarlo</h3>
<p>Si tienes Debian o Ubuntu, descarga el .deb de la página de <a href="https://github.com/educollado/KDETeleprompter/releases" target="_blank" rel="noopener">releases</a> y:</p>
<pre>sudo apt install ./kdeteleprompter_1.0.1_all.deb</pre>
<p>Listo. Las dependencias las gestiona apt solo, no tienes que hacer nada más. Aparece en el lanzador de aplicaciones de KDE y todo.</p>
<p>Si prefieres tirarlo desde el código fuente:</p>
<pre>pip install PyQt6
python3 kdeteleprompter.py</pre>
<p>Los atajos que molan tener memorizados</p>
<pre>┌─────────┬───────────────────────┐
│ Tecla   │     Para qué          │
├─────────┼───────────────────────┤
│ Espacio │     Play / Pausa      │
├─────────┼───────────────────────┤
│ R       │  Volver al principio  │
├─────────┼───────────────────────┤
│ + / -   │ Más o menos velocidad │
├─────────┼───────────────────────┤
│ Ctrl+E  │ Editar el guion       │
├─────────┼───────────────────────┤
│ Escape  │ Cerrar                │
└─────────┴───────────────────────┘</pre>
<p>El código está en GitHub, la licencia es MIT porque el código original era MIT y hay que respetar las licencias, es libre, abierto, lo que quieras:</p>
<p><a href="http://github.com/educollado/KDETeleprompter" target="_blank" rel="noopener">github.com/educollado/KDETeleprompter</a></p>
<p>Si le ves algo mejorable o te peta en tu máquina, abre un issue y lo miramos.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7534</post-id>	</item>
		<item>
		<title>EasyPodcast</title>
		<link>https://www.eduardocollado.com/2026/02/18/easypodcast/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 18 Feb 2026 21:11:59 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[easypodcast]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[podcasting]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[software libre]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7470</guid>

					<description><![CDATA[Puedes leer la documentación oficial de EasyPodcast en https://www.easypodcast.eu/. Llevo tiempo dándole vueltas a una cosa: ¿cómo algo tan sencillo como publicar un podcast se&#8230;]]></description>
										<content:encoded><![CDATA[<blockquote><p><strong>Puedes leer la documentación oficial de EasyPodcast en <a href="https://www.easypodcast.eu/" target="_blank" rel="noopener">https://www.easypodcast.eu/</a>.</strong></p></blockquote>
<p>Llevo tiempo dándole vueltas a una cosa: ¿cómo algo tan sencillo como publicar un podcast se ha convertido en una especie de gymkana tecnológica?</p>
<p><img decoding="async" class="alignleft size-medium wp-image-7511" src="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1-300x200.avif" alt="" width="300" height="200" srcset="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1-300x200.avif 300w, https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1-1024x683.avif 1024w, https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1-768x512.avif 768w, https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1-120x80.avif 120w, https://www.eduardocollado.com/wp-content/uploads/2026/02/foto1.avif 1536w" sizes="(max-width: 300px) 100vw, 300px" />La opción fácil es darse de alta en una plataforma, pagar una cuota, aceptar quince pantallas de configuración, conectar servicios que no sabes muy bien para qué sirven… y al final tú solo querías subir un audio y que el RSS funcionase. La otra opción es montarte un WordPress, instalar un plugin enorme, instalar 10.000 dependencias y al final del todo tienes un podcast, pero creo que a veces no es lo que queremos.</p>
<p>Así que un día quería montar un podcast nuevo y no me apetecía ninguna de las dos opciones, y de ahí salió <strong>EasyPodcast</strong>.</p>
<p>EasyPodcast es un gestor sencillo para publicar podcasts usando PHP y SQLite. Nada de infraestructuras ni de ingeniería aeroespacial, nada de depender de terceros, nada de cosas que no se pueden controlar. Lo mejor: hacérselo uno mismo. Lo subes a tu servidor, lo configuras y te pones a publicar en 5 minutos. Como debería ser. Vamos, que no hace falta pedir audiencia en el Vaticano para sacar un episodio.</p>
<p><img decoding="async" style="width: 100%; max-width: 800px; margin: 20px 0;" src="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto2.avif" alt="EasyPodcast - Vista pública del podcast" /></p>
<p>Yo quería algo que hiciera estrictamente lo necesario y ni una línea más. Al publicar un episodio, se guarda en SQLite, se actualiza el feed RSS y se muestra en la web pública. Punto.</p>
<p>Uso SQLite porque me parece una maravilla infravalorada. Un archivo y listo. No necesitas montar un servidor de base de datos aparte ni complicarte la vida. Al final son muy pocos datos y realmente no lo necesitas, sobre todo si es un proyecto personal. Pero incluso para algo más serio, SQLite es suficiente.</p>
<p>Si ya tienes un VPS pequeño o tu propio servidor, lo puedes tener funcionando antes de que termine el café.</p>
<p><img decoding="async" style="width: 100%; max-width: 800px; margin: 20px 0;" src="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto3.avif" alt="EasyPodcast - Edición de episodios con Markdown" /></p>
<p>No pretende competir con plataformas gigantes ni con soluciones empresariales. No es su guerra. EasyPodcast es para quien quiere control, simplicidad y autonomía. Para quien prefiere tener su feed RSS en casa, bajo su dominio, sin que mañana alguien cambie las condiciones y te deje mirando a Cuenca. Que ya nos conocemos.</p>
<p>El panel de administración es limpio y directo. Subes el audio, rellenas los datos del episodio y a correr. No hay tutorial de 40 minutos en YouTube para entenderlo. Si sabes usar un formulario web, sabes usar EasyPodcast. Y si sabes algo de PHP, además puedes abrir el código y entender qué está pasando. Sin magia negra.</p>
<p><img decoding="async" style="width: 100%; max-width: 800px; margin: 20px 0;" src="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto4.avif" alt="EasyPodcast - Feed RSS y metadatos" /></p>
<p>Con el tiempo le he ido añadiendo las cosas que de verdad hacen falta. Las descripciones de los episodios se escriben en Markdown con vista previa en tiempo real, porque escribir en un textarea pelado en 2025 no tiene ningún sentido. Al subir un MP3, escribe automáticamente los metadatos ID3, incluida la portada, para que el episodio llegue bien presentado a cualquier app de podcast. Hay sitemap, Open Graph y datos estructurados JSON-LD, porque si publicas algo, que al menos Google se entere. Y hay un sistema de copias de seguridad integrado para exportar e importar la base de datos y los ficheros, que uno no quiere depender solo de que el servidor no se muera. Por si acaso.</p>
<p>A partir de la versión 0.7 también tiene modo oscuro, que ya sé que parece una tontería, pero cuando son las once de la noche y estás preparando el episodio de la semana, lo agradeces.</p>
<p><img decoding="async" style="width: 100%; max-width: 800px; margin: 20px 0;" src="https://www.eduardocollado.com/wp-content/uploads/2026/02/foto5.avif" alt="EasyPodcast - Modo oscuro" /></p>
<p>¿Es perfecto? No. Ni lo pretende. Es pequeño a propósito. Es mantenible a propósito. Es sencillo a propósito. Porque a veces lo mejor no es añadir más cosas, sino quitar las que sobran. Que eso parece que cuesta más.</p>
<p>En el fondo, EasyPodcast nace de una idea muy básica: si el estándar del podcasting es abierto y el RSS es abierto, ¿por qué necesitamos intermediarios para publicar un mp3?</p>
<h2>Cómo instalarlo</h2>
<p>La instalación es de las más sencillas que he podido hacer. Sin SSH, sin consola, sin complicaciones. Solo necesitas un servidor con PHP.</p>
<ol>
<li><strong>Descarga el instalador:</strong> ve al repositorio <a href="https://github.com/educollado/EasyPodcast-Installer" target="_blank" rel="noopener">EasyPodcast-Installer en GitHub</a> y descarga el archivo <a href="https://github.com/educollado/EasyPodcast-Installer/blob/main/instalar.php" target="_blank" rel="noopener"><code>instalar.php</code></a>. También puedes descargarlo directamente desde este enlace: <a href="https://raw.githubusercontent.com/educollado/EasyPodcast-Installer/main/instalar.php" target="_blank" rel="noopener">descargar instalar.php</a> (clic derecho → Guardar como).</li>
<li><strong>Súbelo a tu servidor:</strong> copia <code>instalar.php</code> en el directorio raíz donde quieres instalar EasyPodcast. Ese directorio debería estar vacío (o ser el único archivo que haya en él).</li>
<li><strong>Abre el instalador en el navegador:</strong> accede a <code>https://tu-dominio.com/instalar.php</code> y sigue los tres pasos del asistente: comprobación de compatibilidad, verificación del directorio e instalación.</li>
<li><strong>Listo:</strong> el instalador descarga la última versión de EasyPodcast desde GitHub, extrae los archivos, crea la base de datos SQLite y te redirige al panel de administración en <code>/admin.php</code>. El propio instalador intenta borrarse solo al terminar; si no puede, bórralo tú manualmente antes de empezar a usar la aplicación.</li>
</ol>
<p>Requisitos mínimos: PHP 8.0+ con las extensiones <code>pdo_sqlite</code>, <code>sqlite3</code>, <code>zip</code>, <code>gd</code>, <code>fileinfo</code> y <code>xmlwriter</code>. La mayoría de hostings compartidos modernos los tienen activados por defecto.</p>
<p>Si eres de los que tiene servidor propio, te gusta trastear y prefieres depender de ti mismo antes que de una plataforma con suscripción mensual, igual te encaja. Puedes ver el código completo en <a href="https://github.com/educollado/EasyPodcast" target="_blank" rel="noopener">github.com/educollado/EasyPodcast</a> y ver un ejemplo real funcionando en <a href="https://www.aratospodcast.com/" target="_blank" rel="noopener">aratospodcast.com</a>.</p>
<p>La verdad es que me haría mucha ilusión si lo probarais, porque nunca se sabe y a lo mejor es lo que estabais buscando.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7470</post-id>	</item>
		<item>
		<title>Detectores de intrusión en sistemas Linux</title>
		<link>https://www.eduardocollado.com/2026/02/10/detectores-de-intrusion-en-sistemas-linux/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 12:39:10 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[ids]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=7074</guid>

					<description><![CDATA[Introducción En la era digital actual, la seguridad de las redes se ha convertido en una preocupación primordial para organizaciones de todos los tamaños. Con&#8230;]]></description>
										<content:encoded><![CDATA[<h3 class="western">Introducción</h3>
<p>En la era digital actual, la seguridad de las redes se ha convertido en una preocupación primordial para organizaciones de todos los tamaños. Con la creciente sofisticación de los ataques cibernéticos, es imperativo que las infraestructuras de TI no solo estén protegidas por medidas de seguridad perimetral tradicionales, como firewalls y antivirus, sino también por sistemas avanzados de detección y prevención de intrusiones. Estos sistemas son esenciales para identificar, alertar y, en algunos casos, responder automáticamente a actividades maliciosas antes de que puedan causar daño significativo.</p>
<p>Los Sistemas de Detección de Intrusiones (IDS) juegan un papel crucial en la defensa en profundidad, monitoreando el tráfico de red y/o la actividad en los sistemas para detectar patrones de comportamiento sospechosos o conocidos de ataques. Al operar como los centinelas de la red, los IDS proporcionan una capa adicional de seguridad que ayuda a identificar y mitigar las amenazas en tiempo real o de manera retrospectiva, permitiendo a los equipos de seguridad investigar y responder a los incidentes de manera informada.</p>
<p>Dentro del ámbito de los IDS, existen varias herramientas poderosas y ampliamente adoptadas, cada una con sus propias fortalezas, capacidades y enfoques únicos para la detección de intrusiones. En este artículo, nos centraremos en tres de las herramientas más prominentes y sofisticadas disponibles para sistemas Linux: <strong>Snort</strong>, <strong>Suricata</strong> y <strong>Zeek</strong>.</p>
<p><strong>Snort</strong> es uno de los IDS más antiguos y ampliamente utilizados en el mundo. Desarrollado por Sourcefire y ahora bajo el amparo de Cisco, Snort es una herramienta de detección basada en firmas que inspecciona el tráfico de red en busca de patrones específicos que indican posibles intrusiones. Su amplia base de usuarios y su conjunto de reglas actualizadas continuamente lo convierten en una solución de confianza para muchas organizaciones.</p>
<p><strong>Suricata</strong>, por otro lado, es un sistema de detección, prevención e inspección de intrusiones de próxima generación. Desarrollado por la Open Information Security Foundation (OISF), Suricata es conocido por su capacidad para realizar análisis de tráfico en tiempo real, utilizando técnicas de detección basadas en firmas, anomalías y protocolos. Es altamente escalable y puede procesar grandes volúmenes de tráfico, aprovechando las capacidades de procesamiento multihilo.</p>
<p><strong>Zeek</strong> (anteriormente conocido como Bro) se distingue por su enfoque en el análisis de eventos de red de alta fidelidad y la generación de registros detallados de actividad. A diferencia de Snort y Suricata, que se centran en la detección basada en firmas, Zeek proporciona un marco flexible para el análisis de tráfico que permite a los usuarios escribir sus propios scripts de detección. Esto lo hace excepcionalmente poderoso para identificar comportamientos anómalos y complejos en la red que pueden no ajustarse a las firmas de ataque conocidas.</p>
<p>La selección entre Snort, Suricata y Zeek depende de varios factores, incluidas las necesidades específicas de seguridad de la red, la infraestructura existente, los recursos disponibles y la experiencia técnica del equipo de seguridad. Al entender las capacidades y limitaciones de cada herramienta, las organizaciones pueden implementar una solución de detección de intrusiones robusta y efectiva, fortaleciendo significativamente su postura de seguridad en red.</p>
<h3 class="western">¿Qué es un Sistema de Detección de Intrusiones (IDS)?</h3>
<p>Un Sistema de Detección de Intrusiones (IDS) es una herramienta esencial dentro de la ciberseguridad, diseñada para identificar y alertar sobre intentos de intrusión o actividades maliciosas en una red o sistema. Su principal objetivo es monitorear y analizar tanto el tráfico de red como el comportamiento de los sistemas para detectar acciones sospechosas que podrían indicar una amenaza de seguridad. Esto incluye desde intentos de acceso no autorizado hasta ataques más sofisticados, como el malware, el phishing, y otros tipos de ciberataques.</p>
<h4 class="western">Definición y Objetivo de un IDS</h4>
<p>La definición formal de un IDS se centra en su capacidad para identificar patrones de comportamiento anormal o firmas de ataques conocidos, basándose en un conjunto predefinido de reglas o criterios. Estos sistemas se diseñaron con el objetivo de proporcionar una capa adicional de seguridad, complementando las defensas perimetrales tradicionales como firewalls y soluciones antivirus. Al hacerlo, los IDS desempeñan un papel crucial en la detección temprana de posibles incidentes de seguridad, permitiendo a los administradores de red tomar medidas proactivas para mitigar los riesgos antes de que se produzcan daños significativos.</p>
<h4 class="western">Tipos de IDS</h4>
<p>Los sistemas de detección de intrusiones se clasifican generalmente en dos categorías principales, basados en su enfoque de monitoreo:</p>
<ul>
<li><strong>IDS Basados en Red (NIDS):</strong> Estos sistemas se centran en el análisis del tráfico de red que pasa por puntos estratégicos de la red, buscando patrones de tráfico sospechosos o anomalías. Los NIDS son especialmente efectivos para identificar ataques dirigidos a múltiples sistemas dentro de la red, ya que tienen una visión global del tráfico de red.</li>
<li><strong>IDS Basados en Host (HIDS):</strong> A diferencia de los NIDS, los HIDS se instalan en dispositivos individuales y monitorean las actividades internas de ese sistema, incluyendo el sistema de archivos, los registros de eventos del sistema y las operaciones de los usuarios. Estos sistemas son capaces de detectar cambios maliciosos en los archivos del sistema, intentos de escalada de privilegios y otras amenazas específicas del host.</li>
</ul>
<p>Además de estos dos tipos principales, existen variantes híbridas y especializadas de IDS que combinan características de ambos enfoques, ofreciendo una detección de amenazas más comprensiva y adaptativa.</p>
<h4 class="western">Integración en una Estrategia de Seguridad en Profundidad</h4>
<p>La integración de IDS en una estrategia de seguridad en profundidad es fundamental para establecer una defensa robusta contra las amenazas cibernéticas. La seguridad en profundidad se basa en la aplicación de múltiples capas de defensa distribuidas a lo largo de la infraestructura de TI, con el fin de proteger los datos en todos los niveles. Los IDS complementan otras medidas de seguridad al proporcionar detección de amenazas en tiempo real y análisis detallado del comportamiento de la red y de los sistemas.</p>
<p>La implementación efectiva de un IDS dentro de esta estrategia implica no solo su configuración y mantenimiento continuo sino también la integración con otros componentes de seguridad, como sistemas de prevención de intrusiones (IPS), firewalls, sistemas de gestión de eventos e información de seguridad (SIEM) y soluciones de respuesta ante incidentes. Esto permite a las organizaciones no solo detectar amenazas de manera proactiva sino también responder de manera rápida y efectiva, minimizando así el impacto de los ataques.</p>
<p>En conclusión, los sistemas de detección de intrusiones son componentes críticos dentro de la arquitectura de seguridad de cualquier organización. Su capacidad para detectar actividades sospechosas o maliciosas en tiempo real, junto con su integración en una estrategia de seguridad en profundidad, los convierte en herramientas indispensables para la protección contra una amplia gama de ciberamenazas. Al elegir e implementar el tipo adecuado de IDS, las organizaciones pueden fortalecer significativamente su postura de seguridad y su capacidad para responder a incidentes de seguridad.</p>
<h3 class="western">Snort</h3>
<p>Snort es un sistema de prevención y detección de intrusiones de red (NIDS/NIPS) ampliamente reconocido y utilizado en el mundo de la seguridad informática. Desde su creación en 1998 por Martin Roesch, Snort ha evolucionado de ser una simple herramienta de detección de intrusiones a convertirse en un sofisticado sistema de prevención de intrusiones, gracias a su capacidad para analizar el tráfico de red en tiempo real, identificar patrones de ataques y realizar acciones correctivas automáticas.</p>
<h4 class="western">Historia y Desarrollo de Snort</h4>
<p>Snort fue lanzado inicialmente como un proyecto de código abierto, lo que permitió que una comunidad global de desarrolladores y profesionales de seguridad contribuyera a su desarrollo y mejora continua. A lo largo de los años, Snort ha recibido varias actualizaciones significativas que han ampliado sus capacidades de detección y prevención de intrusiones, así como su eficiencia y facilidad de uso. En 2013, Snort fue adquirido por Cisco Systems, lo que marcó el comienzo de una nueva era de desarrollo y soporte profesional, garantizando que Snort siguiera siendo relevante y efectivo frente a las amenazas cibernéticas en constante evolución.</p>
<h4 class="western">Características Principales</h4>
<ul>
<li><strong>Detección Basada en Firmas:</strong> Snort utiliza un extenso conjunto de firmas de ataques, que son patrones de datos que corresponden a comportamientos conocidos de amenazas. Esto permite a Snort identificar y bloquear una amplia gama de ataques, desde intentos de intrusión hasta malware y actividad de exfiltración de datos.</li>
<li><strong>Análisis de Protocolos:</strong> Snort es capaz de inspeccionar y analizar varios protocolos de red, incluidos HTTP, FTP, SMTP, y muchos otros. Esta capacidad permite a Snort detectar anomalías y ataques que se llevan a cabo a través de protocolos específicos, mejorando la precisión de la detección.</li>
<li><strong>Prevención de Intrusiones:</strong> Además de detectar ataques, Snort puede actuar como un sistema de prevención de intrusiones, bloqueando el tráfico malicioso antes de que alcance los sistemas objetivo. Esto se logra mediante la integración de Snort con dispositivos de control de tráfico de red, como firewalls y switches.</li>
</ul>
<h4 class="western">Arquitectura y Componentes Principales</h4>
<ul>
<li><strong>Preprocesadores:</strong> Los preprocesadores son módulos en Snort que preparan el tráfico de red para el análisis, realizando tareas como la normalización de protocolos, la decodificación de flujos y la detección de anomalías. Esto permite a Snort analizar el tráfico de manera más eficiente y efectiva.</li>
<li><strong>Motor de Detección:</strong> El corazón de Snort es su motor de detección, que utiliza algoritmos y patrones de firmas para analizar el tráfico de red en busca de indicadores de ataques. El motor de detección es altamente configurable, permitiendo a los usuarios ajustar la sensibilidad y las especificaciones de detección según las necesidades de su entorno.</li>
<li><strong>Salidas de Alerta:</strong> Cuando Snort detecta una actividad sospechosa, genera alertas que pueden ser enviadas a varios destinos, como archivos de registro, consolas de administración de seguridad o sistemas de gestión de eventos e información de seguridad (SIEM). Esto facilita la monitorización y respuesta rápida a incidentes de seguridad.</li>
</ul>
<h4 class="western">Comunidad y Soporte</h4>
<ul>
<li><strong>Reglas de Snort:</strong> Una de las fortalezas de Snort es su sistema de reglas, que es mantenido tanto por la comunidad de usuarios como por equipos profesionales. Las reglas definen los patrones de tráfico que Snort debe buscar y pueden ser personalizadas para satisfacer las necesidades específicas de cualquier red. La comunidad de Snort juega un papel crucial en el desarrollo y actualización constante de estas reglas, asegurando que Snort pueda detectar las últimas amenazas.</li>
<li><strong>Snort3:</strong> La última versión importante de Snort, Snort3, introduce varias mejoras significativas sobre las versiones anteriores, incluyendo una arquitectura completamente reescrita para mejorar el rendimiento y la eficiencia, un sistema de configuración simplificado y capacidades avanzadas de inspección de tráfico. Snort3 representa el compromiso continuo de la comunidad y Cisco para mantener a Snort a la vanguardia de la detección y prevención de intrusiones.</li>
</ul>
<p>En conclusión, Snort se mantiene como una herramienta indispensable en el arsenal de cualquier profesional de seguridad de redes, ofreciendo capacidades robustas de detección y prevención de intrusiones respaldadas por una comunidad activa y un soporte profesional sólido. Su arquitectura flexible y sistema de reglas potente permiten a Snort adaptarse a una amplia gama de entornos y desafíos de seguridad, haciendo de él una solución de confianza para proteger contra las amenazas cibernéticas modernas.</p>
<h3 class="western">Suricata</h3>
<p>Suricata es un sistema de detección, prevención e inspección de intrusiones de alto rendimiento, desarrollado por la Open Information Security Foundation (OISF). Es conocido por su capacidad para realizar un análisis en profundidad del tráfico de red, utilizando tanto la detección basada en firmas como la detección de anomalías para identificar amenazas. Suricata se distingue por su enfoque en el rendimiento, la escalabilidad y la capacidad de manejar grandes volúmenes de datos en tiempo real.</p>
<h4 class="western">Historia y Desarrollo de Suricata</h4>
<p>Suricata fue lanzado en 2009 por la OISF, con el objetivo de proporcionar una herramienta de detección de intrusiones de próxima generación que fuera de código abierto, altamente escalable y fácil de integrar con otros sistemas de seguridad. Desde su lanzamiento, Suricata ha recibido el apoyo de una comunidad activa de desarrolladores y usuarios que contribuyen a su desarrollo continuo, mejoras en las características y actualizaciones regulares para mantenerse al día con las nuevas amenazas de seguridad.</p>
<h4 class="western">Características Distintivas</h4>
<ul>
<li><strong>Multihilo:</strong> Suricata está diseñado para ser multihilo, lo que le permite procesar grandes cantidades de tráfico de red de manera eficiente al distribuir la carga de trabajo a través de varios núcleos de procesador. Esta característica hace que Suricata sea especialmente adecuado para entornos de alta demanda, donde el rendimiento y la capacidad de respuesta son críticos.</li>
<li><strong>Detección Basada en Firmas y en Anomalías:</strong> Suricata utiliza un sistema híbrido de detección que combina la detección basada en firmas, para identificar patrones de ataque conocidos, con la detección de anomalías, para identificar comportamientos sospechosos o desconocidos. Esto le permite detectar una amplia gama de amenazas, desde ataques conocidos hasta actividades maliciosas novedosas o sofisticadas.</li>
<li><strong>Soporte para IPv6 y TLS:</strong> En reconocimiento a la evolución de las redes modernas, Suricata ofrece soporte completo para IPv6, permitiendo a las organizaciones proteger sus redes mientras adoptan la última generación de protocolos de Internet. Además, Suricata puede inspeccionar el tráfico cifrado TLS, lo que es esencial para detectar amenazas en conexiones seguras que de otro modo estarían ocultas.</li>
</ul>
<h4 class="western">Arquitectura y Flujo de Trabajo</h4>
<p>La arquitectura de Suricata está diseñada para maximizar el uso eficiente de los recursos y la escalabilidad. Al utilizar un enfoque multihilo, Suricata puede distribuir el análisis de tráfico a través de varios núcleos de CPU, lo que permite un procesamiento más rápido y la capacidad de manejar volúmenes de tráfico elevados sin degradar el rendimiento. Suricata también implementa una arquitectura de flujo de trabajo que procesa el tráfico de red en etapas, desde la captura de paquetes hasta el análisis de protocolos, la detección de amenazas y la generación de alertas, optimizando el flujo de trabajo para una detección eficaz y precisa.</p>
<h4 class="western">Integración y Soporte</h4>
<ul>
<li><strong>Open Information Security Foundation (OISF):</strong> Suricata es un proyecto de la OISF, una fundación dedicada al desarrollo de herramientas de seguridad de red de código abierto. La OISF proporciona soporte y recursos para la comunidad de Suricata, facilitando el desarrollo continuo y la adopción de la herramienta en la industria.</li>
<li><strong>Actualizaciones de Reglas:</strong> Suricata se beneficia de un sistema de actualización de reglas dinámico, con contribuciones tanto de la comunidad como de proveedores comerciales. Esto asegura que Suricata esté siempre equipado con las últimas definiciones de amenazas, permitiendo a los usuarios detectar y responder a las amenazas emergentes de manera oportuna. Además, Suricata es compatible con las reglas de Snort, lo que permite a los usuarios aprovechar una amplia base de datos de firmas de ataques conocidos.</li>
</ul>
<p>Suricata representa una solución robusta y de vanguardia en el ámbito de la detección y prevención de intrusiones, destacándose por su rendimiento, escalabilidad y flexibilidad. La combinación de características avanzadas, como el procesamiento multihilo, la detección híbrida y el soporte para tecnologías emergentes, junto con el fuerte soporte de la OISF y una comunidad activa, hacen de Suricata una elección preferente para organizaciones que buscan proteger sus redes contra una amplia gama de amenazas de seguridad.</p>
<h3 class="western">Zeek (anteriormente Bro)</h3>
<p>Zeek es un potente marco de análisis de seguridad de red que se distingue por su enfoque en la inspección de tráfico en profundidad y el análisis de eventos de red. Originalmente conocido como Bro, el proyecto fue renombrado a Zeek en 2018 para reflejar mejor su evolución y capacidades más allá de una herramienta de detección de intrusiones tradicional. Zeek se ha establecido como una solución de seguridad de red flexible y poderosa, apreciada por su capacidad para analizar el tráfico de red en detalle y proporcionar un contexto rico para la actividad de red, lo que facilita la detección de comportamientos maliciosos y anomalías.</p>
<h4 class="western">Historia y Cambio de Nombre de Bro a Zeek</h4>
<p>El sistema fue desarrollado inicialmente en 1994 por Vern Paxson en Lawrence Berkeley National Laboratory como una herramienta de monitoreo de red. Bro fue diseñado para interpretar lo que sucede en la red desde un punto de vista semántico, llenando el vacío entre el análisis de paquetes tradicional y el alto nivel de abstracción de las intrusiones. Con el tiempo, Bro evolucionó para incluir capacidades de análisis de tráfico más sofisticadas, convirtiéndose en una plataforma completa para la seguridad de la red. En 2018, para reflejar su amplio espectro de capacidades y alejarse de las connotaciones negativas asociadas al término «bro», el proyecto fue renombrado a Zeek.</p>
<h4 class="western">Enfoque y Características</h4>
<ul>
<li><strong>Análisis de Eventos de Red:</strong> Zeek se centra en convertir el tráfico de red en eventos de alto nivel, permitiendo una comprensión detallada de la actividad de la red. A diferencia de las herramientas de detección de intrusiones basadas en firmas, Zeek analiza los patrones de comportamiento y las conexiones entre eventos, lo que lo hace efectivo en identificar amenazas sofisticadas y ataques sin firmas conocidas.</li>
<li><strong>Scripting Flexible:</strong> Una de las características más potentes de Zeek es su lenguaje de scripting, que permite a los usuarios escribir sus propios scripts para extender la funcionalidad de Zeek, personalizar el análisis de tráfico y adaptar la herramienta a las necesidades específicas de su entorno de red. Esto hace de Zeek una herramienta extremadamente versátil y adaptable.</li>
<li><strong>Menos Dependiente de Firmas:</strong> A diferencia de otros sistemas de detección de intrusiones, Zeek no depende principalmente de las firmas de ataques conocidos para detectar anomalías. En su lugar, analiza el contexto y el comportamiento del tráfico de red, lo que le permite detectar actividades sospechosas basadas en patrones de comportamiento y anomalías, incluso si el ataque es nuevo o desconocido.</li>
</ul>
<h4 class="western">Arquitectura y Uso</h4>
<p>La arquitectura de Zeek se basa en su motor de eventos, que procesa el tráfico de red y genera eventos de alto nivel para análisis. Los scripts de Zeek definen cómo se analizan y responden a estos eventos, permitiendo una gran personalización. Los usuarios pueden escribir scripts para realizar una amplia gama de tareas, desde la detección de ataques específicos hasta la recolección de estadísticas de red y la generación de registros detallados. Esta capacidad de personalización hace que Zeek sea adecuado para una variedad de entornos de red, desde pequeñas empresas hasta grandes infraestructuras corporativas.</p>
<h4 class="western">Comunidad y Recursos Disponibles</h4>
<ul>
<li><strong>Paquetes de Scripts:</strong> La comunidad de Zeek ofrece una amplia gama de paquetes de scripts para diferentes propósitos, desde la detección de malware y exfiltración de datos hasta el análisis de protocolos específicos. Estos paquetes permiten a los usuarios ampliar rápidamente las capacidades de Zeek para satisfacer sus necesidades específicas.</li>
<li><strong>Formación y Documentación:</strong> Zeek cuenta con un extenso conjunto de recursos de formación y documentación para ayudar a los nuevos usuarios a familiarizarse con la herramienta y para asistir a los usuarios experimentados en la personalización y extensión de Zeek. La comunidad de Zeek organiza regularmente talleres, webinars y conferencias para proporcionar formación y compartir conocimientos.</li>
<li><strong>Comunidad Activa:</strong> La comunidad de Zeek es una de sus mayores fortalezas, con un amplio soporte disponible a través de listas de correo, canales de Slack y foros de discusión. Los usuarios pueden colaborar, compartir conocimientos y obtener ayuda de otros profesionales de seguridad.</li>
</ul>
<p>En resumen, Zeek ofrece una plataforma potente y flexible para el análisis de seguridad de red, destacándose por su enfoque en el análisis de eventos, la flexibilidad de scripting y la capacidad de adaptarse a una amplia gama de entornos de red. Con el apoyo de una comunidad activa y recursos extensos, Zeek continúa siendo una herramienta valiosa para profesionales de la seguridad que buscan una comprensión profunda y detallada de la actividad de su red.</p>
<h3 class="western">Comparación y Casos de Uso</h3>
<p>Al elegir entre Snort, Suricata y Zeek para la seguridad de la red, los profesionales deben considerar varios factores críticos, incluidos el rendimiento, la facilidad de uso, la flexibilidad y el soporte comunitario. Cada uno de estos sistemas de detección de intrusiones ofrece ventajas únicas y puede ser más adecuado para ciertos entornos y necesidades de seguridad.</p>
<h4 class="western">Comparación Directa</h4>
<ul>
<li><strong>Rendimiento:</strong>
<ul>
<li><strong>Snort</strong> es ampliamente reconocido por su robustez y ha sido el estándar de oro en la detección basada en firmas durante muchos años. Sin embargo, puede no ser tan eficiente en el procesamiento de grandes volúmenes de tráfico de red como Suricata, debido a su arquitectura monohilo en versiones anteriores (antes de Snort 3).</li>
<li><strong>Suricata</strong> se destaca por su capacidad de procesamiento multihilo, lo que le permite manejar grandes volúmenes de datos con mayor eficacia, haciendo de Suricata una opción preferida para redes de alto rendimiento.</li>
<li><strong>Zeek</strong> no se centra primariamente en la detección basada en firmas sino en el análisis de eventos de red, lo que requiere un enfoque diferente en términos de rendimiento. Su capacidad para generar análisis detallados y registros de eventos lo hace valioso para investigaciones de seguridad y monitoreo de red en tiempo real, aunque esto puede requerir recursos computacionales significativos para el procesamiento.</li>
</ul>
</li>
<li><strong>Facilidad de Uso:</strong>
<ul>
<li><strong>Snort</strong> tiene una curva de aprendizaje moderada, especialmente para configurar y personalizar reglas. Sin embargo, su amplia adopción y vasta documentación facilitan encontrar guías y soporte.</li>
<li><strong>Suricata</strong> ofrece configuraciones y opciones avanzadas que pueden ser intimidantes para los nuevos usuarios, pero su soporte para reglas de Snort y la adición de capacidades de procesamiento multihilo lo hacen atractivo para usuarios con necesidades de rendimiento específicas.</li>
<li><strong>Zeek</strong> requiere una comprensión más profunda de los scripts y el análisis de eventos de red, lo que puede presentar una curva de aprendizaje más pronunciada. Sin embargo, ofrece flexibilidad sin precedentes para aquellos dispuestos a adentrarse en su lenguaje de scripting.</li>
</ul>
</li>
<li><strong>Flexibilidad:</strong>
<ul>
<li><strong>Snort</strong> y <strong>Suricata</strong> ofrecen flexibilidad en términos de detección de intrusiones y prevención, con Suricata proporcionando capacidades avanzadas de procesamiento de tráfico gracias a su arquitectura multihilo.</li>
<li><strong>Zeek</strong> sobresale en términos de flexibilidad debido a su poderoso lenguaje de scripting, que permite a los usuarios adaptar la herramienta a una amplia gama de escenarios de seguridad específicos.</li>
</ul>
</li>
<li><strong>Soporte Comunitario:</strong>
<ul>
<li><strong>Snort</strong> disfruta de un vasto soporte comunitario, con una gran base de usuarios y desarrolladores contribuyendo a su conjunto de reglas y documentación.</li>
<li><strong>Suricata</strong> también cuenta con una comunidad activa, respaldada por la OISF, y beneficia de actualizaciones regulares y un flujo constante de nuevas características.</li>
<li><strong>Zeek</strong> tiene una comunidad única orientada a investigadores y profesionales de seguridad que comparten scripts, herramientas y mejores prácticas, proporcionando un recurso valioso para usuarios avanzados.</li>
</ul>
</li>
</ul>
<h4 class="western">Elección Dependiendo del Contexto Específico</h4>
<ul>
<li><strong>Tamaño de la Red:</strong>
<ul>
<li>Para redes de gran tamaño y alto volumen de tráfico, <strong>Suricata</strong> puede ser la mejor opción debido a su capacidad de procesamiento multihilo y eficiencia en el manejo de grandes volúmenes de datos.</li>
<li>En redes más pequeñas o en entornos donde el análisis detallado es más crítico que el volumen de tráfico, <strong>Snort</strong> y <strong>Zeek</strong> pueden ser más adecuados.</li>
</ul>
</li>
<li><strong>Recursos Disponibles:</strong>
<ul>
<li>Organizaciones con recursos limitados pueden preferir <strong>Snort</strong> por su amplia base de usuarios y soporte comunitario.</li>
<li>Aquellas con la capacidad de invertir en hardware más potente para el análisis de tráfico podrían inclinarse por <strong>Suricata</strong> o <strong>Zeek</strong>.</li>
</ul>
</li>
<li><strong>Nivel de Experiencia Técnica:</strong>
<ul>
<li><strong>Snort</strong> puede ser una buena entrada para aquellos nuevos en la detección de intrusiones, mientras que <strong>Suricata</strong> ofrece una opción robusta para aquellos con algo más de experiencia.</li>
<li><strong>Zeek</strong> es particularmente adecuado para usuarios con un alto nivel de experiencia técnica que desean una personalización profunda y análisis detallado.</li>
</ul>
</li>
</ul>
<p>La elección entre Snort, Suricata y Zeek debe basarse en una evaluación cuidadosa de las necesidades específicas de seguridad, recursos disponibles y experiencia técnica. Cada herramienta tiene sus fortalezas y puede ser la mejor opción en diferentes contextos. La consideración de estos factores ayudará a garantizar que se elija la solución más adecuada para proteger la infraestructura de red contra amenazas.</p>
<h3 class="western">Implementación y Mejores Prácticas para Sistemas de Detección de Intrusiones (IDS)</h3>
<p>La implementación de un Sistema de Detección de Intrusiones (IDS) es una parte crucial de la estrategia de seguridad en cualquier organización. Su correcta configuración y mantenimiento pueden significar la diferencia entre detectar a tiempo una intrusión potencialmente devastadora y dejar pasar inadvertida una amenaza. Aquí se detallan algunos consejos y mejores prácticas para la implementación efectiva de un IDS, así como para la gestión de alertas y la respuesta a incidentes.</p>
<h4 class="western">Implementación Efectiva de un IDS</h4>
<ul>
<li><strong>Monitoreo del Tráfico de Red:</strong>
<ul>
<li><strong>Cobertura Completa:</strong> Asegúrate de que el IDS tenga visibilidad sobre todo el tráfico de red relevante. Esto puede implicar la colocación estratégica de sensores IDS en puntos clave de la red donde el tráfico de datos es más significativo.</li>
<li><strong>Análisis de Tráfico Cifrado:</strong> Considera la capacidad del IDS para manejar tráfico cifrado, dado que muchas amenazas ahora se ocultan dentro de conexiones seguras. La descifrado, cuando sea legal y éticamente apropiado, puede ser necesario para una inspección profunda del paquete.</li>
</ul>
</li>
<li><strong>Ajuste de la Configuración:</strong>
<ul>
<li><strong>Personalización:</strong> Ajusta las configuraciones y reglas del IDS según el entorno específico de tu red y las políticas de seguridad de tu organización. Lo que funciona para una red puede no ser adecuado para otra.</li>
<li><strong>Minimización de Falsos Positivos y Negativos:</strong> Trabaja continuamente en el ajuste de las reglas para reducir los falsos positivos, que pueden sobrecargar al equipo de seguridad, sin incrementar los falsos negativos, que representan amenazas no detectadas.</li>
</ul>
</li>
<li><strong>Actualización Regular de las Reglas:</strong>
<ul>
<li><strong>Mantente Actualizado:</strong> Las amenazas evolucionan constantemente, por lo que es crucial mantener el sistema de detección de intrusiones actualizado con las últimas reglas y firmas de ataques.</li>
<li><strong>Suscripciones a Fuentes de Inteligencia de Amenazas:</strong> Utiliza fuentes de inteligencia de amenazas para enriquecer las capacidades de detección del IDS, permitiendo que el sistema reconozca las últimas tácticas, técnicas y procedimientos utilizados por los atacantes.</li>
</ul>
</li>
</ul>
<h4 class="western">Gestión de Alertas y Respuesta a Incidentes</h4>
<ul>
<li><strong>Priorización de Alertas:</strong>
<ul>
<li><strong>Clasificación de Alertas:</strong> Desarrolla un sistema para clasificar alertas basado en su gravedad y potencial impacto, lo que permitirá a tu equipo centrarse primero en las más críticas.</li>
<li><strong>Contextualización:</strong> Incorpora contexto a las alertas para ayudar en la rápida evaluación de su importancia. Esto incluye datos sobre los activos afectados, vulnerabilidades conocidas y correlación con otros eventos de seguridad.</li>
</ul>
</li>
<li><strong>Procesos de Respuesta a Incidentes:</strong>
<ul>
<li><strong>Planes de Respuesta Predefinidos:</strong> Establece procedimientos y planes de respuesta específicos para diferentes tipos de alertas. Esto debe incluir pasos claros para la contención, erradicación y recuperación de incidentes.</li>
<li><strong>Automatización:</strong> Donde sea posible, automatiza las respuestas a incidentes comunes para acelerar la resolución y reducir la carga de trabajo manual del equipo de seguridad.</li>
</ul>
</li>
<li><strong>Revisión y Aprendizaje Continuo:</strong>
<ul>
<li><strong>Análisis Post-Incidente:</strong> Después de un incidente, realiza un análisis detallado para entender qué sucedió, cómo se detectó la amenaza, cómo se respondió y cómo se puede mejorar la detección y respuesta en el futuro.</li>
<li><strong>Capacitación y Sensibilización:</strong> Asegúrate de que todos los miembros del equipo de seguridad estén continuamente capacitados en las últimas tendencias de ciberseguridad, técnicas de ataque y estrategias de defensa.</li>
</ul>
</li>
</ul>
<p>Implementar y mantener un IDS eficazmente es una tarea compleja que requiere un enfoque proactivo y un compromiso con la mejora continua. Al seguir estas mejores prácticas, las organizaciones pueden fortalecer significativamente su capacidad para detectar y responder a las amenazas de seguridad, protegiendo así sus activos críticos y manteniendo la integridad de sus sistemas y datos.</p>
<h3 class="western">Conclusión</h3>
<p>Los Sistemas de Detección de Intrusiones (IDS) representan una faceta crítica de la ciberseguridad, crucial para la protección integral de las infraestructuras de Tecnologías de la Información (TI). A medida que el panorama de amenazas evoluciona con ataques cada vez más sofisticados y diversificados, la necesidad de implementar y mantener IDS eficientes se hace más evidente. Estas herramientas no solo ofrecen la capacidad de detectar actividades maliciosas en tiempo real, sino que también proporcionan una visión profunda del tráfico de red, lo que permite a los equipos de seguridad identificar patrones sospechosos y responder adecuadamente antes de que se materialicen daños significativos.</p>
<p>La importancia de los IDS dentro de la infraestructura de TI trasciende la simple detección de ataques. Estos sistemas juegan un papel vital en la estrategia de defensa en profundidad, complementando otras medidas de seguridad como firewalls, sistemas de prevención de intrusiones (IPS), y soluciones antivirus. Al monitorear continuamente el tráfico de red y los sistemas host para detectar actividades anómalas o maliciosas, los IDS proporcionan una capa adicional de seguridad que fortalece la postura general de ciberseguridad de una organización.</p>
<p>La elección del IDS adecuado, sin embargo, no es una decisión que deba tomarse a la ligera. Cada herramienta de IDS, ya sea Snort, Suricata o Zeek, viene con sus propias fortalezas, debilidades y áreas de especialización. La decisión de implementar una solución específica debe basarse en una evaluación detallada de las necesidades específicas de seguridad de la organización, la infraestructura de red existente, los recursos disponibles, y el nivel de experiencia técnica del equipo de seguridad.</p>
<p>Para redes de alto rendimiento que manejan grandes volúmenes de datos, Suricata, con su capacidad de procesamiento multihilo, puede ofrecer la eficiencia necesaria. Para organizaciones que buscan una solución madura y ampliamente soportada con una gran base de reglas, Snort podría ser la opción preferida. Por otro lado, Zeek se destaca por su flexibilidad y capacidad de análisis detallado del tráfico, lo que lo hace ideal para entornos que requieren un alto grado de personalización y análisis forense.</p>
<p>En última instancia, la implementación exitosa de un IDS requiere no solo la selección de la herramienta adecuada, sino también un compromiso continuo con las mejores prácticas de configuración, mantenimiento y respuesta a incidentes. Esto incluye el ajuste regular de la configuración para minimizar los falsos positivos, la actualización constante de las reglas para detectar las últimas amenazas, y el desarrollo de un proceso efectivo de gestión de alertas y respuesta a incidentes.</p>
<p>Los IDS son, sin duda, componentes indispensables de una estrategia de seguridad robusta. Sin embargo, su eficacia está intrínsecamente ligada a la habilidad de la organización para integrarlos adecuadamente dentro de su ecosistema de seguridad, personalizarlos según las necesidades únicas del entorno, y responder de manera efectiva a las alertas generadas. En el contexto actual de amenazas cibernéticas en constante evolución, la capacidad de una organización para proteger sus activos de información depende en gran medida de su enfoque proactivo hacia la seguridad de la red, en el cual los IDS juegan un papel central.</p>
<h3 class="western">Referencias</h3>
<p>La implementación y gestión eficaces de los Sistemas de Detección de Intrusiones (IDS) como Snort, Suricata y Zeek requieren acceso a una amplia gama de recursos de aprendizaje y soporte. A continuación, se presenta una lista de referencias útiles, incluyendo documentación oficial, estudios de caso, tutoriales y recursos comunitarios para cada uno de estos sistemas.</p>
<h4 class="western">Snort</h4>
<ul>
<li><strong>Documentación Oficial:</strong> La documentación oficial de Snort proporciona una guía exhaustiva sobre la instalación, configuración y operación de Snort. Disponible en: https://www.snort.org/documents</li>
<li><strong>Tutoriales:</strong> Los tutoriales de Snort, disponibles en su sitio web oficial y en plataformas como YouTube, ofrecen instrucciones paso a paso para usuarios de todos los niveles.</li>
<li><strong>Recursos Comunitarios:</strong> La comunidad de Snort en https://www.snort.org/community es un lugar excelente para encontrar soporte, compartir configuraciones y discutir las mejores prácticas.</li>
<li><strong>Estudios de Caso:</strong> Diversos estudios de caso sobre la implementación de Snort en entornos empresariales pueden ser encontrados a través de búsquedas en internet, proporcionando perspectivas reales sobre su aplicación y beneficios.</li>
</ul>
<h4 class="western">Suricata</h4>
<ul>
<li><strong>Documentación Oficial:</strong> La Open Information Security Foundation (OISF) mantiene una documentación detallada de Suricata, que es esencial para cualquier implementación. Disponible en: https://suricata.readthedocs.io/en/suricata-6.0.0/</li>
<li><strong>Tutoriales:</strong> Hay una amplia gama de tutoriales disponibles en línea para ayudar a los usuarios a comenzar con Suricata, desde la configuración inicial hasta el análisis avanzado de tráfico.</li>
<li><strong>Recursos Comunitarios:</strong> El foro de Suricata en https://forum.suricata.io/ y otros grupos en plataformas de redes sociales son excelentes recursos para obtener soporte y consejos de la comunidad.</li>
<li><strong>Estudios de Caso:</strong> Investigaciones y publicaciones específicas sobre el uso de Suricata en diferentes sectores industriales pueden proporcionar una visión valiosa sobre su adaptabilidad y eficacia.</li>
</ul>
<h4 class="western">Zeek</h4>
<ul>
<li><strong>Documentación Oficial:</strong> La documentación de Zeek es un recurso invaluable que ofrece una visión completa sobre cómo utilizar y personalizar Zeek. Disponible en: https://docs.zeek.org/en/current/</li>
<li><strong>Tutoriales:</strong> Los tutoriales específicos de Zeek, que van desde configuraciones básicas hasta el desarrollo de scripts avanzados, son accesibles a través de su sitio web oficial y plataformas de aprendizaje en línea.</li>
<li><strong>Recursos Comunitarios:</strong> La comunidad de Zeek, accesible en https://zeek.org/get-involved/, ofrece una amplia gama de recursos, incluyendo una lista de correo, Slack y eventos como ZeekWeek para fomentar el aprendizaje y la colaboración.</li>
<li><strong>Estudios de Caso:</strong> Los estudios de caso sobre Zeek ofrecen insights sobre cómo esta herramienta se ha implementado en entornos complejos para resolver problemas de seguridad específicos.</li>
</ul>
<p>Estos recursos representan puntos de partida esenciales para aquellos interesados en profundizar en la teoría y práctica de los IDS. Ya sea que estés buscando implementar un nuevo sistema de detección de intrusiones, optimizar una configuración existente o simplemente expandir tu conocimiento en el área, la documentación oficial, tutoriales, recursos comunitarios y estudios de caso proporcionan una base sólida sobre la cual construir tu experiencia.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7074</post-id>	</item>
		<item>
		<title>Controlar el User-Agent</title>
		<link>https://www.eduardocollado.com/2023/09/07/controlar-el-user-agent/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 07 Sep 2023 06:19:16 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[user-agent]]></category>
		<category><![CDATA[web]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6815</guid>

					<description><![CDATA[En un grupo de telegram privado en el que estoy con unos amigos ha saltado un tema que me parece muy interesante y básicamente decía&#8230;]]></description>
										<content:encoded><![CDATA[<p>En un grupo de telegram privado en el que estoy con unos amigos ha saltado un tema que me parece muy interesante y básicamente decía que el contenido de Internet está siendo absorbido por las IAs y que al final llegaremos a un mundo de contenido de pago.</p>
<p>El tema social es muy interesante, pero a mi me ha llamado la atención el tema de los bots, porque se hablaba de un bot llamado CCBot que debe de ser un bot con un gusto excelente porque por esta web ya ha pasado, de hecho este año lleva ya 688 visitas, que no son muchas, pero sí las suficientes para haber visto lo que le interesaba y haberlo procesado.</p>
<p>Además tenemos el bot GPTBot que ha visitado este humilde blog ya 1495 veces.</p>
<p>No se qué hará ese bot en concreto, pero parece ser que alimenta a Common Crawl, uno de los mayores conjuntos de datos de IA. El bot BGPBot supongo que como su nombre indica es el bot de ChatGPT y GPT-4.</p>
<p>El tema aquí está en que si esos bots revisan tu web y luego sirven el contenido desde sus aplicaciones, por supuesto sin mencionar desde donde lo han obtenido, al final la gente va a dejar de revisar las webs.</p>
<p>Ante esto hay quien prefiere bloquear estos bots, realmente los <em>user-agent</em> que usan, ¿pero como se hace?, simplemente modificando en el .htaccess de tu web y añadiendo un par de líneas como estas:</p>
<pre>#BLOQUEAR CRAWLERS INDESEADOS
RewriteCond %{HTTP_USER_AGENT} (CCBot|GPTBot) [NC]
RewriteRule .* - [R=403,L]</pre>
<p>Obviamente a la lista podéis añadir todos aquellos bots que consideréis indeseables para vuestra web.</p>
<p>Ahora, ¿esto sirve para algo? Pues sí, si una visita se identifica con un bot de ese tipo le dará un 403 y no podrá cargar la web.</p>
<p>Todo tiene su user-agent, por ejemplo, si usáis Firefox el user-agent será Mozilla/5.0, pero esto es cambiable, para hacerlo podéis seguir los siguientes pasos:</p>
<ol>
<li>Abrir about:config</li>
<li>Aceptar el aviso</li>
<li>Buscar general.useragent.override, que no va a estar.</li>
<li>Pinchar en cadena y en el botón +</li>
<li>Ahora te saldrá un recuadro para rellenar, ahí puedes poner el user-agent que quieras</li>
</ol>
<p>Una vez cambiado el user-agent cuando visites una web saldrá el user-agent que le hayas puesto ahí.</p>
<p>Foto de cabecera de Mat Kedzia: <a href="https://www.pexels.com/es-es/foto/foto-de-primer-plano-de-la-arana-2091017/" target="_blank" rel="noopener">https://www.pexels.com/es-es/foto/foto-de-primer-plano-de-la-arana-2091017/</a></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6815</post-id>	</item>
		<item>
		<title>eVPN con Nokia</title>
		<link>https://www.eduardocollado.com/2023/06/17/evpn-con-nokia/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 17 Jun 2023 16:26:57 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[evpn]]></category>
		<category><![CDATA[nokia]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6786</guid>

					<description><![CDATA[Pues hoy nos hemos sentado Aitor Osuna (https://nubus.link/) y yo delante de la cámara y hemos estado charlando un poco de eVPN y Aitor me&#8230;]]></description>
										<content:encoded><![CDATA[<p>Pues hoy nos hemos sentado Aitor Osuna (<a href="https://nubus.link/" target="_blank" rel="noopener">https://nubus.link/</a>) y yo delante de la cámara y hemos estado charlando un poco de eVPN y Aitor me ha estado contando un poco, muy interesante y me gustaría compartirlo con vosotros.</p>
<p><iframe class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/1Ue5MKCvWMQ?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6786</post-id>	</item>
		<item>
		<title>Encaminamiento en el Centro de Datos con plataformas Open Source</title>
		<link>https://www.eduardocollado.com/2023/06/14/encaminamiento-en-el-centro-de-datos-con-plataformas-open-source/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 14 Jun 2023 08:42:22 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Redes]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[vyos]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6781</guid>

					<description><![CDATA[El pasado sábado 10 de Junio fui invitado por la gente de KDE España para hablar en el Akademy 2023 en Málaga. La presentación versó&#8230;]]></description>
										<content:encoded><![CDATA[<p>El pasado sábado 10 de Junio fui invitado por la gente de <a href="https://www.kde-espana.org/" target="_blank" rel="noopener">KDE España</a> para hablar en el <a href="https://www.kde-espana.org/akademy-es-2023" target="_blank" rel="noopener">Akademy 2023</a> en Málaga.</p>
<p>La presentación versó en una introducción a <a href="https://vyos.org/" target="_blank" rel="noopener">Vyos</a> en el Centro de Datos, porque al fin y al cabo es lo que usamos en <a href="https://tecnocratica.net/" target="_blank" rel="noopener">Tecnocrática</a> para la red.</p>
<p>La presentación fue muy amena, al menos a mi me resultó muy amena gracias a aquellas personas que asistieron y que quiero darles las gracias de nuevo.</p>
<p>La presentación se grabó, pero en la grabación no se ve muy bien lo que se estaba proyectando así que he vuelto a grabarla para que podáis tener las diapos.</p>
<p>El vídeo lo tenéis en el canal de You Tube que hemos abierto en Tecnocrática (<a href="https://www.youtube.com/@TecnocraticaNet" target="_blank" rel="noopener">https://www.youtube.com/@TecnocraticaNet</a>)</p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/z2mueCzZluI?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
<p>De todos modos aquí debajo os dejo las configuraciones usadas:</p>
<pre>VyOS1
=====
configure
set system host-name vyos1
set interfaces ethernet eth1 address 198.51.100.1/24
set interfaces loopback lo address 192.0.2.1/32

set protocols ospf area 0 network '198.51.100.0/24'
set protocols ospf area 0 network '192.0.2.1/32'
set protocols ospf interface eth1
set protocols ospf redistribute connected


VyOS2
=====
configure
set system host-name vyos2
set interfaces ethernet eth1 address 198.51.100.2/24
set interfaces loopback lo address 192.0.2.2/32

set protocols ospf area 0 network '198.51.100.0/24'
set protocols ospf area 0 network '192.0.2.2/32'
set protocols ospf interface eth1
set protocols ospf redistribute connected


VyOS3
=====
configure
set system host-name vyos3
set interfaces ethernet eth1 address 198.51.100.3/24
set interfaces loopback lo address 192.0.2.3/32

set protocols ospf area 0 network '198.51.100.0/24'
set protocols ospf area 0 network '192.0.2.3/32'
set protocols ospf interface eth1
set protocols ospf redistribute connected


=============
LABORATORIO 2
=============

VyOS3
=====
set protocols ospf default-information originate


set interfaces ethernet eth2 address 203.0.113.1/24


set protocols ospf area 0 network '203.0.113.0/24' ?????????????


VyOS4
=====
configure
set system host-name vyos4
set interfaces ethernet eth0 address 203.0.113.2/24


VyOS3
=====
configure
set protocols bgp system-as '15954'
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast
set protocols bgp neighbor 203.0.113.2 remote-as 100
set protocols bgp address-family ipv4-unicast import
set protocols bgp parameters router-id '203.0.113.1'


set protocols bgp address-family ipv4-unicast network 192.168.150.0/24


set policy route-map Todo rule 1 action 'permit'
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast route-map export 'Todo'
set protocols bgp neighbor 203.0.113.2 address-family ipv4-unicast route-map import 'Todo'


VyOS4
=====
configure
set protocols bgp system-as 100

set protocols bgp neighbor 203.0.113.1 address-family ipv4-unicast
set protocols bgp neighbor 203.0.113.1 remote-as 15954
set protocols bgp address-family ipv4-unicast import
set protocols bgp parameters router-id 203.0.113.2




set policy route-map Todo rule 1 action 'permit'
set protocols bgp neighbor 203.0.113.1 address-family ipv4-unicast route-map export 'Todo'
set protocols bgp neighbor 203.0.113.1 address-family ipv4-unicast route-map import 'Todo'</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6781</post-id>	</item>
		<item>
		<title>Consideraciones de seguridad operativa para redes Ipv6</title>
		<link>https://www.eduardocollado.com/2023/04/28/consideraciones-de-seguridad-operativa-para-redes-ipv6/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Fri, 28 Apr 2023 18:00:12 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Redes]]></category>
		<category><![CDATA[ipv6]]></category>
		<category><![CDATA[seguridad]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6751</guid>

					<description><![CDATA[El direccionamiento es uno de los elementos más importantes a considerar cuando se trata de la postura de seguridad de una red, ya que el&#8230;]]></description>
										<content:encoded><![CDATA[<div class="flex relative flex-col im:pb-0 w-full im:w-[50%] bg-[#FAFAFA] h-auto items-center overflow-y-auto im:h-[340px] im:overflow-y-auto min-h-[50%] h-[60%] ">
<div class="im:h-full w-full max-h-full paraphrase-result">
<div class="h-full pt-5">
<div class="relative flex flex-col justify-between im:h-full max-h-full overflow-y-auto">
<div class="relative flex max-h-full justify-start im:max-h-full overflow-y-auto">
<p class="px-4 whitespace-pre-line text4 p-0 pb-5 m-0 w-full im:h-[280px]"><span class="text-brand-02">El </span><span class="">direccionamiento </span><span class="text-brand-02">es </span><span class="text-brand-02">uno </span><span class="">de </span><span class="">los </span><span class="text-brand-02">elementos </span><span class="text-brand-02">más </span><span class="text-brand-02">importantes </span><span class="text-brand-02">a </span><span class="text-brand-02">considerar </span><span class="text-brand-02">cuando </span><span class="">se </span><span class="">trata </span><span class="">de </span><span class="">la </span><span class="">postura </span><span class="">de </span><span class="">seguridad </span><span class="">de </span><span class="">una </span><span class="">red, </span><span class="text-brand-02">ya </span><span class="">que </span><span class="text-brand-02">el </span><span class="text-brand-02">tipo </span><span class="">de </span><span class="">arquitectura </span><span class="">de </span><span class="">direccionamiento </span><span class="text-brand-02">elegido </span><span class="">para </span><span class="">una </span><span class="">implementación </span><span class="">específica </span><span class="">de </span><span class="">IPv6 </span><span class="">puede </span><span class="">tener </span><span class="">un </span><span class="text-brand-02">efecto </span><span class="">significativo </span><span class="">en </span><span class="">las </span><span class="text-brand-02">capacidades </span><span class="">de </span><span class="">enrutamiento, </span><span class="">filtrado </span><span class="">de </span><span class="">tráfico </span><span class="">y </span><span class="text-brand-02">registro. </span><span class="">Por </span><span class="text-brand-02">tanto, </span><span class="text-brand-02">es </span><span class="text-brand-02">esencial </span><span class="text-brand-02">conocer </span><span class="text-brand-02">a </span><span class="text-brand-02">fondo </span><span class="">los </span><span class="text-brand-02">distintos </span><span class="">tipos </span><span class="">de </span><span class="">direcciones </span><span class="">IPv6 </span><span class="">y </span><span class="">sus </span><span class="">implicaciones </span><span class="">para </span><span class="">la </span><span class="">seguridad, </span><span class="">que </span><span class="">se </span><span class="">presentan </span><span class="">en </span><span class="">detalle </span><span class="">en </span><span class="">esta </span><span class="text-brand-02">sección. </span></p>
<p class="px-4 whitespace-pre-line text4 p-0 pb-5 m-0 w-full im:h-[280px]"><span class="text-brand-02">Las </span><span class="text-brand-02">cabeceras </span><span class="">de </span><span class="text-brand-02">extensión </span><span class="text-brand-02">también </span><span class="text-brand-02">son </span><span class="">un </span><span class="text-brand-02">aspecto </span><span class="text-brand-02">crucial </span><span class="text-brand-02">a </span><span class="">tener </span><span class="">en </span><span class="text-brand-02">cuenta, </span><span class="text-brand-02">ya </span><span class="">que </span><span class="text-brand-02">son </span><span class="">una </span><span class="">de </span><span class="">las </span><span class="">principales </span><span class="text-brand-02">distinciones </span><span class="">técnicas </span><span class="">entre </span><span class="">IPv4 </span><span class="">e </span><span class="">IPv6. </span><span class="text-brand-02">Además, </span><span class="text-brand-02">poseen </span><span class="text-brand-02">algunas </span><span class="">propiedades </span><span class="">de </span><span class="">seguridad </span><span class="">interesantes, </span><span class="">y </span><span class="text-brand-02">a </span><span class="text-brand-02">veces </span><span class="text-brand-02">incluso </span><span class="text-brand-02">desafiantes. </span><span class="">Por </span><span class="text-brand-02">este </span><span class="text-brand-02">motivo, </span><span class="">las </span><span class="text-brand-02">cabeceras </span><span class="">de </span><span class="text-brand-02">extensión </span><span class="">se </span><span class="text-brand-02">tratan </span><span class="">en </span><span class="">una </span><span class="">sección </span><span class="">específica. </span></p>
<p>La seguridad de la capa de enlace es un componente esencial de la seguridad de las redes IPv6, y esta sección examina los mecanismos de comunicación local desde un punto de vista tanto ofensivo como defensivo. Los temas principales tratados en esta sección incluyen los ataques NDP, los anuncios de router deshonestos y los mecanismos de protección asociados a estas actividades. Es importante señalar que estos temas difieren significativamente entre las redes IPv4 e IPv6.</p>
<p>La seguridad del plano de control es otro tema crucial cuando se habla de la seguridad de la infraestructura, y se le dedica una sección específica debido a su importancia. En esta sección se examinan las medidas de seguridad asociadas al plano de control de una red IPv6, y se analizan las mejores prácticas para protegerlo. Al igual que en la sección de seguridad de la capa de enlace, existen grandes diferencias entre las redes IPv4 e IPv6 en lo que se refiere a sus respectivas medidas de seguridad del plano de control. Por ello, es esencial comprender ambas redes y sus protocolos de seguridad para garantizar una red lo más segura posible.</p>
<p>La seguridad del encaminamiento es una preocupación primordial cuando se trata de redes IPv6, y las mismas buenas prácticas de seguridad que se aplican a las redes IPv4 deben aplicarse también a las IPv6. Por ejemplo, la <a href="https://www.rfc-editor.org/rfc/rfc7454.txt" target="_blank" rel="noopener">RFC 7454 <em>BGP Operations and Security</em></a> proporciona una excelente orientación sobre las mejores prácticas para las redes IPv6.</p>
<p>Sin embargo, cuando se trata de registro y supervisión, hay algunos elementos de la arquitectura IPv6 que tienen un impacto significativo. Por ejemplo, la naturaleza efímera de las direcciones IPv6 y el hecho de que normalmente puedan coexistir varias de ellas en una interfaz determinado puede suponer un reto, al igual que el formato general de las direcciones IPv6. Para abordar estas cuestiones, las organizaciones deben tener en cuenta los detalles que se tratan en este segmento. También es importante asegurarse de que se asignan los recursos necesarios para garantizar que el registro y la supervisión de la seguridad se realizan correctamente.</p>
<p>Las organizaciones suelen pasar por alto las tecnologías de transición/coexistencia, y no implementan correctamente la seguridad de doble pila. Por eso muchas redes están considerando la opción de pasar a ser sólo v6, ya que elimina la necesidad de tales implementaciones. Las tecnologías de túnel también pueden ser una fuente de problemas para los profesionales de la seguridad, y deben tenerse en cuenta a la hora de desarrollar una RFC. Este fue un tema muy debatido durante el desarrollo de la RFC, ya que muchos creían que los problemas de seguridad no estaban causados por el propio IPv6, sino por problemas operativos en las redes IPv4. Es importante comprender los posibles problemas de seguridad que pueden surgir de las implementaciones de doble pila y las tecnologías de tunelización, y tomar las medidas necesarias para garantizar que las redes sean lo más seguras posible.</p>
<p class="px-4 whitespace-pre-line text4 p-0 pb-5 m-0 w-full im:h-[280px]"><span class=""> El </span><span class="text-brand-02">fortalecimiento </span><span class="">general </span><span class="">de </span><span class="text-brand-02">los </span><span class="text-brand-02">dispositivos </span><span class="text-brand-02">es </span><span class="text-brand-02">una </span><span class="text-brand-02">parte </span><span class="text-brand-02">esencial </span><span class="">de </span><span class="text-brand-02">cualquier </span><span class="">documento </span><span class="">de </span><span class="">orientación </span><span class="">sobre </span><span class="">seguridad, </span><span class="text-brand-02">ya </span><span class="">que </span><span class="text-brand-02">sirve </span><span class="text-brand-02">para </span><span class="text-brand-02">protegerlos </span><span class="">de </span><span class="text-brand-02">ataques </span><span class="text-brand-02">maliciosos. </span><span class="text-brand-02">Es </span><span class="text-brand-02">importante </span><span class="text-brand-02">asegurarse </span><span class="">de </span><span class="">que </span><span class="text-brand-02">todos </span><span class="text-brand-02">los </span><span class="text-brand-02">dispositivos </span><span class="text-brand-02">están </span><span class="text-brand-02">debidamente </span><span class="text-brand-02">reforzados, </span><span class="text-brand-02">ya </span><span class="">que </span><span class="text-brand-02">cualquier </span><span class="text-brand-02">dispositivo </span><span class="">no </span><span class="text-brand-02">seguro </span><span class="text-brand-02">podría </span><span class="text-brand-02">ser </span><span class="text-brand-02">una </span><span class="text-brand-02">puerta </span><span class="">de </span><span class="text-brand-02">entrada </span><span class="text-brand-02">para </span><span class="text-brand-02">agentes </span><span class="text-brand-02">maliciosos. </span><span class="text-brand-02">Cuando </span><span class="">se </span><span class="text-brand-02">trata </span><span class="">de </span><span class="text-brand-02">consideraciones </span><span class="">de </span><span class="">seguridad </span><span class="">específicas </span><span class="">de </span><span class="">la </span><span class="text-brand-02">empresa, </span><span class="">la </span><span class="text-brand-02">implantación </span><span class="">de </span><span class="">IPv6 </span><span class="">en </span><span class="">entornos </span><span class="">empresariales </span><span class="text-brand-02">requiere </span><span class="text-brand-02">una </span><span class="text-brand-02">reflexión </span><span class="text-brand-02">adicional, </span><span class="text-brand-02">como </span><span class="text-brand-02">estipula </span><span class="">el </span><span class="">documento </span><span class="text-brand-02">Enterprise </span><span class="">IPv6 </span><span class="text-brand-02">Implementation </span><span class="text-brand-02">Guidelines </span><span class="">RFC </span><span class="">7381. </span><span class="text-brand-02">Para </span><span class="text-brand-02">garantizar </span><span class="">la </span><span class="">seguridad </span><span class="">de </span><span class="">la </span><span class="text-brand-02">red, </span><span class="text-brand-02">hemos </span><span class="">dedicado </span><span class="">un </span><span class="">capítulo </span><span class="text-brand-02">entero </span><span class="">a </span><span class="text-brand-02">este </span><span class="text-brand-02">tema, </span><span class="">que </span><span class="">a </span><span class="">su </span><span class="">vez </span><span class="">se </span><span class="">divide </span><span class="">en </span><span class="">dos </span><span class="text-brand-02">subsecciones: </span><span class="text-brand-02">una </span><span class="">sobre </span><span class="">seguridad </span><span class="text-brand-02">externa </span><span class="">y </span><span class="text-brand-02">otra </span><span class="">sobre </span><span class="">seguridad </span><span class="text-brand-02">interna. </span></p>
<p class="px-4 whitespace-pre-line text4 p-0 pb-5 m-0 w-full im:h-[280px]"><span class="">La </span><span class="">seguridad </span><span class="text-brand-02">externa </span><span class="">se </span><span class="text-brand-02">centra </span><span class="">en </span><span class="">la </span><span class="">seguridad </span><span class="">de </span><span class="text-brand-02">los </span><span class="text-brand-02">datos </span><span class="">que </span><span class="text-brand-02">viajan </span><span class="text-brand-02">entre </span><span class="">la </span><span class="text-brand-02">empresa </span><span class="">y </span><span class="text-brand-02">los </span><span class="text-brand-02">usuarios </span><span class="">externos, </span><span class="text-brand-02">mientras </span><span class="">que </span><span class="">la </span><span class="">seguridad </span><span class="text-brand-02">interna </span><span class="">se </span><span class="text-brand-02">centra </span><span class="">en </span><span class="">la </span><span class="">seguridad </span><span class="">de </span><span class="text-brand-02">los </span><span class="text-brand-02">datos </span><span class="text-brand-02">dentro </span><span class="">de </span><span class="">la </span><span class="text-brand-02">empresa. </span><span class="text-brand-02">Ambas </span><span class="">subsecciones </span><span class="text-brand-02">abarcan </span><span class="text-brand-02">temas </span><span class="text-brand-02">como </span><span class="">la </span><span class="text-brand-02">autenticación, </span><span class="">la </span><span class="text-brand-02">autorización, </span><span class="">el </span><span class="text-brand-02">cifrado </span><span class="">y </span><span class="text-brand-02">otros. </span><span class="text-brand-02">Es </span><span class="text-brand-02">importante </span><span class="text-brand-02">señalar </span><span class="">que </span><span class="">la </span><span class="text-brand-02">implantación </span><span class="">de </span><span class="">IPv6 </span><span class="">en </span><span class="">entornos </span><span class="">empresariales </span><span class="text-brand-02">requiere </span><span class="text-brand-02">una </span><span class="text-brand-02">comprensión </span><span class="text-brand-02">exhaustiva </span><span class="">de </span><span class="text-brand-02">los </span><span class="text-brand-02">protocolos </span><span class="">y </span><span class="text-brand-02">prácticas </span><span class="">de </span><span class="">seguridad. </span><span class="">Por </span><span class="text-brand-02">tanto, </span><span class="text-brand-02">es </span><span class="text-brand-02">esencial </span><span class="text-brand-02">contar </span><span class="text-brand-02">con </span><span class="">un </span><span class="text-brand-02">equipo </span><span class="">de </span><span class="text-brand-02">profesionales </span><span class="text-brand-02">dedicados </span><span class="">y </span><span class="text-brand-02">versados </span><span class="">en </span><span class="">las </span><span class="text-brand-02">últimas </span><span class="text-brand-02">tendencias </span><span class="">y </span><span class="text-brand-02">tecnologías </span><span class="">de </span><span class="">seguridad </span><span class="text-brand-02">para </span><span class="text-brand-02">proteger </span><span class="">la </span><span class="text-brand-02">red. </span></p>
<p>Las consideraciones de seguridad del proveedor de servicios son de vital importancia cuando se despliegan redes IPv6. Es esencial que se establezcan los controles de seguridad necesarios para garantizar que la red está adecuadamente protegida. Estos controles de seguridad deben detallarse en la RFC, y deben cubrir aspectos como la autenticación, el cifrado y el control de acceso. Además, deben tenerse en cuenta muchos aspectos específicos del operador, como la interceptación legal. Esto implica la supervisión y recopilación de datos que se consideren de interés legal o reglamentario. Es esencial que se establezcan medidas de seguridad para garantizar que estos datos se recogen y almacenan de forma segura. Además, los operadores deben disponer de un modo eficaz de acceder a los datos y analizarlos, garantizando al mismo tiempo que los datos sólo se utilicen para los fines previstos.</p>
<div class="sticky top-[50%] opacity-1 shadow-lg right-[0px]">
<div class="z-10 pr-4 cursor-pointer hidden im:flex justify-start items-start"></div>
</div>
</div>
</div>
</div>
</div>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6751</post-id>	</item>
		<item>
		<title>Posibles cambio en los .net por parte de ICANN</title>
		<link>https://www.eduardocollado.com/2023/04/24/cambio-net-icann/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 24 Apr 2023 13:33:41 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[libertad]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6756</guid>

					<description><![CDATA[En la web freespeech.com se ha publicado una noticia muy interesante: Red Alert: ICANN and Verisign Proposal Would Allow Any Government In The World To&#8230;]]></description>
										<content:encoded><![CDATA[<p>En la web freespeech.com se ha publicado una noticia muy interesante:</p>
<blockquote class="wp-embedded-content" data-secret="MMShq2rbai"><p><a href="https://freespeech.com/2023/04/19/red-alert-icann-and-verisign-proposal-would-allow-any-government-in-the-world-to-seize-domain-names/">Red Alert: ICANN and Verisign Proposal Would Allow Any Government In The World To Seize Domain Names</a></p></blockquote>
<p><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;Red Alert: ICANN and Verisign Proposal Would Allow Any Government In The World To Seize Domain Names&#8221; &#8212; FreeSpeech.com" src="https://freespeech.com/2023/04/19/red-alert-icann-and-verisign-proposal-would-allow-any-government-in-the-world-to-seize-domain-names/embed/#?secret=CZFbKphDwm#?secret=MMShq2rbai" data-secret="MMShq2rbai" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe></p>
<p>En esta noticia se hacen eco de unos posibles cambios en la política de nombres de dominio en la extensión .net. Según esa noticia se estaría preparando una modificación que permitiría a cualquier <em>Gobierno</em> / <em>Autoridad Administrativa</em> / <em>Autoridad Gubernamental</em> / <em>Tribunal Competente</em>&#8230;. <span class="">denieguen, cancelen, redirijan o transfieran cualquier dominio registro de nombres, en otras palabras, se podrían confiscar dominio por cualquier entidad con «<em>autoridad</em>» y claro, esto pues podría supone un problema.</span></p>
<p>De momento este borrador sólo afecta a los dominios con extensión .net, pero podría afectar a los .com en un futuro no muy lejano.</p>
<p>El documento en cuestión está vivo en <a href="https://itp.cdn.icann.org/en/files/registry-agreement/redline-proposed-amendment-2017-net-registry-agreement-11-04-2023-en.pdf" target="_blank" rel="noopener">https://itp.cdn.icann.org/en/files/registry-agreement/redline-proposed-amendment-2017-net-registry-agreement-11-04-2023-en.pdf</a>, pero os dejo una <a href="https://www.eduardocollado.com/wp-content/uploads/2023/04/redline-proposed-amendment-2017-net-registry-agreement-11-04-2023-en.pdf" target="_blank" rel="noopener">copia también por aquí</a> por si queréis verla o si desapareciese.</p>
<p>Estos cambio son bastante preocupantes y en la web de freespeech.com ponen una serie de ejemplos que se podrían dar si esta nueva versión de la normativa entrase en juego.</p>
<blockquote>
<ol>
<li><span><span class="">El gobierno de China ordena que se suspendan (o simplemente se transfieran al gobierno chino) los nombres de dominio que operan sitios web que critican sus políticas.</span></span></li>
<li><span>El gobierno de Rusia, en guerra con Ucrania, ordena la transferencia de nombres de dominio pro-ucranianos al control del gobierno ruso.</span></li>
<li><span>El gobierno de Ucrania, en guerra con Rusia, ordena la transferencia de nombres de dominio prorrusos al control del gobierno ucraniano.</span></li>
<li><span>El gobierno de Texas ordena que los nombres de dominio a favor del aborto se transfieran al gobierno de Texas.</span></li>
<li><span> El gobierno talibán en Afganistán ordena que los nombres de dominio a favor del aborto y aquellos que promueven la educación de las niñas sean transferidos al gobierno.</span></li>
<li><span> El gobierno de Irán ordena que todos los nombres de dominio en todo el mundo con contenido «para adultos» (es decir, pornografía) se transfieran al gobierno iraní.</span></li>
<li><span>El gobierno de Tuvalu, (que ya licencia el registro .TV para recaudar fondos) que enfrenta una crisis económica debido al cambio climático, ordena que cada punto-net de 2 letras, 3 letras y una palabra sea transferido al gobierno de Tuvalu, con el fin de subastar los nombres de dominio para recaudar nuevos fondos para ellos mismos.</span></li>
<li><span>Un gobierno en Argentina lanza un nuevo programa cuyo nombre resulta ser idéntico al nombre de dominio propiedad de una empresa francesa durante los últimos 25 años. El gobierno de Argentina ordena que se les transfiera el nombre de dominio, sin compensación por la expropiación.</span></li>
<li><span>El gobierno de Italia está molesto por una empresa de redes sociales que opera desde China y ordena que el nombre de dominio de la empresa china se transfiera al gobierno italiano.</span></li>
<li><span><span class="">El gobierno del Reino Unido está molesto porque el software publicado por una empresa sueca tiene cifrado de extremo a extremo. </span>Ordena transferir el nombre de dominio de la empresa sueca al gobierno del Reino Unido.</span></li>
</ol>
</blockquote>
<p>Si esto se permitira a todo el mundo imaginad el descontrol que esto podría ser. Por suerte de momento está todo en borrador y es probable que no salga adelante, pero hay que andar con cuidado, porque estas cosas pasan cada vez más a menudo</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6756</post-id>	<enclosure length="1401143" type="application/pdf;charset=UTF-8" url="https://itp.cdn.icann.org/en/files/registry-agreement/redline-proposed-amendment-2017-net-registry-agreement-11-04-2023-en.pdf"/><itunes:explicit>no</itunes:explicit><itunes:subtitle>En la web freespeech.com se ha publicado una noticia muy interesante: Red Alert: ICANN and Verisign Proposal Would Allow Any Government In The World To&amp;#8230;</itunes:subtitle><itunes:summary>En la web freespeech.com se ha publicado una noticia muy interesante: Red Alert: ICANN and Verisign Proposal Would Allow Any Government In The World To&amp;#8230;</itunes:summary><itunes:keywords>Blog Profesional, Sistemas, libertad</itunes:keywords></item>
		<item>
		<title>Backup de Proxmox con PBS</title>
		<link>https://www.eduardocollado.com/2023/03/27/backup-de-proxmox-con-pbs/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 27 Mar 2023 17:46:16 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Podcast de Redes]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[deduplicación]]></category>
		<category><![CDATA[pbs]]></category>
		<category><![CDATA[proxmox]]></category>
		<category><![CDATA[zstandard]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6720</guid>

					<description><![CDATA[Si eres una de esas personas que utiliza Proxmox para virtualizar tu plataforma enhorabuena, estás usando una plataforma magnífica e insuperable en precio, puedes tenerla&#8230;]]></description>
										<content:encoded><![CDATA[<p>Si eres una de esas personas que utiliza Proxmox para virtualizar tu plataforma enhorabuena, estás usando una plataforma magnífica e insuperable en precio, puedes tenerla si quieres gratis, realmente no es necesario pagar nada, aunque si quieres los repositorios enterprise puedes pagar la suscripción de proxmox que va desde los 105 euros al año por socket.</p>
<p>Pero hoy no quiero hablar de proxmox, sino de proxmox backup server, que es el servicio de backup de proxmox.</p>
<p>La instalación es muy similar a la de proxmox VE, el hipervisor, y para entrar en vez de utilizar el puerto 8006 se utilizará el puerto 8007, lo cual, no se lo digáis a nadie, pero permite instalar el PBS en el mismo servidor que el Proxmox VE.</p>
<p>Instalar ambos softwares en el mismo hipervisor está bien si lo que queremos es un laboratorio o si tenemos dos servidores y hacemos copias cruzadas. De todos modos, que se pueda no significa que sea buena idea. Recordad que no todo lo que se puede hacer es buena idea, se puede beber lejía, pero yo no lo haría.</p>
<p>PBS tiene cuatro cosas muy graciosas que le hacen ser un software maravilloso:</p>
<ol>
<li>La deduplicación en las copias de seguridad, es decir, el backup va a ocupar muy poquito espacio.En el caso de KVM que las copias son muy rápidas y ligeras. En LXC el backup no es tan eficiente, pues hace copia de la máquina completa.</li>
<li>Retención y rotación de backups. Puedes tener las copias de seguridad y retenerlas con la antigüedad que quieras, por ejemplo backups cada hora, día, semana, mes, año. Una maravilla vamos.</li>
<li>Por supuesto la integración con Proxmox VE es total y absoluta.</li>
<li>PBS hace replicación entre PBS, con lo cual puedes tener siempre un backup externo en otro lado porque siempre va a estar sincronizado con tu PBS principal</li>
</ol>
<p>PBS es un componente integral de la plataforma de virtualización Proxmox VE, y se integra perfectamente con el hipervisor Proxmox VE para proporcionar una solución de copia de seguridad completa. PBS ofrece una amplia gama de características, como la capacidad de realizar copias de seguridad de forma incremental, comprimir y cifrar los datos de respaldo, y programar copias de seguridad de manera automática.</p>
<p>PBS utiliza la tecnología de copia de seguridad basada en <a href="https://facebook.github.io/zstd/" target="_blank" rel="noopener">Zstandard</a> y deduplicación de datos, lo que permite reducir significativamente el tamaño de las copias de seguridad y, por lo tanto, el espacio de almacenamiento requerido. También es compatible con varios tipos de almacenamiento de respaldo, como discos duros, almacenamiento de red (NAS) y sistemas de almacenamiento en la nube.</p>
<ul>
<li>Por si no lo conocéis <strong>Zstandard</strong> es un algoritmo de compresión muy rápido que se distribuye de forma gratuita con licencia BSD. Es un algoritmo desarrollado en Facebook, un lugar donde se hacen cosas muy interesantes.</li>
<li>Y la <strong>deduplicación</strong> lo que hace es ir buscando trozos de 4KB y le asigna un hash a cada uno. Al final si se ve un bloque duplicado no se guarda y sólo se almacenan bloques únicos, por eso el ahorro de espacio es tan salvaje. La deduplicación no es sólo no guardar dos veces el mismo fichero, sino que va mucho más allá, es algo mucho más sesudo y complicado de implementar, pero PBS nos lo ofrece gratis.</li>
</ul>
<p>PBS es una solución maravillosa, pero como os contaba en el audio anterior si tenemos el PBS en nuestras oficinas tenemos que tener en cuenta que sólo en electricidad nos va a costar unos 70 euros al mes, además de la amortización de hardware, control de discos, el que la sala no sea lo más adecuado, etc&#8230;</p>
<p>Así que una opción estupenda es tener el PBS en un Centro de Datos externo o incluso si tenéis el Proxmox VE en un Centro de Datos tener las copias en otro Centro de Datos.</p>
<p>La opción tradicional consiste en levantar un servidor nuevo en otro Centro de Datos, o bien usar un servicio de PBS remoto como el que ofrecemos nosotros en Tecnocrática, es cuestión de echar números y mirar qué es lo que más nos interesa. También se puede usar nuestro PBS para replicar el PBS que tengas</p>
<p>Pensar que la cantidad de datos que necesitáis de PBS es muy baja gracias a la deduplicación, así que quizás os interese hacer los backups en un PBS externo como el nuestro. Nosotros en Tecnocrática, por cierto cobramos 50 euros al mes el Tera usado y neto en el PBS que es mucho menso de lo que realmente se hace backup por lo que os he contado antes. Además en ese servicio nosotros nos encargamos de todo y tú sólo tienes que preocuparte de que las copias de seguridad se lancen.</p>
]]></content:encoded>
					
		
				<enclosure length="25740116" type="audio/mpeg" url="https://media.blubrry.com/eduardocollado/www.eduardocollado.com/wp-content/uploads/2023/03/podcast-274-pbs.mp3"/>

				<itunes:episodeType>full</itunes:episodeType>
		<itunes:duration>20:24</itunes:duration>
<post-id xmlns="com-wordpress:feed-additions:1">6720</post-id>	<itunes:explicit>no</itunes:explicit><itunes:subtitle>Si eres una de esas personas que utiliza Proxmox para virtualizar tu plataforma enhorabuena, estás usando una plataforma magnífica e insuperable en precio, puedes tenerla&amp;#8230;</itunes:subtitle><itunes:summary>Si eres una de esas personas que utiliza Proxmox para virtualizar tu plataforma enhorabuena, estás usando una plataforma magnífica e insuperable en precio, puedes tenerla&amp;#8230;</itunes:summary><itunes:keywords>Blog Profesional, Podcast de Redes, backup, deduplicación, pbs, proxmox, zstandard</itunes:keywords></item>
		<item>
		<title>Censura en Internet usando SNI en España</title>
		<link>https://www.eduardocollado.com/2021/11/02/censura-en-internet-usando-sni-en-espana/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 02 Nov 2021 12:16:44 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Redes]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[censura]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[sni]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6364</guid>

					<description><![CDATA[Aquí os dejo la presentación que hice este verano para esLibre en la que hablo sobre la censura en internet y el problema del SNI&#8230;]]></description>
										<content:encoded><![CDATA[<p>Aquí os dejo la presentación que hice este verano para <a href="https://eslib.re/2021/" target="_blank" rel="noopener">esLibre</a> en la que hablo sobre la censura en internet y el problema del SNI en TLS.</p>
<p>Os recomiendo que os deis una vuelta por el resto de los vídeos ya que los tenéis muy interesantes: <a href="https://commons.wikimedia.org/wiki/Category:EsLibre_2021" target="_blank" rel="noopener">https://commons.wikimedia.org/wiki/Category:EsLibre_2021</a></p>
<div style="width: 640px;" class="wp-video"><video class="wp-video-shortcode" id="video-6364-2" width="640" height="360" preload="metadata" controls="controls"><source type="video/webm" src="https://upload.wikimedia.org/wikipedia/commons/d/d5/EsLibre_2021_P42_-_Eduardo_Collado_Cabeza_-_Censura_en_Internet_usando_SNI_en_Espa%C3%B1a.webm?_=2" /><a href="https://upload.wikimedia.org/wikipedia/commons/d/d5/EsLibre_2021_P42_-_Eduardo_Collado_Cabeza_-_Censura_en_Internet_usando_SNI_en_Espa%C3%B1a.webm">https://upload.wikimedia.org/wikipedia/commons/d/d5/EsLibre_2021_P42_-_Eduardo_Collado_Cabeza_-_Censura_en_Internet_usando_SNI_en_Espa%C3%B1a.webm</a></video></div>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6364</post-id>	<enclosure length="64568329" type="video/webm" url="https://upload.wikimedia.org/wikipedia/commons/d/d5/EsLibre_2021_P42_-_Eduardo_Collado_Cabeza_-_Censura_en_Internet_usando_SNI_en_Espa%C3%B1a.webm"/><itunes:explicit>no</itunes:explicit><itunes:subtitle>Aquí os dejo la presentación que hice este verano para esLibre en la que hablo sobre la censura en internet y el problema del SNI&amp;#8230;</itunes:subtitle><itunes:summary>Aquí os dejo la presentación que hice este verano para esLibre en la que hablo sobre la censura en internet y el problema del SNI&amp;#8230;</itunes:summary><itunes:keywords>Blog Profesional, Redes, Vídeos, censura, internet, sni</itunes:keywords></item>
		<item>
		<title>Ver tráfico de Netflow en Wireshark</title>
		<link>https://www.eduardocollado.com/2021/09/13/ver-trafico-de-netflow-en-wireshark/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 13 Sep 2021 13:48:42 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Redes]]></category>
		<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[netflow]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=6331</guid>

					<description><![CDATA[Hoy necesitaba ver el contenido de unos mensajes de netflow en mi portátil y no quería ver la salida que me da nfsen, quería ver&#8230;]]></description>
										<content:encoded><![CDATA[<p>Hoy necesitaba ver el contenido de unos mensajes de netflow en mi portátil y no quería ver la salida que me da nfsen, quería ver exactamente qué contenido traía el paquete de netflow, así que he pensado en lo más fácil, abro un wireshark y ya está, pero no, no es tan fácil, hay que ver cómo leer con wireshark netflow.</p>
<p>Voy a contaros paso a paso qué es lo que he hecho:</p>
<h2>Obtener el tráfico de netflow</h2>
<p>Para ello me he contectado por ssh al netflow de turno y he generado un fichero pcap con el tráfico que quería capturar que era el que enviaba uno de los routers:</p>
<pre>tcpdump -i eth1 src 10.0.0.0.1 -w mi_router.pcap</pre>
<p>Con esto generamos el fichero mi_router.pcap, obviamente en mi caso el fichero no se llama así y la IP tampoco es esa, cada uno tendrá que poner los datos que le correspondan, pero la 10.0.0.1 es la IP origen desde la que se generan los flujos con dirección al netflow.</p>
<p>Ahora bajamos ese fichero con un scp o lo que sea al ordenador local, en mi caso un portátil.</p>
<h2>Abrimos Wireshark</h2>
<p>Ahora abrimos ese fichero con wireshark, entramos en cualquier paquete y oh, sorpresa, no se puede ver nada de nada:</p>
<figure id="attachment_6332" aria-describedby="caption-attachment-6332" style="width: 840px" class="wp-caption alignnone"><a href="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1.png" target="_blank" rel="noopener"><img decoding="async" class="wp-image-6332 size-large" src="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1-1024x566.png" alt="Wireshark" width="840" height="464" srcset="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1-1024x566.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1-300x166.png 300w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1-768x425.png 768w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1-1536x850.png 1536w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark1.png 1960w" sizes="(max-width: 840px) 100vw, 840px" /></a><figcaption id="caption-attachment-6332" class="wp-caption-text">El wireshark no nos permite ver el tráfico de Netflow</figcaption></figure>
<p>El tráfico de Netflow viene en la parte de abajo, dentro del Data de UDP, así que si habéis llegado hasta aquí que sepáis que aún os queda un paso.</p>
<h2>Decodificar</h2>
<p>Ahora vamos a la sección de arriba y con el botón derecho le damos a «<strong>Decode as</strong>» y en la columna Current seleccionamos <strong>CFLOW</strong>.</p>
<figure id="attachment_6333" aria-describedby="caption-attachment-6333" style="width: 790px" class="wp-caption alignnone"><img decoding="async" class="size-full wp-image-6333" src="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark2.png" alt="Decode" width="790" height="531" srcset="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark2.png 790w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark2-300x202.png 300w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark2-768x516.png 768w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark2-120x80.png 120w" sizes="(max-width: 790px) 100vw, 790px" /><figcaption id="caption-attachment-6333" class="wp-caption-text">Decode</figcaption></figure>
<p>Le damos aceptar y mágicamente ya podemos ver la información de Netflow, en este caso podéis ver una respuesta a una petición de DNS:</p>
<figure id="attachment_6334" aria-describedby="caption-attachment-6334" style="width: 840px" class="wp-caption alignnone"><a href="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3.png" target="_blank" rel="noopener"><img decoding="async" class="wp-image-6334 size-large" src="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3-1024x585.png" alt="Decode Netflow" width="840" height="480" srcset="https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3-1024x585.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3-300x171.png 300w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3-768x439.png 768w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3-1536x878.png 1536w, https://www.eduardocollado.com/wp-content/uploads/2021/09/wireshark3.png 1960w" sizes="(max-width: 840px) 100vw, 840px" /></a><figcaption id="caption-attachment-6334" class="wp-caption-text">Decode Netflow</figcaption></figure>
<div class="level__left">
<div class="level__item">
<div class="js-copy-attribute-content photo-page__adp-cta__container__attribution">Foto de <strong><a href="https://www.pexels.com/es-es/@aleksandr-neplokhov-486399?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" target="_blank" rel="noopener">Aleksandr Neplokhov</a></strong> en <strong><a href="https://www.pexels.com/es-es/foto/grupo-de-personas-reunidas-cerca-de-cartas-de-flujo-de-pie-libres-1238965/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" target="_blank" rel="noopener">Pexels</a></strong></div>
</div>
</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6331</post-id>	</item>
		<item>
		<title>Configurar NextDNS en Gl.iNET</title>
		<link>https://www.eduardocollado.com/2020/11/01/configurar-nextdns-en-gl-inet/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sun, 01 Nov 2020 21:02:48 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[dnsotls]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=5917</guid>

					<description><![CDATA[Para configurar NextDNS en Gl.iNet tenemos que editar la configuración de Stubby en el fichero /etc/stubby/stubby.yml e introducir ahí los datos de configuración que nos&#8230;]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Para configurar <a href="https://www.eduardocollado.com/2020/08/20/dns-sobre-https-con-adrian-almenar/">NextDNS</a> en Gl.iNet tenemos que editar la configuración de <a href="https://wiki.archlinux.org/index.php/Stubby" target="_blank" rel="noreferrer noopener">Stubby</a> en el fichero <strong>/etc/stubby/stubby.yml </strong>e introducir ahí los datos de configuración que nos ofrece NextDNS y en donde nuestro TLS Auth Name será <em>mango-abcdef.nextdns.io</em> siendo:</p>



<ul class="wp-block-list"><li><strong>mango</strong>: Nombre con el que queremos identificarnos en los registros, puede ser lo que querramos y recordad que si queremos que haya espacios en medio pondremos &#8212; (dos guiones)</li><li><strong>abcdef</strong>: Nuestro ID de cliente</li><li><strong>nextdns.io</strong>: esto siempre tiene que ser así</li></ul>



<p class="wp-block-paragraph">Antes de realizar la modificación de la configuración de TLS con Cloudflare para adaptarla a TLS con NextDNS yo os recomendaría guardar un backup, con:</p>



<pre id="block-2c893acc-2882-47d4-ba6c-a46de5694a4a" class="wp-block-code"><code>cp /etc/stubby/stubby.yml /etc/stubby/stubby.yml.cloudflare</code></pre>



<p class="wp-block-paragraph">Una vez hecho esto simplemente comentamos las líneas correspondientes de Cloudflare y añadimos las de NextDNS y os quedará un fichero como este:</p>



<pre class="wp-block-code"><code>root@GL-MT300N-V2:/etc/stubby# cat stubby.yml
#NOTE: See '/etc/stubby/stubby.yml.default' for original config file and descriptions

resolution_type: GETDNS_RESOLUTION_STUB

dns_transport_list:
  - GETDNS_TRANSPORT_TLS

tls_authentication: GETDNS_AUTHENTICATION_REQUIRED

tls_query_padding_blocksize: 128

edns_client_subnet_private : 0

round_robin_upstreams: 0

idle_timeout: 10000

listen_addresses:
  - 127.0.0.1@53535
  -  0::1@53535

upstream_recursive_servers:
# IPv6 addresses
# # Cloudflare IPv6
#  - address_data: 2606:4700:4700::1111
#    tls_port: 853 
#    tls_auth_name: "cloudflare-dns.com"

# # Cloudflare IPv6 secondary
#  - address_data: 2606:4700:4700::1001
#    tls_port: 853
#    tls_auth_name: "cloudflare-dns.com"

# # Quad 9 IPv6
#  - address_data: 2620:fe::10
#    tls_auth_name: "dns.quad9.net"

# IPv4 addresses
# # Cloudflare servers
#  - address_data: 1.1.1.1
#    tls_port: 853
#    tls_auth_name: "cloudflare-dns.com"
                      
# # Cloudflare servers secondary     
#  - address_data: 1.0.0.1          
#    tls_port: 853                  
#    tls_auth_name: "cloudflare-dns.com"

# Quad 9 service
#  - address_data: 9.9.9.10
#    tls_auth_name: "dns.quad9.net"

# NextDns service
  - address_data: 45.90.28.0
    tls_port: 853
    tls_auth_name: "mango-abcdef.dns1.nextdns.io"
  - address_data: 2a07:a8c0::0
    tls_port: 853
    tls_auth_name: "mango-abcdef.dns1.nextdns.io"
  - address_data: 45.90.30.0
    tls_port: 853
    tls_auth_name: "mango-abcdef.nextdns.io"
  - address_data: 2a07:a8c1::0
    tls_port: 853
    tls_auth_name: "mango-abcdef.nextdns.io"</code></pre>



<p class="wp-block-paragraph">Una vez hecho el cambio simplemente reiniciar el servicio y a funcionar con tus DNSs de NextDNS en Gl.iNet.</p>



<pre class="wp-block-preformatted">/etc/init.d/stubby restart</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5917</post-id>	</item>
		<item>
		<title>Cumulus Linux – Puertos de acceso y trunks</title>
		<link>https://www.eduardocollado.com/2020/04/01/cumulus-linux-puertos-de-acceso-y-trunks/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 01 Apr 2020 07:50:53 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[cumulus]]></category>
		<category><![CDATA[cumulus linux]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=5263</guid>

					<description><![CDATA[Cumulus Linux - Puertos de acceso y trunks. Configuración Cumulus vs Cisco.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Para configurar puertos de acceso y troncales en Cumulus Linux podemos hacer lo que en Cisco es algo como esto:</p>



<p class="wp-block-paragraph"><strong>Configuración en Cisco</strong></p>



<pre class="wp-block-code"><code>interface gigabitethernet4/1
    switchport mode trunk
    switchport trunk allowed vlan 100, 200
    switchport trunk native vlan 1

interface gigabitethernet 1/1
    switchport mode access
    switchport access vlan 100</code></pre>



<p class="wp-block-paragraph">En Cumulus Linux es un poco más complicado y la configuración sería del estilo:</p>



<p class="wp-block-paragraph"><strong>Configuración en Cumulus Linux</strong></p>



<pre class="wp-block-code"><code>auto bridge
iface bridge
    bridge-ports swp1 swp2 swp3
    bridge-vlan-aware yes
    bridge-stp on
    bridge-vid 100 200
    bridge-pvid 1

auto swp1
iface swp1
    bridge-access 100</code></pre>



<p class="wp-block-paragraph">Ambas configuraciones son más o menos equivalentes,  la diferencia principal estriba en que en cisco hay <strong>PVST+</strong> y<strong> en Cumulus Linux se comparte la instancia de spanning entre las dos vlans</strong> porque estamos utilizando<strong> vlan aware</strong>.</p>



<p class="wp-block-paragraph">Con esta configuración en dos switches conseguiríamos que dos PCs se vieran directamente a través de ellos utilizando el puerto swp2 de ambos switches, de momento el swp3 lo dejamos sin uso:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="843" height="352" src="https://www.eduardocollado.com/wp-content/uploads/2020/03/maqueta.jpeg" alt="maqueta" class="wp-image-5224" srcset="https://www.eduardocollado.com/wp-content/uploads/2020/03/maqueta.jpeg 843w, https://www.eduardocollado.com/wp-content/uploads/2020/03/maqueta-300x125.jpeg 300w, https://www.eduardocollado.com/wp-content/uploads/2020/03/maqueta-768x321.jpeg 768w, https://www.eduardocollado.com/wp-content/uploads/2020/03/maqueta-840x352.jpeg 840w" sizes="(max-width: 843px) 100vw, 843px" /><figcaption>Maqueta</figcaption></figure>



<p class="wp-block-paragraph">También hablé de Cúmulus <a href="https://www.eduardocollado.com/2020/03/19/cumulus-linux-introduccion/">aquí</a> y <a href="https://www.eduardocollado.com/2020/03/23/cumulus-linux-primeros-pasos-con-la-maqueta/">aquí</a>.</p>



<p class="wp-block-paragraph">Foto de cabecera de <strong><a rel="noreferrer noopener" href="https://www.pexels.com/@nusta-vikas?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" target="_blank">Vikas Sawant</a></strong> desde <strong><a rel="noreferrer noopener" href="https://www.pexels.com/photo/flock-of-birds-gathering-on-concrete-pavement-near-sea-2480956/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels" target="_blank">Pexels</a></strong></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5263</post-id>	</item>
		<item>
		<title>La automatización de icecast más sencilla: ezstream</title>
		<link>https://www.eduardocollado.com/2019/02/14/la-automatizacion-de-icecast-mas-sencilla-ezstream/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 14 Feb 2019 17:49:29 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[automatización]]></category>
		<category><![CDATA[ezstream]]></category>
		<category><![CDATA[icecast]]></category>
		<category><![CDATA[radio]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=4513</guid>

					<description><![CDATA[Montar un servicio de streaming con Icecast es relativamente sencillo en un servidor linux, ya publiqué en el blog de Tecnocrática una entrada explicándolo hace&#8230;]]></description>
										<content:encoded><![CDATA[<p>Montar un servicio de streaming con Icecast es relativamente sencillo en un servidor linux, ya <a href="https://blog.tecnocratica.net/2017/01/31/como-emitir-audio-en-directo/" target="_blank" rel="noopener noreferrer">publiqué en el blog de Tecnocrática</a> una entrada explicándolo hace algún tiempo.</p>
<p>Básicamente montar un servicio de Icecast básico es instalar el software icecast2 y configurarlo..</p>
<p>Una vez configurado ya podemos transmitir en directo desde nuestras cosas, pero &#8230; ¿Cómo puedes hacer para que icecast siga transmitiendo aunque no estemos transmitiendo?</p>
<p>Lo que se tiene que hacer es montar un automatizador, el más sencillo es sin duda es <a href="https://icecast.org/ezstream/" target="_blank" rel="noopener noreferrer">ezstream</a>.</p>
<p>Realmente lo más sencillo es contratar todo montado y que nos pongan un panel como <a href="https://centova.com/en/cast" target="_blank" rel="noopener noreferrer">Centova</a>, pero quizás queramos ahorrarnos ese dinero, sobre todo si lo que queremos es hacer transmisiones amateur.</p>
<p>Lo primero será tener un fichero de configuración de ejemplo, os pego una configuración mía:</p>
<pre class="lang:default decode:true">&lt;!--
   EXAMPLE: MP3 playlist stream WITHOUT reencoding

   This example streams a playlist that contains only MP3 files. No other file
   formats may be listed. Since ezstream will not be doing any reencoding, the
   resulting stream format (bitrate, samplerate, channels) will be of the
   respective input files.
 --&gt;
&lt;ezstream&gt;
    &lt;url&gt;http://xxxxxxx.eduardocollado.com:8000/musica&lt;/url&gt;
    &lt;!--
      If a different user name than "source" should be used, set it in
      &lt;sourceuser/&gt;:   --&gt; 
    &lt;sourceuser&gt;usuario_secreto&lt;/sourceuser&gt;

    &lt;sourcepassword&gt;password_secreta&lt;/sourcepassword&gt;
    &lt;format&gt;MP3&lt;/format&gt;
    &lt;filename&gt;/home/mp3/podcast/playlist.txt&lt;/filename&gt;
    &lt;!-- Once done streaming playlist.m3u, exit: --&gt;
    &lt;stream_once&gt;0&lt;/stream_once&gt;
    &lt;shuffle&gt;0&lt;/shuffle&gt;
   
    &lt;svrinfoname&gt;Musica libre&lt;/svrinfoname&gt;
    &lt;svrinfourl&gt;https://www.eduarodcollado.com&lt;/svrinfourl&gt;
    &lt;svrinfogenre&gt;Talk&lt;/svrinfogenre&gt;
    &lt;svrinfodescription&gt;Stream de musica libre sin derechos y tecnologia&lt;/svrinfodescription&gt;
    &lt;svrinfobitrate&gt;128&lt;/svrinfobitrate&gt;
    &lt;svrinfochannels&gt;2&lt;/svrinfochannels&gt;
    &lt;svrinfosamplerate&gt;44100&lt;/svrinfosamplerate&gt;
    &lt;svrinfopublic&gt;0&lt;/svrinfopublic&gt;
&lt;/ezstream&gt;</pre>
<p>En la siguiente línea indico cual es el host donde hay que hacer el streaming, el ezstream no tiene por qué estar en el mismo servidor que el icecast</p>
<pre class="lang:default decode:true ">&lt;url&gt;http://xxxxxxx.eduardocollado.com:8000/musica&lt;/url&gt;</pre>
<p>Ahora tendremos que indicar el usuario y contraseña de ese stream:</p>
<pre class="lang:default decode:true ">&lt;sourceuser&gt;usuario_secreto&lt;/sourceuser&gt; 
&lt;sourcepassword&gt;password_secreta&lt;/sourcepassword&gt;</pre>
<p>Inidicamos el formato de la transmisión, en mi caso mp3:</p>
<pre class="lang:default decode:true ">&lt;format&gt;MP3&lt;/format&gt;</pre>
<p>Ahora indicamos la lista con los ficheros de audio</p>
<pre class="lang:default decode:true">&lt;filename&gt;/home/xxxxx/musica/playlist.txt&lt;/filename&gt;</pre>
<p>El fichero con la lista tendría una pinta tal que así:</p>
<pre class="lang:default decode:true ">root@icecast:~# cat /home/musica/playlist.txt 
/home/mmusica/cctrax/Echo_Delta_-_Blu_Eon_mp3_320_kbps/01_Mistyfog.mp3
/home/musica/cctrax/Echo_Delta_-_Blu_Eon_mp3_320_kbps/02_Morph.mp3
/home/musica/podcast/podcast-130-ipsec.mp3
/home/musica/cctrax/Echo_Delta_-_Blu_Eon_mp3_320_kbps/03_Inly.mp3
[...]</pre>
<p>Este fichero puede ser todo lo largo que queráis.</p>
<p>Las dos líneas siguiente son bastante importantes y nos indican cómo trabajar con la lista de ficheros:</p>
<pre class="lang:default decode:true ">&lt;stream_once&gt;0&lt;/stream_once&gt;
&lt;shuffle&gt;0&lt;/shuffle&gt;</pre>
<p>Le decimos que puede hacer streaming más de una vez, para que haga un bucle y le decimos que no lo haga de forma aleatoria, es decir, que lea los ficheros de forma secuencial.</p>
<p>Las siguientes líneas ya no son tan importantes.</p>
<p>Algo que tenemos que tener en cuenta es que quizás queramos tener más de un stream en el servidor, para ello podemos lanzar tantos procesos ezstream como queramos, lo único que tenemos que tener en cuenta es que por defecto icecast sólo permite dos streams y eso lo podemos cambiar en:</p>
<pre class="lang:default decode:true ">$cat /etc/icecast2/icecast.xml
[...]
    &lt;limits&gt;
        &lt;clients&gt;100&lt;/clients&gt;
        &lt;sources&gt;10&lt;/sources&gt;
[...]</pre>
<p>Donde pone sources es donde lo definimos. Obviamente luego tenemos que reiniciar el servicio.</p>
<p>Por supuesto tenemos más métodos de automatización, muchos más completos como <a href="https://www.liquidsoap.info/" target="_blank" rel="noopener noreferrer">liquidsoap</a>, pero no ten sencillos.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4513</post-id>	</item>
		<item>
		<title>Renombrar ficheros en linux</title>
		<link>https://www.eduardocollado.com/2019/02/13/renombrar-ficheros-en-linux/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 13 Feb 2019 07:56:34 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[comandos]]></category>
		<category><![CDATA[unix]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=4484</guid>

					<description><![CDATA[En cualquier sistema UNIX podemos renombrar ficheros de al forma estándar con mv sin problemas y podemos automatizar tareas para renombrar ficheros, pero podemos ir&#8230;]]></description>
										<content:encoded><![CDATA[<p>En cualquier sistema UNIX podemos renombrar ficheros de al forma estándar con mv sin problemas y podemos automatizar tareas para renombrar ficheros, pero podemos ir un poco más allá</p>
<p>El comando <strong>rename</strong> nos va a facilitar muchísimo la vida y podemos hacer cosas muy interesantes.</p>
<p>Por ejemplo, queremos sustituir todos los espacios en los nombres por guiones bajos, además queremos quitar los paréntesis, los guiones medios y los &amp;, ¿cómo podemos hacer todo esto?</p>
<pre class="">rename 's/ /_/g' *
rename 's/\$//g' *
rename 's/\(//g' *
rename 's/\)//g' *
rename 's/\-//g' *</pre>
<p>El comando rename para hacer las sustituciones funciona de forma similar a como se hace una búsqueda en <strong>vi</strong>, así que si sabéis buscar en <strong>vi</strong> sabéis usar este comando.</p>
<p>Para hacer las sustituciones tendremos que escribir después de rename &#8216;<em>s/LO_QUE_QUERAMOS_BUSCAR/POR_LO_QUE_QUEREMOS_CAMBIAR/g</em>&#8216;.</p>
<p>Hay que tener en cuenta que a lo mejor es necesario que escapemos caracteres. Por ejemplo si queremos sustituir un &amp; lo suyo es escaparlo con \&amp;.</p>
<p>La cadena entera empezará por <strong>s</strong> y terminará por <strong>g</strong>, es todo lo que tenemos que tener en cuenta.</p>
<p>Espero que os sea de utilidad.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4484</post-id>	</item>
		<item>
		<title>Podcast Generator, plataforma de podcasts fácil</title>
		<link>https://www.eduardocollado.com/2018/11/11/podcast-generator-plataforma-de-podcasts-facil/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sun, 11 Nov 2018 14:07:10 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[podcast]]></category>
		<category><![CDATA[podcasting]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=4292</guid>

					<description><![CDATA[Mucha gente sigue utilizando plataformas como Ivoox, Audioboom, Spreaker y similares simplemente porque creen que tener su propia web para alojar sus podcasts es complicado&#8230;]]></description>
										<content:encoded><![CDATA[<p>Mucha gente sigue utilizando plataformas como Ivoox, Audioboom, Spreaker y similares simplemente porque creen que tener su propia web para alojar sus podcasts es complicado y difícil, y no es cierto.</p>
<p>Existen varias opciones más complicadas y más sencillas, pero hoy os quiero presentar la opción más sencilla posible, al menos la más sencilla que he encontrado, se llama Podcast Generator.</p>
<p>Esta aplicación necesita solo php, no necesita ni bases de datos ni nada  excepcional, con lo que es perfecta para usuarios que no quieran calentarse la cabeza o que no quieran ningún tipo de complejidad técnica.</p>
<p>Además, el requerir solo php y no mysql hace que en muchos hosters el precio del alojamiento baje muchísimo, por ejemplo en Neodigit hospedar con Podcast Generator un podcast como A Ratos Podcast que tiene 53 capítulos con una calidad mínima por episodio de 128kbps estaría en torno a los 6 euros al mes, pero ampliar tendría un coste de 1,2 euros por cada 50 capítulos aproximadamente, obviamente si son capítulos de 2 horas pues son menos y si son de 5 minutos pues son más los que se pueden subir.</p>
<p>También tiene la ventaja al no tener base de datos que el mantenimiento es más sencillo. Podéis probarlo y ver sus características en <a href="http://www.podcastgenerator.net" target="_blank" rel="noopener noreferrer">http://www.podcastgenerator.net</a>, pero que nadie siga almacenando sus audios por ahí si no es por algún tipo de opción personal.</p>
<p>El software además permite personalizar plantillas de una forma más o menos sencilla, esto no es trivial, y permite hacer muchas cosas. Cualquier duda con el software lo podemos ver sin problemas.</p>
<p>Ya tenemos un nuevo CMS, esta vez más especializado, espero que os guste.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4292</post-id>	</item>
		<item>
		<title>Redes a 400G</title>
		<link>https://www.eduardocollado.com/2018/11/06/redes-a-400g/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 06 Nov 2018 17:49:52 +0000</pubDate>
				<category><![CDATA[Redes]]></category>
		<category><![CDATA[400G]]></category>
		<category><![CDATA[cisco]]></category>
		<category><![CDATA[huawei]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=4240</guid>

					<description><![CDATA[Cuando empecé a tocar routers Cisco trabajábamos con la serie 2500, de hecho yo llegué a tener algún router en casa de esos, eran routers&#8230;]]></description>
										<content:encoded><![CDATA[<p>Cuando empecé a tocar routers Cisco trabajábamos con la serie 2500, de hecho yo llegué a tener algún router en casa de esos, eran routers que de hecho algunos tenían puertos ethernet AUI, es decir, el puerto ethernet no era un conector RJ45, usaban un conector DB-15.</p>
<p>A ese conector DB-15 conectábamos un transceptor AUI / RJ45 y en ese transceptor pinchábamos nuestro cable RJ45.</p>
<p><figure id="attachment_4243" aria-describedby="caption-attachment-4243" style="width: 300px" class="wp-caption alignleft"><img decoding="async" class="wp-image-4243 size-medium" src="https://www.eduardocollado.com/wp-content/uploads/2018/11/aui-300x238.jpg" alt="" width="300" height="238" srcset="https://www.eduardocollado.com/wp-content/uploads/2018/11/aui-300x238.jpg 300w, https://www.eduardocollado.com/wp-content/uploads/2018/11/aui.jpg 500w" sizes="(max-width: 300px) 100vw, 300px" /><figcaption id="caption-attachment-4243" class="wp-caption-text">Transceptor AUI/RJ-45</figcaption></figure></p>
<p>Transceptores de esos yo creo que tengo todavía alguno en alguna caja en casa, pero no os imaginéis el transceptor como un transceptor de un SFP, estos eran muchísimo más grandes y toscos.</p>
<p>Esos transceptores eran Ethernet y cuando digo Ethernet quiero decir 10-Base-T, es decir, 10Mbps.</p>
<p>Luego salieron los puertos Fast Ethernet a 100Mbps, esto era increíble, podíamos hacer cosas maravillosas como router on stick, pasar vlans, era una cosa increíble, teníamos routers que solo tenían un puerto, o al menos solo usábamos un puerto, todo cabía en 100Mbps.</p>
<p>Posteriormente pasamos a puertos de 1Gbps, a 10Gbps, y ahí se desmadró la cosa.</p>
<p>Del 10G pasamos al 40G que usaban unos interfaces llamados QSFP+ que permitían despeinar ese 40G en 4 puertos de 10G, con adaptadores obviamente.</p>
<p>De ahí pasamos al 100G y así como el que no quiere la cosa al 400G, usando la misma analogía que se usó al pasar del 10G a 40G.</p>
<p>Pues bien, esto ha cambiado de tal manera que a día de hoy, Noviembre de 2018 me encuentro en mi mesa escribiendo sobre redes a 400G.</p>
<p>A la red cada día se le exige más y más, se le exige tanto que a veces cuesta creer que se pueda llegar a hacer más, pero siempre tenemos gente que consigue estirar más y más la capacidad de la red para seguir prestando servicios.</p>
<p>Y claro, no solo velocidad se pide, sino también eficiencia, agilidad &#8230; en fin&#8230; todo lo que pase por la mente, pero siendo un poco más concretos cada vez es más común pedir a la red el análisis de tráfico a tiempo real, obviamente los buffers tienen que ser más grandes, pero por otro lado se pide que la latencia baje</p>
<p>Obviamente todo esto no se puede ofrecer con la tecnología existente, así que hay que adaptar conectores y tecnología óptica, de hecho en 400G los transceptores son <strong>QSFP-DD</strong> (<em>Quad Small Form Factor &#8211; Double Density</em>).</p>
<p>En cuanto a fabricantes metidos en este berenjenal tenemos varios como son Cisco, Juniper, Huawei o Fujitsu. Aquí se quedan fuera otros como Mikrotik, los cuales no tienen ni la capacidad ni la fuerza necesaria para entrar en este tipo de tecnologías en esta fase tan temprana.</p>
<p><figure id="attachment_4246" aria-describedby="caption-attachment-4246" style="width: 300px" class="wp-caption alignright"><img decoding="async" class="wp-image-4246 size-medium" src="https://www.eduardocollado.com/wp-content/uploads/2018/11/CE9860X-300x170.png" alt="" width="300" height="170" srcset="https://www.eduardocollado.com/wp-content/uploads/2018/11/CE9860X-300x170.png 300w, https://www.eduardocollado.com/wp-content/uploads/2018/11/CE9860X.png 718w" sizes="(max-width: 300px) 100vw, 300px" /><figcaption id="caption-attachment-4246" class="wp-caption-text">Huawei CE9860X</figcaption></figure></p>
<p>Mientras Huawei ha centrado sus esfuerzos de 400G en el switch <strong>Huawei CE9860X</strong>, en el que recaerá gran parte de la innovación. El CE9860X actualmente soporta <strong>128 puertos de 100G</strong> Cisco ya tiene listos cuatro modelos para ser lanzados a lo largo del 2019</p>
<ul>
<li><strong>Nexus 9316D-GX</strong>, un switch de <strong>16 puertos</strong> y 1U de altura que, según Cisco, funcionará bien en aplicaciones de aplicaciones de infraestructura centrada en la aplicación (ACI).</li>
<li><strong>Nexus 93600CD-GX</strong>, que ofrece <strong>28 puertos de 100GbE</strong> y <strong>8 puertos de 400Gb</strong>E en una sola U para backbone.</li>
<li><strong>Nexus 3408-S</strong>, que cuenta con un chasis de 4U y ocho ranuras que admite <strong>128 puertos de 100GbE</strong> o <strong>32 puertos de 400GbE</strong> a través de módulos de expansión de tarjeta de línea.</li>
<li><strong>Nexus 3432D-S</strong>, un switch de 1U con<strong> 32 puertos de 10/40/100 / 400GbE nativos</strong> y <strong>2x200GbE y 4&#215;50 / 100GbE</strong>.</li>
</ul>
<p>El año que viene me parece que vamos a ver el despegue de equipos con puertos de 400G, al menos podremos ver cómo fabricantes empiezan a sacarlos por todas partes., sino tiempo al tiempo.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4240</post-id>	</item>
		<item>
		<title>Cómo borrar contenido antiguo de Twitter</title>
		<link>https://www.eduardocollado.com/2018/11/02/como-borrar-contenido-antiguo-de-twitter/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Fri, 02 Nov 2018 09:33:22 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=4178</guid>

					<description><![CDATA[Es posible que en algún momento queráis eliminar contenido antiguo de Twitter y que necesitéis una forma de hacerlo. En mi caso cree la cuenta&#8230;]]></description>
										<content:encoded><![CDATA[<p>Es posible que en algún momento queráis eliminar contenido antiguo de Twitter y que necesitéis una forma de hacerlo.</p>
<p>En mi caso cree la cuenta de Twitter en Marzo de 2007, y claro, casi 12 años después las cosas han cambiado, mi vida ha cambiado y no tengo ni idea de qué he escrito en los 26500 tweets que llevaba escritos, así que he decidido hacer limpieza, por higiene más que nada.</p>
<p>Lo primero que haces es buscar en la propia red social si es posible eliminar tweets antiguos y favoritos, y sí, es posible, pero uno a uno, y claro, borrar 26500 tweets uno a uno no es viable, en absoluto es una opción, así que empiezas a buscar servicios online.</p>
<p>Servicios online hay varios, pero todos tienen el mismo problema, borran hasta 3000 tweets, y ¿qué pasa con los demás 23500? ¿se van a quedar ahí?, pues si sólo usas estos servicios online es así, vas a tener 23500 tweets que no vas a poder borrar, pero tranquilo, que tampoco los vas a ver a no ser que tengas el enlace.</p>
<p>Por alguna razón que desconozco Twitter sólo te muestra los últimos 3000 tweets (ó 3200, no recuerdo muy bien), así que una vez los borres con esos servicios online no vas a ver tweets, pero estarán ahí, de hecho en el perfil de Twitter verás que tienes tweets, aunque no puedas verlos.</p>
<p>Si os parece bien voy a describiros el proceso que he seguido para eliminar el contenido de la red social y hacer un poco de higiene digital a mi persona.</p>
<h3>Hacer un backup de vuestros tweets</h3>
<p>Lo primero es hacer un backup de vuestros tweets, porque una cosa es quererlos borrar y otra muy diferentes quererlos perder, además, esta información la vamos a necesitar para el borrado de tweets, con lo que además de ser interesante tener una copia de seguridad de vuestra información es necesario.</p>
<p>Para hacer el backup de vuestros tweets tenéis que ir en vuestro perfil a Configuración y Privacidad y después más abajo a Tu archivo de Tweets. ahí lo podéis solicitar. Os llegará un correo al cabo de unas horas con un enlace para descargarlo, será un archivo .zip.</p>
<h3>Borrar los tweets</h3>
<p>Si al abrir el .zip os encontráis con un fichero tweets.csv entonces estaréis en mi mismo caso y tendréis que bajaros <a href="https://github.com/koenrh/delete-tweets" target="_blank" rel="noopener">https://github.com/koenrh/delete-tweets</a>, o clonar obviamente, en mi caso he clonado que es más fácil.</p>
<p>Este repositorio contiene un script en python que va borrar el contenido de nuestra cuenta de Twitter, así que tenéis que tener instalado Python y pip en vuestro PC.</p>
<p>Para poderlo ejecutar necesitaréis las claves del API de Twitter, podéis conseguirlas en api.twitter.com y ahí declarando una nueva aplicación. Para cargarlas como variables de entorno en Linux tendréis que hacer lo siguiente:</p>
<pre class="">export TWITTER_CONSUMER_KEY="xxxxxxxxxxxxx"
export TWITTER_CONSUMER_SECRET="xxxxxxxxxxxxx"
export TWITTER_ACCESS_TOKEN="xxxxxxxxxxxxx"
export TWITTER_ACCESS_TOKEN_SECRET="xxxxxxxxxxxxx"</pre>
<p>En otros sistemas operativos no tengo muy claro como se haría.</p>
<p>Una vez tengáis esto copiáis en este directorio el fichero tweets.csv que habéis obtenido de vuestro backup.</p>
<p>Bien, una vez cargadas las variables de entorno ya podéis ejecutar el script.</p>
<pre class=""># python ./deletetweets.py -h
usage: deletetweets.py [-h] -d DATE [-r {reply,retweet}]

Delete old tweets.

optional arguments:
-h, --help show this help message and exit
-d DATE Delete tweets until this date
-r {reply,retweet} Restrict to either replies or retweets</pre>
<p>Así que tendréis que indicar desde qué fecha queréis que borre, si es desde hoy 2 de Noviembre de 2018 sería así:</p>
<pre class=""># python ./deletetweets.py -d 2018-11-2</pre>
<p>Y empezará a borrar los tweets:</p>
<pre class="">.
.
.
Deleting tweet #148406602 (2007-07-13)
Deleting tweet #148732832 (2007-07-13)
Deleting tweet #147859102 (2007-07-13)
Deleting tweet #148133142 (2007-07-13)
Deleting tweet #148144692 (2007-07-13)
Deleting tweet #146365992 (2007-07-12)
Deleting tweet #146406372 (2007-07-12)
Deleting tweet #146406982 (2007-07-12)
Deleting tweet #146687632 (2007-07-12)
Deleting tweet #146700722 (2007-07-12)
Deleting tweet #146850332 (2007-07-12)
Deleting tweet #147053022 (2007-07-12)
Deleting tweet #147062252 (2007-07-12)
Deleting tweet #147186782 (2007-07-12)
Deleting tweet #147192762 (2007-07-12)
Deleting tweet #145003742 (2007-07-11)
Deleting tweet #145004962 (2007-07-11)
Deleting tweet #145021302 (2007-07-11)
Deleting tweet #145131432 (2007-07-11)
.
.
.
</pre>
<p>Este proceso puede tardar, y de hecho tarda horas, así que armaros de paciencia y es muy probable que os falle, así que si os falla volvéis a empezar el script, pero ajustando la fecha hasta la que hayáis borrado.</p>
<h3>Borrado de favoritos</h3>
<p>Una vez hayáis borrado los tweets querréis seguramente borrar los favoritos, ya os digo, podéis ir uno por uno, pero seguramente el proceso se va a demorar semanas o meses, así que mucho mejor automatizar la tarea.</p>
<p>Para borrar los favoritos yo he usado un script también de github: <a href="https://github.com/martinshelton/Purge-Twitter-Faves" target="_blank" rel="noopener">https://github.com/martinshelton/Purge-Twitter-Faves</a>.</p>
<p>Una vez descargado tenéis que abrir el fichero favorite_purge.py e introducir ahí vuestras claves de Twitter y vuestro usuario de Twitter.</p>
<p>Después es ejecutarlo y esperar, también unas cuantas horas.</p>
<p>Con esto ya tenéis vuestros datos eliminados y podéis seguir usando vuestra propia cuenta de Twitter sin perder followers ni hacer nada extraño. Y lo mejor, sin depender de servicios de terceros.</p>
<p>Espero que os haya sido útil.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4178</post-id>	</item>
		<item>
		<title>Puesta en marcha correcta de WordPress</title>
		<link>https://www.eduardocollado.com/2018/01/01/puesta-en-marcha-correcta-de-wordpress/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 01 Jan 2018 11:43:26 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=3160</guid>

					<description><![CDATA[Poner un WordPress en marcha de forma correcta no es algo tan fácil como dar al autoinstalador de nuestro hosting o hacer una instalación estándar,&#8230;]]></description>
										<content:encoded><![CDATA[<p>Poner un WordPress en marcha de forma correcta no es algo tan fácil como dar al autoinstalador de nuestro hosting o hacer una instalación estándar, eso lo sabe hacer cualquiera, hay que seguir muchos más pasos y realizarlos concienzudamente, no es algo ni obvio ni automático, hay que dedicar esfuerzo y atención.</p>
<p>Instalar y mantener un sitio WordPress seguro, y rápido es algo que todos queremos y deseamos, pero que muy pocos lo consiguen. Internet está lleno de WordPress desactualizados, pesados y/o inseguros, y tampoco es cuestión de volverse loco ni obsesivo con la seguridad, simplemente hay que instalar la herramienta de forma correcta y realizar un mantenimiento de periódico de actualizaciones y ajustes necesarios.</p>
<p>En el post de hoy quiero daros una guía para poder instalar un WordPress de forma adecuada con los pasos que personalmente creo que son interesantes, obviamente habrá muchas más opciones por Internet, pero esta es la forma que yo recomiendo.</p>
<h2>Instalación</h2>
<p>El primer paso será obviamente instalar Wordress, para ello realizaremos una instalación estándar, la única diferencia que recomiendo es que cuando nos pregunte por el prefijo de la base de datos no lo dejemos en <strong>wp_</strong>, seguro que podemos ser mucho más creativos y poner otras cosas como <strong>epsteuagi_vlodaor_</strong> o cualquier cosa que se nos pase por la cabeza en ese momento.</p>
<blockquote><p>[&#8230;]simplemente hay que instalar la herramienta de forma correcta y realizar un mantenimiento de periódico de actualizaciones y ajustes necesarios[&#8230;]</p></blockquote>
<p>No os cuento como realizar una instalación básica de WordPress pues tenéis miles de tutoriales para hacer esto, símplemente recordar cambiar el prefijo de las tablas de la base de datos.</p>
<p>Una vez instalado lo primero va a ser establecer el esquema de URL, a lo que nosotros queramos, esto lo haremos en <strong>Ajustes &#8211; Enlaces Permanentes</strong>.</p>
<p>El siguiente paso puede ser si queréis quitar el famoso category, cuando entras en una categoría, pero no cambiarlo por otra cosa, sino directamente quitarlo, a mi me resulta muy molesto tener ese <em>category</em> u otra palabra ahí en medio, por eso siempre recomiendo quitarlo, el problema es que si lo quitamos poniendo en la misma página en la que estamos un punto «<strong>.</strong>» en Categoría Base nos van a fallar otras cosas en el futuro, y si váis directamente a modificar en el .htaccess también, así que hay que modificar dentro de WordPress, para eso hay un plugin muy tontorrón que se llama <a href="https://es.wordpress.org/plugins/no-category-base-wpml/" target="_blank" rel="noopener">No Category Base (WPML)</a> y que lo hará por vosotros, esto obviamente no es necesario ni va a hacer que nuestro sitio sea más seguro, pero siempre quedará mejor que las URLs no tengan cosas en medio que estorben y como estábamos en la sección de establecer los enlaces permanentes era interesante comentarlo aquí.</p>
<h2>Certificado SSL</h2>
<p>Ahora vamos a <strong>activar el SSL</strong>, es decir, el https, para ello lo primero que vais a necesitar es un certificado, puede ser desde un Let&#8217;s Encrypt hasta el certificado más caro que os podáis imaginar, esto tenéis que preguntarlo en vuestro hosting, entiendo que estando en 2018 esto estará ya superado, así que no deberíais de encontrar ningún problema para ello. Una vez instalado podéis cambiar a mano la URL base de vuestro Wordress e ir con mucho cuidado o instalar otro plugin, en este caso se llama <a href="https://es.wordpress.org/plugins/really-simple-ssl/" target="_blank" rel="noopener">Really Simple SSL</a> que lo hará todo por vosotros.</p>
<p>Siguiente paso arreglar un poco el .htaccess, necesitamos que todo esto que estamos montando funcione correctamente, así que vamos a editar el fichero .htaccess y vamos a añadir las siguientes líneas para <strong>solucionar problemas del strict transport</strong>, entiendo que vuestro dominio va a ser con www, si lo queréis sin www tenéis que modificar las dos últimas líneas.</p>
<pre class="lang:default decode:true">&lt;IfModule mod_headers.c&gt;
Header set Strict-Transport-Security "max-age=31536000; preload" env=HTTPS
&lt;/IfModule&gt;
#FORZAR A www con HTTPS
RewriteEngine On
RewriteCond %{HTTP_HOST} ^vuestro_dominio.com [NC]
RewriteRule ^(.*)$ https://www.vuestro_dominio.com/$1 [L,R=301]</pre>
<p>Ahora ya está nuestro WordPress instalado con https, con las URLs como queremos y si lo consultamos con http:// nos va a responder siempre con https:, esto empieza a tomar forma.</p>
<h2>Seguridad</h2>
<p>El siguiente aso será potenciar la seguridad del sitio, esto lo vamos a hacer modificando permisos de ficheros, añadiendo líneas en el .htaccess y con plugins, la combinación de las tres cosas.</p>
<p>Todos <strong>los ficheros estarán en 644 y los directorios en 755</strong>, esto es fundamental y tiene que ser así.</p>
<p>Ahora llegamos a un tema peliagudo, hay muchos sitios que recomiendan que se cambie la base del wp-content y del wp-admin. Cambiar el wp-content, esto se recomienda como una acción que hay que realizar sí o sí, pero el wp-content se ve perfectamente en el código fuente que genera WordPress por qué se ha cambiado y wp-admin sí podría ser interesante si nuestro servidor no puede ofrecernos una capa de seguridad basada en fail2ban para evitar ataques de fuerza bruta, bueno, se pueden cambiar, no hay problema, pero yo relego la parte del wp-admin a la seguridad que proporciona el servidor gracias al fail2ban evitando ataques de fuerza bruta o más fácil restringiendo el acceso por .htaccess. El cambio se puede hacer fácilmente con el plugin WP better security, pero yo no utilizo ese plugin.</p>
<p>En el .htaccess bloqueo el <strong>spam referido</strong>, es decir, que nos puedan meter comentarios en vuestro WordPress desde cualquier sitio que nos sea el propio post, esto os va a quitar muchísimo spam, y lo que también hago es bloquear el acceso al xmlrpc.php y al wp-login desde mis IPs, ojo que también lo que hago es<strong> permitir acceso al xmlrpc.php desde el rango 192.0.64.0/18, ese es el direccionamiento de Automatic, si no permitís esto no os funcionará el Jetpack</strong>.</p>
<p>También nos vamos a proteger de la ejecución de ficheros que ahí no deberían de estar.</p>
<pre class="lang:default decode:true"># BLOQUEO SPAM NO REFERIDO
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_REFERER} !^http(s)?://([^.]+\.)?vuestro_dominio\.com [NC]
RewriteCond %{REQUEST_URI} /wp-comments-post\.php [NC]
RewriteRule .* - [F,L]
&lt;/IfModule&gt;
#BLOQUEO AL xmlrpc.php
&lt;Files xmlrpc.php&gt;
order deny,allow
deny from all
allow from x.x.x.x
allow from x.x.x.x
allow from 192.0.64.0/18
&lt;/Files&gt;
#BLOQUEO ACCESO AL wp-config.php
&lt;files wp-config.php&gt;
order allow,deny
deny from all
allow from x.x.x.x
allow from x.x.x.x
&lt;/files&gt;
# FICHEROS QUE NO DEBERIAN ESTAR
&lt;IfModule mod_alias.c&gt;
RedirectMatch 403 (?i)(^#.*#|~)$
RedirectMatch 403 (?i)/readme\.(html|txt)
RedirectMatch 403 (?i)\.(ds_store|well-known)
RedirectMatch 403 (?i)/wp-config-sample\.php
RedirectMatch 403 (?i)\.(7z|bak|bz2|com|conf|dist|fla|git|inc|ini|log|old|psd|rar|tar|tgz|save|sh|sql|svn|swo|swp)$
&lt;/IfModule&gt;</pre>
<p>Y ahora vamos a por los plugins, que también hay que ponerlos, los que os recomiendo son: <strong>Akismet Anti-Spam</strong>, <strong>All In One WP Security</strong>, <strong>Block Bad Queries (BBQ)</strong> y <strong>WP fail2ban</strong>, os voy contando para que sirve cada uno y cual es el objetivo de cada uno de los plugins.</p>
<ul>
<li><strong>Akismet Anti-Spam</strong>: Este plugin está desarrollado por Automatic y es un antispam, al instalarlo hay que registrarlo en la web de WordPress, nos da el enlace, no tiene mayor complicación, si es para uso personal podemos elegir si pagamos o no y cuanto queremos pagar.</li>
<li><strong>All In One WP Security</strong>: Este es uno de esos plugins enormes que hacen de todo, aquí tendréis que ver las opciones que más os interesen, a mi me gusta mucho la parte de exploración donde nos revisa los ficheros modificados y podremos detectar automáticamente si hay modificación de ficheros. Luego hay otras opciones que no utilizo como por ejemplo la del antispam porque akismet es mucho mejor, o la de bloqueos porque lo relego en otros plugins que lo hacen mejor.</li>
<li><strong>Block Bad Queries (BBQ)</strong>: Gracias a BBQ evitaremos peticiones maliciosas por http, inyecciones de código, etc&#8230; este plugin es muy recomendable.</li>
<li><strong>WP fail2ban</strong>: Para poder utilizar este plugin tu hosting tiene que soportarlo, en el caso de <a href="https://neodigit.net">Neodigit</a> se soporta sin problemas ya que los servidores están configurados para integrar el plugin con los firewalls. Cualquier intento de ataque de fuerza bruta será bloqueado por el firewall y no por el php, lo cual hará que no baje el rendimento de la web, si lo hicieramos con algún plugin de seguridad, el rendimento de la web se vendría abajo pues aunque no mostremos la página tendremos que procesar esa petición.</li>
</ul>
<p>Por supuesto además de instalar plugins es totalmente <strong>necesario estar atentos a las actualizaciones</strong> que vayan surgiendo <strong>y a la posible obsolescencia de plugins y temas</strong>, ya que es por los temas y plugins no mantenidos por donde suelen venir todos los problemas de WordPress.</p>
<h2>Optimización</h2>
<p>Llegamos un punto que es importante para la calidad de nuestro sitio, pero que no va a hacer que sea más seguro, sino más rápido y va a mejorar la experiencia del usuario.</p>
<p>Para optimizar lo más importante es elegir bien el tema y tenerlo cuidado y trabajado, pero si eso no lo podemos hacer al menos que podamos hacer otras cosas, pero que nunca van a sustituir a la elección correcta del tema, sólo podrán complementarlo.</p>
<p>Definir en el .htaccess los expires necesarios:</p>
<pre class="lang:default decode:true">&lt;IfModule mod_expires.c&gt;
ExpiresDefault                              "access plus 1 month"
ExpiresByType text/html                     "access plus 1 seconds"
ExpiresByType text/xml                      "access plus 1 seconds"
ExpiresByType text/plain                    "access plus 1 seconds"
ExpiresByType application/xml               "access plus 1 seconds"
ExpiresByType application/json              "access plus 1 seconds"
ExpiresByType application/rss+xml           "access plus 1 hour"
ExpiresByType text/css                      "access plus 1 month"
ExpiresByType text/javascript               "access plus 1 month"
ExpiresByType application/javascript        "access plus 1 month"
ExpiresByType application/x-javascript      "access plus 1 month"
ExpiresByType image/x-ico                   "access plus 1 month"
ExpiresByType image/x-icon                  "access plus 1 month"
ExpiresByType image/gif                     "access plus 1 month"
ExpiresByType image/png                     "access plus 1 month"
ExpiresByType image/jpe                     "access plus 1 month"
ExpiresByType image/jpg                     "access plus 1 month"
ExpiresByType image/jpeg                    "access plus 1 month"
ExpiresByType font/truetype                 "access plus 1 month"
ExpiresByType font/opentype                 "access plus 1 month"
ExpiresByType application/x-font-woff       "access plus 1 month"
ExpiresByType video/ogg                     "access plus 1 month"
ExpiresByType audio/ogg                     "access plus 1 month"
ExpiresByType video/mp4                     "access plus 1 month"
ExpiresByType video/webm                    "access plus 1 month"
ExpiresByType image/svg                     "access plus 1 month"
ExpiresByType image/svg+xml                 "access plus 1 month"
ExpiresByType application/pdf               "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
&lt;/IfModule&gt;</pre>
<p>Y ahora pasaremos a los plugins que hay que instalar que son básicamente cinco: <strong>AMP</strong>, <strong>Autoptimize</strong>, <strong>WP Super Cache</strong>,<strong> WP-Sweep </strong>y <strong>Heartbeat Control</strong></p>
<ul>
<li><strong>AMP</strong>: Este plugin nos adaptará las páginas al AMP de Google, se supone que Google funcionará con AMP si puede y las páginas cargarán más rápidas</li>
<li><strong>Autoptimize</strong>: Realiza una optimización de html, css y javascript, con esto conseguiremos mejorar el tiempo de carga de nuestras webs.</li>
<li><strong>WP-Sweep</strong>: Limpieza de bases de datos. La base de datos de WordPress si no se mantiene limpia va creciendo hasta el infinito, haciendo que nuestro WordPress cada vez sea más y más lento.</li>
<li><strong>WP Super Cache</strong>: Un plugin de caché indispensable que tiene una relación usabilidad, facilidad y resultado excelentek, hay otros como W3 Total Cache, pero la dificultad que nos ofrece hace que no merezca la pena.</li>
<li><strong>Heartbeat Control</strong>: Este plugin va a modificar el tiempo entre chequeos del API de WordPress, lo que hará que use muchos menos recursos y que el servidor funcione mejor.</li>
</ul>
<p>Solo agregar que es de total importancia que la<strong> versión de php sea superior a la 7.0</strong> que mejora el rendimiento enormemente, en <a href="https://neodigit.net" target="_blank" rel="noopener">Neodigit</a> ya tenemos la versión 7.2 en estado alpha, pero totalmente usable, este blog es prueba de ello :).</p>
<p>Espero que este post os sirva para poder configurar correctamente vuestro WordPress.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3160</post-id>	</item>
		<item>
		<title>Conexión a Mikrotik vía Radius</title>
		<link>https://www.eduardocollado.com/2017/07/24/conexion-a-mikrotik-via-radius/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 24 Jul 2017 16:18:55 +0000</pubDate>
				<category><![CDATA[Redes]]></category>
		<category><![CDATA[freeradius]]></category>
		<category><![CDATA[mikrotik]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=2388</guid>

					<description><![CDATA[Para gestionar un Mikrotik por una o dos personas simplemente creamos un usuario en el router y ya podemos entrar, pero ¿qué pasa si tenemos&#8230;]]></description>
										<content:encoded><![CDATA[<p>Para gestionar un Mikrotik por una o dos personas simplemente creamos un usuario en el router y ya podemos entrar, pero ¿qué pasa si tenemos 200 routers a los que acceder y accede un equipo de gente que puede ir cambiando? ¿tenemos que aprender 200 contraseñas diferentes y tenemos que crear los usuarios en cada router cada vez que entra un usuario nuevo? Obviamente no.</p>
<p>La respuesta a todo esto es usar Radius para la autenticación remota. Acceder por Radius nos va a permitir configurar los usuarios en un único lugar, un servidor Radius, y que gracias a esa configuración cada usuario podrá acceder a todos los routers, mucho más fácil y gestionable que ir configurando usuarios por todas partes y luego gestinar eso, que se vuelve inmanejable.</p>
<p>¿Para hacer esto qué vamos a necestar? pues un servidor radius y uno o muchos Mikrotiks. Obviamente aquí os voy a mostrar como hacerlo con Mikrotiks, pero se puede hacer con cualquier otra cosa que soporte Radius, que es la mayoría de cosas.</p>
<p>Servidores Radius hay muchísimos, pero para el ejemplo voy a utilizar <a href="//freeradius.org/" target="_blank" rel="noopener">Freeradius</a> sobre una Ubuntu 16.04.02.</p>
<p>La instalación es tan sencilla como:</p>
<pre class="lang:default decode:true ">sudo apt-get install freeradius</pre>
<p>Una vez instalado tendremos que añadir el cliente, es decir, el router que vamos a permitir conectarse al radius para autenticar en el fichero /etc/freeradius/clients.conf</p>
<pre class="lang:default decode:true ">client 192.168.91.214/32 {
	secret = password
	shortname = MikroTik
}</pre>
<p>En este caso la IP 192.168.91.214, es la IP de mi router Mikrotik y la contraseña de autenticación es la palabra password. Esto simplemente indica que desde esa IP se pueden hacer peticiones.</p>
<p>Ahora configuraremos un usuario, eso lo haremos en el fichero /etc/freeradius/users con el siguiente contenido:</p>
<pre class="lang:default decode:true ">edu Cleartext-Password := "password"</pre>
<p>Aquí le decimos que el usuario edu tiene de contraseña la palabra password</p>
<p>Con esto ya tendríamos la parte de Radius configurada para poder tener control de acceso a los routers, sin más, así de fácil.</p>
<p>Ahora en el mikrotik tendremos que configurar:</p>
<pre class="lang:default decode:true ">/radius
add address=192.168.91.213 secret=password service=login
/radius incoming
set accept=yes
/user aaa 
set use-radius=yes
</pre>
<p>Hemos hecho dos cosas, le hemos dicho que el servidor Radius es la IP 192.168.91.213 con contraseña password, esto tiene que coincidir con lo que hemos dicho en el servidor Radius en el fichero clients.conf. Y además le hemos dicho que ese servidor Radius se utilizará para login, es decir, para acceder al equipo.</p>
<p>Este último punto es interesante porque podemos tener un servidor radius de gestión, para acceder a los equipos y otro por ejemplo para pppoe o temas similares.</p>
<p>Y muy importante, le diremos que utilice Radius.</p>
<p>Radius va a funcionar siempre una vez que no haya funcionado la autenticación local.</p>
<p>Os dejo un pantallazo para que lo veáis en acción, no lo he comentado pero para poder ver lo que hace el servidor radius es con el comando sudo freeradius -X, si tenéis otra instancia de freeradius tendréis que matarla.</p>
<p><img decoding="async" class="alignleft size-full wp-image-2391" src="https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819.png" alt="" width="1600" height="900" srcset="https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819.png 1600w, https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819-300x169.png 300w, https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819-768x432.png 768w, https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819-1024x576.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2017/07/Screenshot_20170724_141819-700x394.png 700w" sizes="(max-width: 1600px) 100vw, 1600px" /></p>
<p><strong>ACTUALIZACION</strong>: Si os ha interesado podéis escuchar el <a href="https://www.eduardocollado.com/2017/07/29/podcast-37-login-radius-en-mikrotik/">capítulo 37 del podcast</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2388</post-id>	</item>
		<item>
		<title>Red en docker</title>
		<link>https://www.eduardocollado.com/2017/04/26/red-en-docker/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 26 Apr 2017 17:44:00 +0000</pubDate>
				<category><![CDATA[Redes]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[red]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=2130</guid>

					<description><![CDATA[El otro día me propuse hacer un tutorial rápido sobre docker, pero me quedó un poco coja la parte de red, así que hoy voy a&#8230;]]></description>
										<content:encoded><![CDATA[<p>El otro día me propuse hacer un <a href="//www.eduardocollado.com/2017/04/23/podcast-25-introduccion-a-docker/" target="_blank" rel="noopener noreferrer">tutorial rápido sobre docker</a>, pero me quedó un poco coja la parte de red, así que hoy voy a intentar avanzar un poco más, porque docker es un tema realmente fascinante, así que si me prestáis un rato de vuestro preciado tiempo intentaremos avanzar un poquito más por el camino de docker.</p>
<p>El otro día empezamos a hablar un poco de red en docker y os comenté como enlazar un puerto externo a uno interno con -p puerto_externo:puerto_de_docker pero claro, eso está bien si ejecutamos un sólo contenedor, pero ¿qué ocurre si estamos ejecutando varios?, llevar el control de los puertos puede ser complejo así que tenemos la opción de la gestión dinámica de puertos.</p>
<p>Para ver los puertos asignados dinámicamente lo hacemos con docker port y el nombre</p>
<pre class="lang:default decode:true">edu@thinkpad ~ # docker run --name nc -p 80 -p 443 -d nextcloud
edu@thinkpad ~ # docker port nc 
443/tcp -&gt; 0.0.0.0:32768
80/tcp -&gt; 0.0.0.0:32769</pre>
<p>A mi personalmente me gusta fijar los puertos siempre que sea posible, pero la opción ahí está.</p>
<p>Y si queremos fijar un puerto, pero UDP podemos indicarlo</p>
<pre class="lang:default decode:true">docker run -p 1234:1234/udp -d imagen</pre>
<p>Imaginad un servidor de DNS dockerizado, pues ahí podríamos mostrar un puerto udp, el 53.</p>
<p>Ahora vamos a ir un poco más allá y vamos a conectar por red dos contenedores. Para ello tenemos la opción de conectarlos vía el host, vía el mapeo de puertos definido antes, no creo que haga falta hablar más de ello, o bien, directamente, de un contenedor a otro, pero sin usar el host.</p>
<p>Una opción es la del enlace directo, en la que tenemos una arquitectura cliente servidor, donde el cliente se lanza con la opción &#8211;link que lo que hace es meter en el fichero de hosts el contenedor que queramos.</p>
<pre class="lang:default decode:true ">edu@thinkpad ~ # docker run -ti --name servidor ubuntu bash
root@46096ba9221f:/#
edu@thinkpad ~ # docker run -ti --name cliente --link servidor ubuntu:latest bash
root@ab6b148a4b59:/# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2	servidor 46096ba9221f
172.17.0.3	ab6b148a4b59</pre>
<p>Pero claro, lo suyo es crear una red para aquellos contenedores que se quieran ver entre sí.</p>
<p>La red se crea con docker network create y docker nos asignará un direccionamiento con su NAT y todo.</p>
<pre class="lang:default decode:true">edu@thinkpad ~ # docker network create red_interna
3c259b15e3850f62540ed8e1ba3b6ed6610c78d8f531a3d401868fbff34f362d
edu@thinkpad ~ # docker run -ti --rm --net=red_interna --name servidor2 ubuntu bash</pre>
<p>Hay una cosa que podemos hacer y es limitar el acceso a la red de docker vía el PAT en función de la IP que accede, por ejemplo.</p>
<pre class="lang:default decode:true ">docker run -p 127.0.0.1:8080:80/tcp</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2130</post-id>	</item>
		<item>
		<title>Instalando y jugando con Ghost</title>
		<link>https://www.eduardocollado.com/2017/04/25/instalando-y-jugando-con-ghost/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 25 Apr 2017 20:31:50 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[ghost]]></category>
		<category><![CDATA[instalacion]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=2133</guid>

					<description><![CDATA[En el vídeo de hoy instalo y juego un poco con Ghost. La instalación la hago en docker por ser mucho más fácil. Este vídeo&#8230;]]></description>
										<content:encoded><![CDATA[<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/tx6Uoq5gunc?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
<p>En el vídeo de hoy instalo y juego un poco con Ghost. La instalación la hago en docker por ser mucho más fácil.</p>
<p>Este vídeo es mi primer contacto con Ghost y bueno, no está mal, ya me contaréis al ver el vídeo.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2133</post-id>	</item>
		<item>
		<title>Cuanto cuesta un servidor en casa</title>
		<link>https://www.eduardocollado.com/2017/04/13/cuanto-cuesta-un-servidor-en-casa/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 13 Apr 2017 15:00:48 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[coste eléctrico]]></category>
		<category><![CDATA[electricidad]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[precio]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=2085</guid>

					<description><![CDATA[En el vídeo de hoy os cuento cuanto dinero nos cuesta tener un PC encendido 24 horas en España, sólo tengo en cuenta el coste&#8230;]]></description>
										<content:encoded><![CDATA[<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/ixgAVMEL6iw?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
<p>En el vídeo de hoy os cuento cuanto dinero nos cuesta tener un PC encendido 24 horas en España, sólo tengo en cuenta el coste de la luz, no pongo ni coste de conexión ni de recambios ni mano de obra ni nada, sólo luz.</p>
<p>Obviamente en el cálculo del vídeo no he tenido en cuenta la parte fija de la factuara, al final se nos va prácticamente a 0,20 el kwh pero bueno, tampoco quería entrar ahí.</p>
<p>Tened en cuenta que al luz en casa se puede caer, se puede caer la conexión a internet en casa, en fin, pueden pasar muchas cosas.</p>
<p>¿Realmente es más barato poner una web en casa que en un hosting?</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2085</post-id>	</item>
		<item>
		<title>Primer contacto con Mastodon</title>
		<link>https://www.eduardocollado.com/2017/04/08/primer-contacto-con-mastodon/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 08 Apr 2017 20:16:50 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=2052</guid>

					<description><![CDATA[Hoy he probado Mastodon, dondeme de alta en mastodon.club, hay más nodos, así que probadlo y ya me decís que tal, ahí encontraréis a un&#8230;]]></description>
										<content:encoded><![CDATA[<p>Hoy he probado Mastodon, dondeme de alta en <a href="//mastodon.club" target="_blank">mastodon.club</a>, hay más nodos, así que probadlo y ya me decís que tal, ahí encontraréis a un montón de buena gente <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Empiezo a hablar en el minuto 3:18 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/2kPC3IJn8sM?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2052</post-id>	</item>
		<item>
		<title>WordPress Staging</title>
		<link>https://www.eduardocollado.com/2017/03/08/wordpress-staging/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 08 Mar 2017 16:24:50 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[staging]]></category>
		<category><![CDATA[wordpress video]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=1740</guid>

					<description><![CDATA[Últimamente se habla de WordPress Staging o Staging en WordPress, como queráis llamarlo, pero ¿qué es el staging? porque nos lo venden como si fuera&#8230;]]></description>
										<content:encoded><![CDATA[<p>Últimamente se habla de WordPress Staging o Staging en WordPress, como queráis llamarlo, pero ¿qué es el staging? porque nos lo venden como si fuera algo mágico que sólo se puede hacer en el Olimpo y Staging se puede hacer de forma fácil y sencilla en cualquier sitio, incluso en una instalación local de WordPress en vuestro PC, no es necesario nada extraño ni sobrenatural.</p>
<p>Tenemos varias formas de hacer staging en cualquier lado, de hacerlo por nosotros mismos sin tener que contratar nada extraño a nadie, hay multitud de herramientas que nos pueden ayudar a ello, pero antes vamos a contestar a la pregunta de antes.</p>
<p>¿Qué es el Staging? Es un proceso en el cual cogemos una web, en nuestro caso un Worpdress ya que estamos haciendo WordPress Staging y copiamos todos los ficheros a un directorio, copiamos la base de datos y empezamos a trabajar.</p>
<p>Pues bien, en el screencast de hoy os cuento como funciona el plugin, con los aciertos y los errores, he preferido no cortar cuando me he equivocado para que vosotros os podáis ahorrar esos momentos.</p>
<p><strong>Enlaces</strong>:</p>
<p>Plugin WP Staging &#8211; DB &amp; File Duplicator &amp; Migration: <a href="https://es.wordpress.org/plugins/wp-staging/" target="_blank">https://es.wordpress.org/plugins/wp-staging/</a></p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/ME-D5jqcrsM?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1740</post-id>	</item>
		<item>
		<title>Poner texto en dos columnas en WordPress sin plugins</title>
		<link>https://www.eduardocollado.com/2017/02/04/poner-texto-en-dos-columnas-en-wordpress-sin-plugins/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 04 Feb 2017 10:21:56 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[columnas]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[edición]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=1453</guid>

					<description><![CDATA[El uso de plugins en WordPress a veces creo que se nos ha ido de las manos y tenemos de vez en cuando que decir&#8230;]]></description>
										<content:encoded><![CDATA[<p>El uso de plugins en WordPress a veces creo que se nos ha ido de las manos y tenemos de vez en cuando que decir eso de «hasta aquí», hay cosas que siempre habríamos hecho sin un plugin, pero WordPress nos ha hecho cómodos.</p>
<p>Javier Archeni hablaba en el último capítulo de su podcast <a href="https://republicaweb.es/" target="_blank">República Web</a> que WordPress es como un martillo y recordando a Maslow se preguntaba si podíamos tratar a todos los problemas de desarrollo de páginas webs como si fueran clavos, os dejo el audio completo por si os interesa.<iframe loading="lazy" width="300" height="200" style="border: 1px solid #EEE; box-sizing: border-box; width: 100%;" id="audio_16816098" frameborder="0" allowfullscreen="allowfullscreen" scrolling="no" src="https://www.ivoox.com/player_ej_16816098_4_1.html?c1=ff6600"></iframe>Yo pienso un poco como Javier Archeni, y aún personalemente siendo un defensor de WordPress pienso que «<em>hay que utilizar la herramienta correcta para cada tarea concreta</em>«, esta última frase lamentablemente no se de quien y seguramente quedará como sabiduría popular, pero tiene mucha razón.</p>
<p>Un ejemplo claro y concreto, en la página principal de https://www.eduardocollado.com tengo un par de reproductores de audio, uno para cada uno de mis podcasts y su momento quería poner los dos reproductores uno al lado del otro, algo que no es complicado, pero el pensamiento en modo WordPress nos hace pensar de forma errónea.</p>
<p>Siguiendo el pensamiento WordPress lo que tendría que hacer era buscar un plugin para hacer esto, porque para mucha gente todo se soluciona poniendo plugins, siguiendo este pensamiento es probable llegar al pensamiento que necesitaba un builder de páginas en WordPress, un Site Origin o similar y usando esa herramienta podría poner las dos columnas, ahora, ¿eso es lo mejor? pues rotundamente no, eso si se me permite creo que es una cochinada porque dependeríamos de un plugin de por vida y tendríamos una caja negra en una de nuestras páginas.</p>
<p>Ahora, ¿cómo lo haríamos con otro razonamiento?, voy a explicaros el razonamiento que he seguido yo, que pudiera parecer más complicado, pero es porque seguramente tengamos ya la cabeza formada al «<em>WordPress&#8217; style</em>«, lo primero es pensar en las posibilidades que nos ofrece WordPress y crearíamos un tema hijo, un child theme, luego crearía un código CSS para hacer las dos columnas, en mi caso este:</p>
<pre class="lang:css decode:true  ">@media only screen and (min-width: 600px) {
	.columna_izquierda{
		width:47%;
		padding:0 5pt 0 0;
		float:left;
	}
}
@media only screen and (min-width: 600px) {
	.columna_derecha{
		width:47%;
		padding:0 0 0 5pt;
		float:right;
	}
}
</pre>
<p>Y ahora en la página donde quisiera poner los reproductores pondría este código, poniendo el editor en modo HTML obviamente:</p>
<pre class="lang:default decode:true ">&lt;div class="columna_izquierda"&gt;
COLUMNA DE LA IZQUIERDA
&lt;/div&gt;
&lt;div class="columna_derecha"&gt;
COLUMNA DE LA DERECHA
&lt;/div&gt;</pre>
<p>Y con esto ya tendríamos el código sin depender de ningún plugin, sin tener una caja negra que nos «<em>encochine</em>» el código y si os dedicáis al desarrollo web estas líneas son más que obvias, así que poco se puede decir más a favor.</p>
<p>Ahora, hay mucha gente que quizás no sepa de CSS lo suficiente como para poner este código de cabeza, pues bien, pueden usar Google y buscar soluciones, exactamente igual que se hace para otras cosas.</p>
<p>El que no avanza corre el riesgo de quedarse atrás y WordPress en ese aspecto es muy peligroso, puede hacernos ser más cómodos y no os lo recomiendo.</p>
<p>Recordad que tengo audios donde explico cosas, como por ejemplo <a href="https://www.eduardocollado.com/2017/01/23/podcast-17-introduccion-a-child-themes/" target="_blank">cómo crear un child-theme</a>, o <a href="https://www.eduardocollado.com/2017/01/26/radiowordpress-18-modificar-css-en-un-child-theme/" target="_blank">cómo modificar el CSS de un child-theme</a>, con esos audio y un poco de búsqueda en internet tenéis lo suficiente para modificar un tema sin tener que recurrir a plugins extraños, porque al final WordPress no son sólo plugins y temas.</p>
<p>Este es el resultado:</p>
<p><img decoding="async" class="aligncenter size-full wp-image-1460" src="https://www.eduardocollado.com/wp-content/uploads/2017/02/reproductores.png" alt="" width="881" height="600" srcset="https://www.eduardocollado.com/wp-content/uploads/2017/02/reproductores.png 881w, https://www.eduardocollado.com/wp-content/uploads/2017/02/reproductores-300x204.png 300w, https://www.eduardocollado.com/wp-content/uploads/2017/02/reproductores-768x523.png 768w, https://www.eduardocollado.com/wp-content/uploads/2017/02/reproductores-700x477.png 700w" sizes="(max-width: 881px) 100vw, 881px" /></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1453</post-id>	</item>
		<item>
		<title>Nueva versión de WordPress, la 4.7</title>
		<link>https://www.eduardocollado.com/2016/12/07/nueva-version-de-wordpress-la-47/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 07 Dec 2016 05:56:47 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=920</guid>

					<description><![CDATA[Pues ya está aquí la nueva versión de WordPress, la 4.7 y con nombre «Vaughan», en honor a la jazzista Sarah “Sassy” Vaughan. La nueva versión&#8230;]]></description>
										<content:encoded><![CDATA[<p>Pues ya está aquí la nueva versión de WordPress, la 4.7 y con nombre «Vaughan», en honor a la jazzista Sarah “Sassy” Vaughan.</p>
<p>La nueva versión viene con una serie de mejoras como nuevas funciones de API y algo que a mi personalmente me gusta mucho y son las «<em>acciones en lote personalizadas</em>«, de las que ya se habló en Octubre en el artículo <a href="https://make.wordpress.org/core/2016/10/04/custom-bulk-actions/" target="_blank">Using Custom Bulk Actions</a> del blog de WordPress, esto nos va a dar una flexibilidad brutal a la hora de hacer cosas.</p>
<p>La nueva versión también permite que cada una de las personas que colaboran en el WordPress pueda tener el panel de administración en un idioma diferente y por fin se elimina la necesidad de logarse una vez se termina la instalación inicial, nunca comprendí por qué era necesario logarse al terminar la configuración inicial, siempre me pareció un paso absurdo y redundante, pues ya no es necesario pasar por ahí.</p>
<p>Pero además de todas estas mejoras lo que los usuarios van a ver es el tema, el <strong>twenty seventeen</strong> que viene con una serie de mejoras muy apreciables y que saltan mucho a la vista.</p>
<p>El nuevo tema viene con la posibilidad de poner vídeo directamente en la cabecera, algo que ya hace tiempo se está volviendo bastante común y que empezaba a ser una necesidad.</p>
<p>También el editor de personalización del nuevo tema:</p>
<p><img decoding="async" class="size-large wp-image-925 aligncenter" src="https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1-1024x576.png" alt="" width="700" height="394" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1-1024x576.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1-300x169.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1-768x432.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1-700x394.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-1.png 1600w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Para insertar el vídeo tenemos que ir a Cabecera multimedia y subir un vídeo o si queréis ahorrar ancho de banda, algo muy recomendable, podéis insertar una URL de YouTube como en este ejemplo:</p>
<p><img decoding="async" class="size-large wp-image-926 aligncenter" src="https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube-1024x576.png" alt="" width="700" height="394" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube-1024x576.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube-300x169.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube-768x432.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube-700x394.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/12/wp47-2-youtube.png 1600w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Y algo que me parece muy interesante es el menú de CSS Adicional, en el que se pueden hacer aquellos ajustes necesarios sin tener que crear temas hijos ni modificaciones extrañas, una autentica maravilla.</p>
<p><img decoding="async" class="size-full wp-image-927 aligncenter" src="https://www.eduardocollado.com/wp-content/uploads/2016/12/css.png" alt="" width="627" height="439" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/12/css.png 627w, https://www.eduardocollado.com/wp-content/uploads/2016/12/css-300x210.png 300w" sizes="(max-width: 627px) 100vw, 627px" /></p>
<p>En cuanto al rendimimiento tengo que decir que no he notado mejoría, la mejoría grande se notó al cambiar a php 7, pero una vez hecho eso no he notado nada más.</p>
<p>Espero que esta pequeña pincelada os muestre un poco las mejoras que hay en esta nueva versión de WordPress.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">920</post-id>	</item>
		<item>
		<title>Limitar acceso por países a una web</title>
		<link>https://www.eduardocollado.com/2016/11/30/limitar-acceso-por-paises-a-una-web/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 30 Nov 2016 07:11:03 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[destacado]]></category>
		<category><![CDATA[filtrar ip]]></category>
		<category><![CDATA[ip locator]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=853</guid>

					<description><![CDATA[Una consulta bastante típica de algunos clientes consiste en preguntar si es posible limitar el acceso a sus webs dependiendo del país de origen, la&#8230;]]></description>
										<content:encoded><![CDATA[<p>Una consulta bastante típica de algunos clientes consiste en preguntar si es posible limitar el acceso a sus webs dependiendo del país de origen, la última consulta de este estilo la he recibido hace unos minutos.</p>
<p>Existen varios plugins para WordPress que hacen esto y por supuesto también tenemos la opción del htaccess manual para limitar el acceso, para ello limitamos a todos los rangos geolocalizados en el país que queremos permitir, o los que no queramos permitir, como queramos.</p>
<p>Hay un servicio que a mi me gusta mucho que es <a href="https://www.ip2location.com/blockvisitorsbycountry.aspx" target="_blank">IP2Location</a> el cual genera el htaccess, aunque también tienen plugin para <a href="https://es.wordpress.org/plugins/ip2location-country-blocker/" target="_blank">WordPress</a>.</p>
<p>Ahora tenemos que tener en cuenta que el htaccess no va a hacer que no llegue tráfico de ciertos países, va a hacer que no sirvamos la web, pero no que nuestro Apache devuelva la conexión, así que ante caso de ataque de DDoS no sirve.</p>
<p>Y luego otras opciones en las que se ejecuta un php para ver si hay que filtrar la conexión ahí además de consumir una conexión de Apache además la procesamos.</p>
<p>Entonces ¿para qué nos sirve esto? Filtrar países es una buena solución si nuestro negocio o web está únicamente enfocada a un único país. También puede servirnos si tenemos alguna web con alguna vulnerabilidad que siempre es explotada desde determinados países, sí, estas cosas pasan y son muy comunes aunque parezca mentira, aunque lo mejor es arreglarlo hay mucha gente que lo único que puede hacer es limitar el acceso.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">853</post-id>	</item>
		<item>
		<title>Configuración cliente openvpn sin adjuntos</title>
		<link>https://www.eduardocollado.com/2016/11/22/configuracion-cliente-openvpn-sin-adjuntos/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 22 Nov 2016 14:33:26 +0000</pubDate>
				<category><![CDATA[Redes]]></category>
		<category><![CDATA[openvpn]]></category>
		<guid isPermaLink="false">https://www.eduardocollado.com/?p=769</guid>

					<description><![CDATA[La configuración cliente de OpenVPN consiste típicamente en un fichero .ovpn y una serie de certificados, normalmente ca.crt, client.crt, client.key y ta.key. En la mayoría&#8230;]]></description>
										<content:encoded><![CDATA[<p>La configuración cliente de OpenVPN consiste típicamente en un fichero .ovpn y una serie de certificados, normalmente ca.crt, client.crt, client.key y ta.key.</p>
<p>En la mayoría de clientes de OpenVPN es posible agregar el fichero de configuración y después adjuntar los ficheros de certificados sin problemas, pero lamentablemente existen casos como en la configuración de OpenVPN en un iPhone donde no es posible agregar los ficheros (a no ser que tengas iTunes).</p>
<p>En ese caso lo que tenemos que hacer es adaptar nuestro fichero de configuración. Si en un inicio es algo así:</p>
<pre class="lang:default decode:true">client
dev tun
proto udp
remote my-server-1 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
comp-lzo
verb 3</pre>
<p>Y además tenemos los ficheros ta.key, client.key, client.crt y ca.crt.</p>
<p>Ahora lo que queremos es incorporar esos ficheros dentro del fichero de configuración, para ellos simplemente convertiremos nuestro fichero en algo parecido a esto:</p>
<pre class="lang:default decode:true">client
dev tun
proto udp
remote my-server-1 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
comp-lzo
verb 3
&lt;ca&gt;
-----BEGIN CERTIFICATE-----
AQUÍ VA EL CONTENIDO DE ca.crt
-----END CERTIFICATE-----
&lt;/ca&gt;
&lt;cert&gt;
-----BEGIN CERTIFICATE-----
AQUÍ VA EL CONTENIDO DE client.crt
-----END CERTIFICATE-----
&lt;/cert&gt;
&lt;key&gt;
-----BEGIN RSA PRIVATE KEY-----
AQUÍ VA EL CONTENIDO DE client.key
-----END RSA PRIVATE KEY-----
&lt;/key&gt;
&lt;tls-auth&gt;
-----BEGIN OpenVPN Static key V1-----
AQUÍ VA EL CONTENIDO DE ta.key
-----END OpenVPN Static key V1-----
&lt;/tls-auth&gt;</pre>
<p>Pues este es todo el secreto <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">769</post-id>	</item>
		<item>
		<title>Formularios HTML con campos dinámicos en JavaScript</title>
		<link>https://www.eduardocollado.com/2016/11/17/formularios-html-con-campos-dinamicos-en-javascript/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 17 Nov 2016 06:15:54 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[formularios]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=703</guid>

					<description><![CDATA[Hoy me he tropezado con una necesidad en un formulario y es que el número de campos tenía que ser dinámico y no predefinido, para&#8230;]]></description>
										<content:encoded><![CDATA[<p>Hoy me he tropezado con una necesidad en un formulario y es que el número de campos tenía que ser dinámico y no predefinido, para que no sea el ejemplo con el que he tenido que lidiar y sea algo más entretenido vamos a pensar en un formulario en el que introduzcamos las canciones de un CD de música, no sabemos como se llama el CD y lo mejor, no sabemos cuantas canciones tiene.</p>
<p>Así que vamos a hacer un formulario que pida el nombre del CD, el autor y todas las canciones junto con la duración de cada una.</p>
<p>Para que quede mono el formulario podemos ir a lo fácil y usar bootstrap, para definir los cuadros podemos ir a <a href="http://shoelace.io/" target="_blank">shoelace.io</a> que es una web que nos ayudará a crear los cuadros de una forma muy fácil y visual, en mi caso:</p>
<p><img decoding="async" class="alignnone size-large wp-image-718" src="http://eduardocollado.com/wp-content/uploads/2016/11/shoelace2-1024x531.png" alt="shoelace" width="700" height="363" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/11/shoelace2-1024x531.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/11/shoelace2-300x155.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/11/shoelace2-768x398.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/11/shoelace2-700x363.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/11/shoelace2.png 1600w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>El código que nos ha generado es el siguiente:</p>
<pre class="lang:default decode:true ">&lt;div class="container"&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-4"&gt;&lt;/div&gt;
        &lt;div class="col-md-4"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-6"&gt;&lt;/div&gt;
        &lt;div class="col-md-2"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-6"&gt;&lt;/div&gt;
        &lt;div class="col-md-2"&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>Obviamente para estas cajas no es necesario usar ninguna aplicación externa, pero que sepáis que existe, a mi me ha venido muy bien.</p>
<p>En cuanto tenemos esto procedemos a meter nuestro formulario ahí dentro.</p>
<pre class="lang:default decode:true">&lt;div class="container"&gt;
    &lt;h3&gt;Formulario de canciones de CD&lt;/h3&gt;
    &lt;form action="relleno_de_cds.php" id="formulario" method="post"&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-4"&gt;&lt;label&gt;Nombre CD&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-4"&gt;&lt;input class="form-control" name="nombre_cd" type="text"/&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-6"&gt;&lt;label&gt;T&amp;iacute;tulo canci&amp;oacute;n&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-2"&gt;&lt;label&gt;Duraci&amp;oacute;n&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-1"&gt;&lt;input type="button" class="btn btn-success" id="add_cancion()" onClick="addCancion()" value="+" /&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;!-- El id="canciones" indica que la función de JavaScript dejará aquí el resultado --&gt;
    &lt;div class="row" id="canciones"&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;</pre>
<p>Como primer paso hemos rellenado la plantilla que nos ha generado la aplicación de antes para usar los campos para distribuir el formulario, sólo hemos añadido un pequeño detalle, y es ese botón «+» que han en la segunda caja y que solo ocupa una columna. La distribución de las columnas es la de bootstrap.</p>
<p>Por supuesto en la cabecera hemos metido el css indicado</p>
<pre class="lang:default decode:true ">&lt;!-- Latest compiled and minified CSS --&gt;
&lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"&gt;</pre>
<p>Y en cuanto al javascript utilizado la función addCancion() que lo que hace es añadir al div canciones, el último y que aparece vacío en el HTML de arriba dos cajas más con los inputs del formulario.</p>
<p>Por supuesto, cada vez que se le da al «+» verde se crea una nueva fila</p>
<pre class="lang:default decode:true ">&lt;script&gt;
a = 0;
function addCancion(){
        a++;

        var div = document.createElement('div');
        div.setAttribute('class', 'form-inline');
            div.innerHTML = '&lt;div style="clear:both" class="cancion_'+a+' col-md-offset-1 col-md-6"&gt;&lt;input class="form-control" name="cancion_'+a+'" type="text"/&gt;&lt;/div&gt;&lt;div class="cancion_'+a+' col-md-2""&gt;&lt;input class="form-control" name="duracion_'+a+'" type="text"/&gt;&lt;/div&gt;';
            document.getElementById('canciones').appendChild(div);document.getElementById('canciones').appendChild(div);
}
&lt;/script&gt;</pre>
<p>El formulario en un navegador al final queda como la imagen que os pongo a continuación:</p>
<p><img decoding="async" class="alignnone size-full wp-image-716" src="http://eduardocollado.com/wp-content/uploads/2016/11/formulairo_cd.png" alt="formulairo_cd" width="935" height="201" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/11/formulairo_cd.png 935w, https://www.eduardocollado.com/wp-content/uploads/2016/11/formulairo_cd-300x64.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/11/formulairo_cd-768x165.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/11/formulairo_cd-700x150.png 700w" sizes="(max-width: 935px) 100vw, 935px" /></p>
<p>El código completo, todo juntito, es el siguiente:</p>
<pre class="lang:default decode:true ">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;

&lt;!-- Latest compiled and minified CSS --&gt;
&lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"&gt;


&lt;script&gt;
a = 0;
function addCancion(){
        a++;

        var div = document.createElement('div');
        div.setAttribute('class', 'form-inline');
            div.innerHTML = '&lt;div style="clear:both" class="cancion_'+a+' col-md-offset-1 col-md-6"&gt;&lt;input class="form-control" name="cancion_'+a+'" type="text"/&gt;&lt;/div&gt;&lt;div class="cancion_'+a+' col-md-2""&gt;&lt;input class="form-control" name="duracion_'+a+'" type="text"/&gt;&lt;/div&gt;';
            document.getElementById('canciones').appendChild(div);document.getElementById('canciones').appendChild(div);
}
&lt;/script&gt;


&lt;/head&gt;

&lt;body&gt;
&lt;div class="container"&gt;
    &lt;h3&gt;Formulario de canciones de CD&lt;/h3&gt;
    &lt;form action="formulario2.html" id="formulario" method="get"&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-4"&gt;&lt;label&gt;Nombre CD&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-4"&gt;&lt;input class="form-control" name="nombre_cd" type="text"/&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-offset-1 col-md-6"&gt;&lt;label&gt;T&amp;iacute;tulo canci&amp;oacute;n&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-2"&gt;&lt;label&gt;Duraci&amp;oacute;n&lt;/label&gt;&lt;/div&gt;
        &lt;div class="col-md-1"&gt;&lt;input type="button" class="btn btn-success" id="add_cancion()" onClick="addCancion()" value="+" /&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;!-- El id="canciones" indica que la función de JavaScript dejará aquí el resultado --&gt;
    &lt;div class="row" id="canciones"&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">703</post-id>	</item>
		<item>
		<title>Git básico</title>
		<link>https://www.eduardocollado.com/2016/11/14/git-basico/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 14 Nov 2016 06:36:12 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[git]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=680</guid>

					<description><![CDATA[Git se ha vuelto imprescindible y es totalmente necesario al menos saber movernos con la aplicación, así que os he preparado un pequeño tutorial de&#8230;]]></description>
										<content:encoded><![CDATA[<p>Git se ha vuelto imprescindible y es totalmente necesario al menos saber movernos con la aplicación, así que os he preparado un pequeño tutorial de uso de git estándar.</p>
<p>Lo primero, crear el repositorio, para ello tenemos tres opciones, crear el repositorio en blanco, clonar un repositorio que tengamos en el disco o bien clonar un repositorio que esté en un servidor remoto</p>
<h3>Iniciar repositorios</h3>
<p><strong>git init</strong> -&gt; creamos repositorio en blanco</p>
<p><strong>git clone <em>/path/al/repositorio</em></strong> -&gt; clonamos un repositorio local</p>
<p><strong>git clone <em>usuario@servidor:/path/al/repositorio</em></strong> -&gt; clonamos un repositorio remoto</p>
<p>En git tenemos que tener en cuenta que tenemos tres estados, el <strong>directorio de trabajo</strong>, el <strong>Index</strong> donde está lo que vamos a guardar y <strong>HEAD</strong> que es lo guardado, vamos a verlo con un ejemplo.</p>
<h3>Añadir ficheros al repositorio</h3>
<p>Para añadir ficheros del directorio de trabajo al Index</p>
<p><strong>git add <em>&lt;fichero&gt;</em></strong></p>
<p><strong>git add *</strong> -&gt; Esto añade todos los ficheros</p>
<p>En este punto tenemos los ficheros añadidos al Index, y ahora tenemos que pasarlos al HEAD, para ello hay que hacer commit</p>
<p><strong>git commit -m «Mensaje para el commit»</strong></p>
<p>Ahora el fichero está en el HEAD, pero todavía no está en el repositorio, para ponerlo en el repositorio</p>
<p><strong>git push origin master</strong></p>
<p>Donde <em>master</em> es la rama del repositorio donde vamos a poner nuestro commit.</p>
<h3>Branches</h3>
<p>Para crear branches (ramas) lo hacemos con</p>
<p><strong>git checkout -b <em>mi_rama</em></strong></p>
<p>Para volver otra vez al master</p>
<p><strong>git checkout -b master</strong></p>
<p>Y para borrar mi_rama</p>
<p><strong>git branch -d <em>mi_rama</em></strong></p>
<p>Pero claro, esto es sólo local, no hemos subido nada a ningún sitio, para subirlo como antes</p>
<p><strong>git push origin <em>mi_rama</em></strong></p>
<h3>Actualizar</h3>
<p>Para actualizar nuestro repositorio local con el repositorio remoto</p>
<p><strong>git pull</strong></p>
<p>Y para mezclar con otra rama</p>
<p><strong>git merge <em>&lt;branch&gt;</em></strong></p>
<p>En caso de conflictos puede que sea necesario añadir ficheros con</p>
<p><strong>git add <em>&lt;fichero&gt;</em></strong></p>
<p>Pero podemos ver las diferencias antes de aplicarlas con</p>
<p><strong>git diff <em>&lt;branch_origen&gt; &lt;branch_destino&gt;</em></strong></p>
<h3>Etiquetas</h3>
<p>Para añadir etiquetas para las versiones de nuestro software se puede hacer con</p>
<p>git tag 0.0.1 7ace24e166</p>
<p>En ese comando hemos puesto una etiqueta a la versión 0.0.1 y hemos indicado los 10 primeros caracteres del commit que lo hemos sacado de hacer</p>
<pre class="lang:default decode:true">$ git log
commit 7ace24e1665fed899a0edf7e3670ae2ea6466a19
Author: Eduardo Collado &lt;edu@tecnocratica.net&gt;
Date: Sun Nov 13 20:28:51 2016 +0100

Primera subida</pre>
<h3>Reemplazar cambios locales</h3>
<p>Si queremos volver atrás a la versión del HEAD de un fichero concreto</p>
<p><strong>git checkout &#8212; <em>&lt;nombre_de_fichero&gt;</em></strong></p>
<p>Y si lo que queremos es tirar atrás todo el último cambio</p>
<p><strong>git fetch origin</strong><br />
<strong> git reset &#8211;hard origin/master</strong></p>
<p>De todos modos aquí os dejo un tutorial muy interesante que encontré en YouTube en un castellano perfecto <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/QGKTdL7GG24?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">680</post-id>	</item>
		<item>
		<title>CRUD en Rails</title>
		<link>https://www.eduardocollado.com/2016/11/13/crud-en-rails/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sun, 13 Nov 2016 15:57:20 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[rest]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=662</guid>

					<description><![CDATA[Para ver como funcionan los formularios para hacer CRUD (Create, Read, Update, Delete) en Rails vamos a hacer una aplicación muy sencilla que servirá de&#8230;]]></description>
										<content:encoded><![CDATA[<p>Para ver como funcionan los formularios para hacer CRUD (Create, Read, Update, Delete) en Rails vamos a hacer una aplicación muy sencilla que servirá de listín telefónico donde almacenaremos nombre, apellidos, dirección postal y todos los números de teléfono y e-mail que tengan nuestros contactos.</p>
<p>El esquema de base de datos será el siguiente:</p>
<p><img decoding="async" class="size-full wp-image-665 aligncenter" src="http://eduardocollado.com/wp-content/uploads/2016/11/agenda2.jpeg" alt="agenda" width="495" height="232" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/11/agenda2.jpeg 495w, https://www.eduardocollado.com/wp-content/uploads/2016/11/agenda2-300x141.jpeg 300w" sizes="(max-width: 495px) 100vw, 495px" /></p>
<p>Las relaciones serán 1 a muchos entre la tabla contactos y las tablas telefonos y e-mails.</p>
<p>Teniendo esto sabemos que necesitaremos 3 modelos que son <strong>contact</strong>, <strong>phone</strong> y <strong>email</strong> (ponemos los nombres en inglés para la pluralización de Rails), las tablas se llamarán igual.</p>
<p>En cuanto a controladores necesitaremos también uno por modelo para definir las acciones de CRUD que son <em>new</em>, <em>create</em>, <em>index</em>, <em>show</em>, <em>edit</em>, <em>update</em>, <em>delete</em> y <em>destroy</em>.</p>
<pre class="lang:default decode:true">rails new contacts -d mysql
</pre>
<p><span style="line-height: 1.5;">Y en mysql</span></p>
<pre class="lang:mysql decode:true ">mysql&gt; CREATE DATABASER contacts_development;
mysql&gt; GRANT ALL PRIVILEGES ON contacts_development.* TO 'edu'@'localhost' IDENTIFIED AS 'superpassword';</pre>
<p>Y pondremos en el fichero /config/database.yml los datos:</p>
<pre class="lang:default decode:true ">username: edu 
password: superpassword</pre>
<p>Y generamos los controllers</p>
<pre class="lang:default decode:true ">$ rails generate controller contacts new create index show edit update delete destroy
$ rails generate controller phones new create index show edit update delete destroy
$ rails generate controller emails new create index show edit update delete destroy</pre>
<p>Ahora generamos los modelos y creamos las tablas</p>
<pre class="lang:default decode:true ">$ rails generate model contact
$ rails generate model phone
$ rails generate model email</pre>
<p>Establecemos las relaciones entre tablas</p>
<p>/app/model/contact.rb</p>
<pre class="lang:default decode:true">class Contact &lt; ApplicationRecord 
    has_many :phones 
    has_many :emails 
end</pre>
<p>/app/model/phone.rb</p>
<pre class="lang:default decode:true">class Phone &lt; ApplicationRecord
  belongs_to :contact 
end</pre>
<p>/app/model/email.rb</p>
<pre class="lang:default decode:true">class Email &lt; ApplicationRecord
  belongs_to :contact
end</pre>
<blockquote><p>En nuestro caso no va a afectar mucho, pero al poner belongs_to y usar Rails 5, como es mi caso, está actuando el presence validator, que por defecto no viene activado en Rails 4, esto quiere decir que si no hay contacto no podemos crear ni teléfono ni email, algo que por otro lado tiene toda la lógica.</p></blockquote>
<p>Pues llegados a este punto inicial ya podemos empezar a trabajar en nuestro CRUD y crear la página web con el formulario.</p>
<p>Para tener una apariencia «mona» vamos a poner la cabecera de bootstrap en nuestro layout por defecto y creamos las migraciones, es decir, la estructura de las tablas:</p>
<p>app/layouts/application.html.erb</p>
<pre class="lang:default decode:true ">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Contacts&lt;/title&gt;
    &lt;%= csrf_meta_tags %&gt;

    &lt;%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %&gt;
    &lt;!-- Latest compiled and minified CSS --&gt;
    &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"&gt;
    &lt;%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %&gt;
    &lt;!-- Latest compiled and minified JavaScript --&gt;
    &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"&gt;&lt;/script&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;div class="container"&gt;
      &lt;%= yield %&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>db/migrate/20161113143332_create_contacts.rb</p>
<pre class="lang:default decode:true">class CreateContacts &lt; ActiveRecord::Migration[5.0]
  def change
    create_table :contacts do |t|
      t.string :nombre, :null =&gt; false
      t.string :apellidos, :null =&gt; false
      t.string :calle
      t.string :poblacion
      t.string :provincia
      t.string :pais
      t.timestamps
    end
  end
end</pre>
<p>db/migrate/20161113143340_create_phones.rb</p>
<pre class="lang:default decode:true ">class CreatePhones &lt; ActiveRecord::Migration[5.0]
  def change
    create_table :phones do |t|
      t.string :telefono
      t.string :contacts_id
      t.timestamps
    end
  end
end</pre>
<p>db/migrate/20161113143345_create_emails.rb</p>
<pre class="lang:default decode:true ">class CreateEmails &lt; ActiveRecord::Migration[5.0]
  def change
    create_table :emails do |t|
      t.string :email
      t.string :contacts_id
      t.timestamps
    end
  end
end</pre>
<p>Ahora ya podemos migrar</p>
<pre class="lang:default decode:true">$ rake db:migrate
== 20161113143332 CreateContacts: migrating ===================================
-- create_table(:contacts)
   -&gt; 0.0359s
== 20161113143332 CreateContacts: migrated (0.0360s) ==========================

== 20161113143340 CreatePhones: migrating =====================================
-- create_table(:phones)
   -&gt; 0.0368s
== 20161113143340 CreatePhones: migrated (0.0369s) ============================

== 20161113143345 CreateEmails: migrating =====================================
-- create_table(:emails)
   -&gt; 0.0411s
== 20161113143345 CreateEmails: migrated (0.0412s) ============================
</pre>
<p>Sólo nos queda configurar una ruta por defecto en nuestro archivo de rutas y a hacer formularios</p>
<pre class="lang:default decode:true ">Rails.application.routes.draw do
  root 'contacts#index'
  match ':controller(/:action(/:id))', :via =&gt; [:get, :post]
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</pre>
<p>Parece ser que en versiones posteriores de Rails se va a eliminar la ruta por defecto, pero mientras podremos seguirla utilizando.</p>
<p>Fijaros que la ruta por defecto la hemos creado sólo para dos verbos, get y post cuando lo suyo es que hubiéramos definido los 4 verbos <em>get</em>, <em>post</em>, <em>patch</em>, <em>delete</em> que se definen en REST.</p>
<p>También hemos definido que la página principal será el index de contacts.</p>
<p>Vamos a ir a construir el index del view contacts:</p>
<pre class="lang:default decode:true">&lt;h1&gt;Lista de contactos&lt;/h1&gt;
&lt;p&gt;&lt;%= link_to("Añadir contacto", {:controller =&gt; 'contacts', :action =&gt; 'new'}, data: { turbolinks: false } , :class =&gt; "btn btn-success" ) %&gt;&lt;/p&gt;

&lt;table class="table table-striped" summary="Contact List"&gt;
  &lt;tr class="header"&gt;
    &lt;th&gt;
      Apellidos
    &lt;/th&gt;
    &lt;th&gt;
      Nombre
    &lt;/th&gt;
    &lt;th&gt;
      Acciones
    &lt;/th&gt;
  &lt;/tr&gt;
  &lt;% @contact.each do |t| %&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;%= t.apellidos %&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;%= t.nombre %&gt;
    &lt;/td&gt;
    &lt;td&gt;
      &lt;%= link_to("Detalles", {:action =&gt; 'show', :id =&gt; t.id}, data: { turbolinks: false }, :class =&gt; "btn btn-primary") %&gt;
      &lt;%= link_to("Editar", {:action =&gt; 'edit', :id =&gt; t.id}, data: { turbolinks: false }, :class =&gt; "btn btn-primary") %&gt;
      &lt;%= link_to("Borrar", {:action =&gt; 'delete', :id =&gt; t.id}, data: { turbolinks: false }, :class =&gt; "btn btn-primary") %&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;% end %&gt;
&lt;/table&gt;
</pre>
<p>Los botones están así porque es la forma de definirlos en bootstrap y los turbolinks están en false porque si no falla en el momento en el que se entre desde otro enlace o se tire atrás.</p>
<p>Arriba hemos definido el enlace a new, así que aquí lo ponemos</p>
<pre class="lang:default decode:true ">&lt;h1&gt;Añadir Contacto&lt;/h1&gt;
&lt;table class="table table-striped" summary="Add Task" &gt;
    &lt;tr class="header"&gt;
        &lt;th&gt;&lt;/th&gt;
        &lt;th&gt;Contenido&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
            &lt;th&gt;Apellidos&lt;/th&gt;
            &lt;%= form_for(:contact, :url =&gt; {:action =&gt; 'create', :id =&gt; @contact.id}) do |f| %&gt;
            &lt;td&gt;&lt;%= f.text_field(:apellidos) %&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
            &lt;th&gt;Nombre&lt;/th&gt;
            &lt;td&gt;&lt;%= f.text_field(:nombre) %&gt;&lt;/td&gt;
    &lt;/tr&gt;

&lt;/table&gt;
        &lt;%= submit_tag("Añadir", :class =&gt; "btn btn-primary") %&gt;
        &lt;% end %&gt;</pre>
<p>Esto es realmente un formulario form_for en el que solicitamos los apellidos y el nombre, para que esto funcione en el controller tenemos que tener esta configuración</p>
<pre class="lang:default decode:true">  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(contact_params)
    @contact.save
    redirect_to(:action =&gt; 'index')

  private
    def contact_params
      params.require(:contact).permit(:nombre, :apellidos, :id, :poblacion, :provincia, :pais)
    end
</pre>
<p>Hemos utilizado un método privado en create para que desde new sólo se pasen los parámetros definidos, ni más ni menos, al método contact_params no se puede acceder desde fuera. El formulario se añadiría en new, pero el se valida en create, donde no hay nada en la vista porque hemos creado una redirección al index.</p>
<p>Ahora vamos a hacer el editar que es igual al crear</p>
<p>app/views/contacts/edit.html.erb</p>
<pre class="lang:default decode:true">&lt;h1&gt;Editar Contacto&lt;/h1&gt;
&lt;table class="table table-striped" summary="Add Task" &gt;
    &lt;tr class="header"&gt;
        &lt;th&gt;&lt;/th&gt;
        &lt;th&gt;Contenido&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
            &lt;th&gt;Apellidos&lt;/th&gt;
            &lt;%= form_for(:contact, :url =&gt; {:action =&gt; 'update', :id =&gt; @contact.id}) do |f| %&gt;
            &lt;td&gt;&lt;%= f.text_field(:apellidos) %&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
            &lt;th&gt;Nombre&lt;/th&gt;
            &lt;td&gt;&lt;%= f.text_field(:nombre) %&gt;&lt;/td&gt;
    &lt;/tr&gt;

&lt;/table&gt;
        &lt;%= submit_tag("Editar", :class =&gt; "btn btn-primary") %&gt;
        &lt;% end %&gt;
</pre>
<p>Y en el controller</p>
<pre class="lang:default decode:true">  def edit
    @contact = Contact.find(params[:id])
  end

  def update
    @contact = Contact.find(params[:id])
    @contact.update_attributes(contact_params)
    redirect_to(:action =&gt;'index')
  end


  private
    def contact_params
      params.require(:contact).permit(:nombre, :apellidos, :id, :poblacion, :provincia, :pais)
    end
</pre>
<p>La única diferencia es que aquí para editar lo hacemos fijándonos en el parámetro :id</p>
<p>Partiendo de aquí el resto sería muy parecido, diferencias las tendríamos en borrar donde tendríamos que borrar los emails asociados y los teléfonos</p>
<pre class="lang:default decode:true ">  def delete
    @contact = Contact.find(params[:id])
  end


  def destroy
    @contact = Task.find(params[:id])
    @phone = Action.where(contact_id: @contact)
    @phone.each do |t|
      t.destroy
    @email = Action.where(contact_id: @contact)
    @email.each do |t|
      t.destroy
    end
    @contact.destroy
    redirect_to(:action =&gt; 'index')
  end</pre>
<p>Con esto ya tendríamos una web de contactos, y a vosotros os dejo la creación de las páginas para los teléfonos y los emails.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">662</post-id>	</item>
		<item>
		<title>vim bootstrap</title>
		<link>https://www.eduardocollado.com/2016/11/03/vim-bootstrap/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 03 Nov 2016 18:44:02 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[screencast]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[vim bootstrap video]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=588</guid>

					<description><![CDATA[vim es sin duda uno de los editores de texto más potentes que existen y por supuesto de los más personalizables y disponible para cualquier&#8230;]]></description>
										<content:encoded><![CDATA[<p><a href="//www.vim.org/" target="_blank">vim</a> es sin duda uno de los editores de texto más potentes que existen y por supuesto de los más personalizables y disponible para cualquier plataforma, sí, para Windows también, aunque nunca lo he probado ahí.</p>
<p>El problema que tiene vim, además de su lenta curva de aprendizaje es la personalización, los plugins, etc&#8230; alrededor de vim hay un Mundo y lograr la personalización perfecta es muy laborioso.</p>
<p>Sin embargo, hoy encontré <a href="//vim-bootstrap.com/" target="_blank">vim-bootstrap</a>, una web que sólo tiene una función, generar el archivo de configuración de vim, seleccionas los lenguajes que quieres utilizar  y descargas un fichero llamado generate.vim, el cual copias en lugar de .vimrc y al arrancar vim todo se configurará sólo como por arte de magia.</p>
<p>Una maravilla, después de probarlo no vais a querer usar otra cosa, en serio, totalmente recomendable.</p>
<p>La única pega que le he encontrado es que al instalar html el código tiene dos líneas con unos saltos de carro feotes que hay que arreglarlos, pero nada más, os dejo el screencast.</p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/z6ytUSHh-CI?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">588</post-id>	</item>
		<item>
		<title>Ejemplo de relaciones de tablas en Rails</title>
		<link>https://www.eduardocollado.com/2016/11/01/ejemplo-de-relaciones-de-tablas-en-rails/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 01 Nov 2016 18:25:26 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[formas normales]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[relaciones bases de datos]]></category>
		<category><![CDATA[sql]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=548</guid>

					<description><![CDATA[Hoy vamos a ver como replicar estas relaciones entre tablas, las de la imagen, en rails, vamos a crear las tablas, y establecer las relaciones&#8230;]]></description>
										<content:encoded><![CDATA[<p>Hoy vamos a ver como replicar estas relaciones entre tablas, las de la imagen, en rails, vamos a crear las tablas, y establecer las relaciones entre ellas. Vamos a tener cuatro tablas:</p>
<p><img decoding="async" class="aligncenter" src="http://eduardocollado.com/wp-content/uploads/2016/11/esquema_bbdd.jpg" alt="esquema bbdd" /></p>
<ul>
<li>nombres</li>
<li>administradores</li>
<li>direcciones_ip</li>
<li>servidores</li>
</ul>
<p>El objetivo es poder definir las relaciones de forma que un administrador es una persona que tiene nombre y apellidos, ese administrador puede gestionar varios servidores, los cuales a su vez pueden ser gestionados por varios administradores, y cada servidor puede tener varias direcciones IP, pero cada dirección IP sólo puede estar en un servidor y en un interfaz.3</p>
<p>Si nos fijamos bien hay otra relación que no está definida entre tablas que es dirección IP e interfaz, es una relación uno a uno y como tal se puede incluir en una misma tabla, pero para nuestro ejemplo hemos separado administradores y el nombre de los mismos.</p>
<p>Lo primero que vamos a hacer como crear el proyecto, crear la base de datos, dar permisos a un usuario, configurar acceso al mysql en rails y crear las tablas, así que vamos a hacerlo todo seguido.</p>
<pre class="lang:default decode:true">ubuntu@ronr:~$ rails new gestionips -d mysql
ubuntu@ronr:~$ mysql -u root -p
mysql&gt; CREATE DATABASE gestionips_development;
mysql&gt; GRANT ALL PRIVILEGES ON gestionips_development.* TO 'edu'@'localhost' IDENTIFIED BY 'password';
ubuntu@ronr:~$ vim gestionips/config/database.yml
    default: &amp;default
    adapter: mysql2
    encoding: utf8
    pool: 5
    username: edu
    password: password
    socket: /var/run/mysqld/mysqld.sock
ubuntu@ronr:~/gestionips$ rails generate model nombre
ubuntu@ronr:~/gestionips$ rails generate model administrador
ubuntu@ronr:~/gestionips$ rails generate model direccion_ip
ubuntu@ronr:~/gestionips$ rails generate model servidor
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142603_create_nombres.rb
  class CreateNombres &lt; ActiveRecord::Migration[5.0]
    def change
      create_table :nombres do |t|  
        t.string("nombre", :limit =&gt; 25, :null =&gt; false)
        t.string("apellidos", :limit =&gt; 50, :null =&gt; false)
        t.timestamps
      end
    end
  end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142608_create_administradors.rb
  class CreateAdministradors &lt; ActiveRecord::Migration[5.0]
    def change
      create_table :administradors do |t|
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142620_create_direccion_ips.rb
  class CreateDireccionIps &lt; ActiveRecord::Migration[5.0]
    def change
      create_table :direccion_ips do |t|
        t.string("ip",:limit =&gt; 15, :null =&gt; false)
        t.string("interfaz", :limit =&gt; 25, :null =&gt; false)
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips/db/migrate$ vim 20161101142626_create_servidors.rb
  class CreateServidors &lt; ActiveRecord::Migration[5.0]
    def change
      create_table :servidors do |t|
        t.string("nombre", :limit =&gt; 50, :null =&gt; false)
        t.timestamps
      end
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate</pre>
<p>Una vez hecho esto ya podemos concentrarnos en las relaciones, ya que lo único que hemos hecho ha sido crear las tablas vacías con los campos que se indicaban en el diagrama.</p>
<p>Ahora vamos a meter unos datos dummy en la base de datos para empezar a trabajar, para ello desde la consola de rails entrando como <strong>rails console</strong> desde el directorio raiz del proyecto:</p>
<pre class="lang:default decode:true">nombre=Nombre.new(:nombre =&gt; "Eduardo", :apellidos =&gt; "Collado Cabeza")
nombre.save
nombre=Nombre.new(:nombre =&gt; "Maria", :apellidos =&gt; "Altamirano García")
nombre.save
nombre=Nombre.new(:nombre =&gt; "Norma", :apellidos =&gt; "Delgado Bugarín")
nombre.save
nombre=Nombre.new(:nombre =&gt; "Carlos", :apellidos =&gt; "Díaz Cruz")
nombre.save
direccion=DireccionIp.new(:ip =&gt; "12.12.43.12", :interfaz =&gt; "eth0")
direccion.save
direccion=DireccionIp.new(:ip =&gt; "56.21.123.14", :interfaz =&gt; "eth1")
direccion.save
direccion=DireccionIp.new(:ip =&gt; "121.32.5.7", :interfaz =&gt; "eth2")
direccion.save
direccion=DireccionIp.new(:ip =&gt; "173.11.53.122", :interfaz =&gt; "eth3")
direccion.save
servidor=Servidor.new(:nombre =&gt; "SRV-Rails1")
servidor.save
servidor=Servidor.new(:nombre =&gt; "SRV-Rails2")
servidor.save
servidor=Servidor.new(:nombre =&gt; "SRV-Rails3")
servidor.save
servidor=Servidor.new(:nombre =&gt; "SRV-Rails4")
servidor.save</pre>
<p>La tabla de administradores sólo tiene una columna que es ID, por eso no hemos rellenado nada después iremos creando según lo necesitemos, así que ya podemos empezar a trabajar.</p>
<h3>Relación uno a uno</h3>
<p>Entre las tablas nombres y administradores tenemos una relación uno a uno y vamos a decir que nombre tiene un administrador y que un administrador pertenece a un nombre, así que editamos ambos modelos:</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips/app/models$ vim nombre.rb 
  class Nombre &lt; ApplicationRecord
    has_one :administrador
  end
ubuntu@ronr:~/gestionips/app/models$ vim administrador.rb
  class Administrador &lt; ApplicationRecord
    belongs_to :nombre
  end
</pre>
<p>En la clase Administrador le hemos dicho que pertenece a nombre, es decir, es una llave foránea a la llave de la tabla nombre, así que tenemos que crear esa columna en la base de datos:</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips$ rails generate migration CrearForeignKeyEnAdministradoclass CrearForeignKeyEnAdministrador &lt; ActiveRecord::Migration[5.0]
    def change
      add_column("administradors","nombre_id","string")
    end
  end</pre>
<p>Y ejecutaremos el migrate</p>
<pre class="lang:default decode:true">ubuntu@ronr:~/gestionips$ rake db:migrate</pre>
<blockquote><p>Si fueramos atrás en versiones y volvieramos tendríamos que volver a introducir los datos dmmy que hemos puesto antes, ya que se borrarían las tablas con drop y al recrearlas lo haría sin contenido.</p></blockquote>
<p>En este momento entraríamos en la consola de rails para crear las cuatro relaciones uno a uno de nombre y administrador</p>
<pre class="lang:default decode:true">ubuntu@ronr:~/gestionips$ rails console
irb(main):001:0&gt; nombre=Nombre.find(1)
  Nombre Load (0.4ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 1 LIMIT 1
=&gt; #&lt;Nombre id: 1, nombre: "Eduardo", apellidos: "Collado Cabeza", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09"&gt;
irb(main):002:0&gt; administrador=Administrador.new()
=&gt; #&lt;Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil&gt;
irb(main):003:0&gt; nombre.administrador=administrador
  Administrador Load (0.4ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '1' LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '1')
   (5.3ms)  COMMIT
=&gt; #&lt;Administrador id: 5, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "1"&gt;
irb(main):004:0&gt; nombre=Nombre.find(2)
  Nombre Load (0.5ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 2 LIMIT 1
=&gt; #&lt;Nombre id: 2, nombre: "Maria", apellidos: "Altamirano García", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09"&gt;
irb(main):005:0&gt; administrador=Administrador.new()
=&gt; #&lt;Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil&gt;
irb(main):006:0&gt; nombre.administrador=administrador
  Administrador Load (0.3ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '2' LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '2')
   (12.9ms)  COMMIT
=&gt; #&lt;Administrador id: 6, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "2"&gt;
irb(main):007:0&gt; nombre=Nombre.find(3)
  Nombre Load (0.7ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 3 LIMIT 1
=&gt; #&lt;Nombre id: 3, nombre: "Norma", apellidos: "Delgado Bugarín", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09"&gt;
irb(main):008:0&gt; administrador=Administrador.new()
=&gt; #&lt;Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil&gt;
irb(main):009:0&gt; nombre.administrador=administrador
  Administrador Load (0.4ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '3' LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.2ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:13', '2016-11-01 17:00:13', '3')
   (5.6ms)  COMMIT
=&gt; #&lt;Administrador id: 7, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "3"&gt;
irb(main):010:0&gt; nombre=Nombre.find(4)
  Nombre Load (0.3ms)  SELECT  `nombres`.* FROM `nombres` WHERE `nombres`.`id` = 4 LIMIT 1
=&gt; #&lt;Nombre id: 4, nombre: "Carlos", apellidos: "Díaz Cruz", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09"&gt;
irb(main):011:0&gt; administrador=Administrador.new()
=&gt; #&lt;Administrador id: nil, created_at: nil, updated_at: nil, nombre_id: nil&gt;
irb(main):012:0&gt; nombre.administrador=administrador
  Administrador Load (0.5ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`nombre_id` = '4' LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.5ms)  INSERT INTO `administradors` (`created_at`, `updated_at`, `nombre_id`) VALUES ('2016-11-01 17:00:14', '2016-11-01 17:00:14', '4')
   (5.2ms)  COMMIT
=&gt; #&lt;Administrador id: 8, created_at: "2016-11-01 17:00:14", updated_at: "2016-11-01 17:00:14", nombre_id: "4"&gt;
</pre>
<p>Se ve más claro si vemos la tabla directamente en MySQL como se ha rellenado la columna nombre_id</p>
<pre class="lang:mysql decode:true">mysql&gt; select * from administradors;
+----+---------------------+---------------------+-----------+
| id | created_at          | updated_at          | nombre_id |
+----+---------------------+---------------------+-----------+
|  5 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 1         |
|  6 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 2         |
|  7 | 2016-11-01 17:00:13 | 2016-11-01 17:00:13 | 3         |
|  8 | 2016-11-01 17:00:14 | 2016-11-01 17:00:14 | 4         |
+----+---------------------+---------------------+-----------+
4 rows in set (0,00 sec)

mysql&gt; select * from nombres;
+----+---------+--------------------+---------------------+---------------------+
| id | nombre  | apellidos          | created_at          | updated_at          |
+----+---------+--------------------+---------------------+---------------------+
|  1 | Eduardo | Collado Cabeza     | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  2 | Maria   | Altamirano García  | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  3 | Norma   | Delgado Bugarín    | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
|  4 | Carlos  | Díaz Cruz          | 2016-11-01 16:54:09 | 2016-11-01 16:54:09 |
+----+---------+--------------------+---------------------+---------------------+
4 rows in set (0,00 sec)
</pre>
<h3>Relación uno a muchos</h3>
<p>Ahora vamos a ver la relación entre servidores y direcciones IP. Un servidor puede tener varias direcciones IP, pero cada dirección IP sólo puede estar en un servidor.</p>
<p>Aquí hay que decir que los métodos disponibles son los siguientes:</p>
<ul>
<li>servidor.direccion_ip</li>
<li>servidor.direccion_ip &lt;&lt; direccion_ip (añadir al array)</li>
<li>servidor.direccion_ip = direccion_ip, direccion_ip (introducimos todo el array)</li>
<li>servidor.direccion_ip.delete(direccion_ip) (borramos el objeto)</li>
<li>servidor.direccion_ip.destroy(direccion_ip) (borramos el objeto y de la base de datos)</li>
<li>servidor.direccion_ip.clear (borramos todo)</li>
<li>servidor.direccion_ip.empty? (preguntamos si está vacío el array)</li>
<li>servidor.direccion_ip.size (preguntamos el tamaño del array)</li>
</ul>
<p>Si lo trasladamos a lenguaje Rails tenemos que un servidor has_many :direccionesip</p>
<p>Así procedemos a configurar el fichero</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips/app/models$ vim servidor.rb 
  class Servidor &lt; ApplicationRecord
    has_many :direccion_ip
  end
ubuntu@ronr:~/gestionips/app/models$ vim direccion_ip.rb
  class DireccionIp &lt; ApplicationRecord
    belongs_to :servidor
  end
</pre>
<p>Y como tenemos belongs_to en direccion_ip significa que tenemos que crear una Foreign Key apuntando a servidor mediante una nueva migración</p>
<p>&nbsp;</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips$ rails generate migration CrearForeignKeyEnDireccionIp
ubuntu@ronr:~/gestionips$ vim db/migrate/20161101172341_crear_foreign_key_en_direccion_ip.rb
  class CrearForeignKeyEnDireccionIp &lt; ActiveRecord::Migration[5.0]
    def change
      add_column("direccion_ips","servidor_id","string")
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate</pre>
<p>Y entramos en la consola de rails. Vamos a asignar todas las IPs que tenemos en los datos dummy al primer servidor</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips$ rails console
Running via Spring preloader in process 7156
Loading development environment (Rails 5.0.0.1)
irb(main):001:0&gt; servidor=Servidor.find(1)
  Servidor Load (0.4ms)  SELECT  `servidors`.* FROM `servidors` WHERE `servidors`.`id` = 1 LIMIT 1
=&gt; #&lt;Servidor id: 1, nombre: "SRV-Rails1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09"&gt;
irb(main):002:0&gt; direccionip = DireccionIp.find(1)
  DireccionIp Load (0.4ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 1 LIMIT 1
=&gt; #&lt;DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil&gt;
irb(main):003:0&gt; servidor.direccion_ip &lt;&lt; direccionip
   (0.3ms)  BEGIN
  SQL (0.6ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:29:50', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 1
   (4.2ms)  COMMIT
  DireccionIp Load (0.7ms)  SELECT `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`servidor_id` = '1'
=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1"&gt;]&gt;
irb(main):004:0&gt; direccionip = DireccionIp.find(2)
  DireccionIp Load (0.7ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 2 LIMIT 1
=&gt; #&lt;DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil&gt;
irb(main):005:0&gt; servidor.direccion_ip &lt;&lt; direccionip
   (0.4ms)  BEGIN
  SQL (0.5ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:29:58', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 2
   (7.9ms)  COMMIT
=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1"&gt;, #&lt;DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1"&gt;]&gt;
irb(main):006:0&gt; direccionip = DireccionIp.find(3)
  DireccionIp Load (0.5ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 3 LIMIT 1
=&gt; #&lt;DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil&gt;
irb(main):007:0&gt; servidor.direccion_ip &lt;&lt; direccionip
   (0.2ms)  BEGIN
  SQL (0.6ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:30:03', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 3
   (7.4ms)  COMMIT
=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1"&gt;, #&lt;DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1"&gt;, #&lt;DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:03", servidor_id: "1"&gt;]&gt;
irb(main):008:0&gt; direccionip = DireccionIp.find(4)
  DireccionIp Load (0.4ms)  SELECT  `direccion_ips`.* FROM `direccion_ips` WHERE `direccion_ips`.`id` = 4 LIMIT 1
=&gt; #&lt;DireccionIp id: 4, ip: "173.11.53.122", interfaz: "eth3", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 16:54:09", servidor_id: nil&gt;
irb(main):009:0&gt; servidor.direccion_ip &lt;&lt; direccionip
   (0.2ms)  BEGIN
  SQL (0.5ms)  UPDATE `direccion_ips` SET `updated_at` = '2016-11-01 17:30:08', `servidor_id` = '1' WHERE `direccion_ips`.`id` = 4
   (7.6ms)  COMMIT
=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;DireccionIp id: 1, ip: "12.12.43.12", interfaz: "eth0", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:50", servidor_id: "1"&gt;, #&lt;DireccionIp id: 2, ip: "56.21.123.14", interfaz: "eth1", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:29:58", servidor_id: "1"&gt;, #&lt;DireccionIp id: 3, ip: "121.32.5.7", interfaz: "eth2", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:03", servidor_id: "1"&gt;, #&lt;DireccionIp id: 4, ip: "173.11.53.122", interfaz: "eth3", created_at: "2016-11-01 16:54:09", updated_at: "2016-11-01 17:30:08", servidor_id: "1"&gt;]&gt;</pre>
<p>Y si vemos en MySQL vemos que todas las IPs se han asignado al servidor_id 1, es decir, al primero:</p>
<pre class="lang:mysql decode:true ">mysql&gt; mysql&gt; select * from direccion_ips;
+----+---------------+----------+---------------------+---------------------+-------------+
| id | ip            | interfaz | created_at          | updated_at          | servidor_id |
+----+---------------+----------+---------------------+---------------------+-------------+
|  1 | 12.12.43.12   | eth0     | 2016-11-01 16:54:09 | 2016-11-01 17:29:50 | 1           |
|  2 | 56.21.123.14  | eth1     | 2016-11-01 16:54:09 | 2016-11-01 17:29:58 | 1           |
|  3 | 121.32.5.7    | eth2     | 2016-11-01 16:54:09 | 2016-11-01 17:30:03 | 1           |
|  4 | 173.11.53.122 | eth3     | 2016-11-01 16:54:09 | 2016-11-01 17:30:08 | 1           |
+----+---------------+----------+---------------------+---------------------+-------------+
4 rows in set (0,00 sec)
</pre>
<h3>Relación muchos a muchos</h3>
<p>Para establecer esta relación y cumplir las <a href="https://es.wikipedia.org/wiki/Forma_normal_(base_de_datos)" target="_blank">formas normales</a> es necesario crear una tabla join intermedia. Esta tabla estará compuesta únicamente por las dos claves foráneas y no tendrá tampoco la clave primaria (id) que crea por defecto Rails, así que habrá que quitársela con :id =&gt; false en la migración.</p>
<p>El nombre de la tabla será igual al nombre de las dos tablas unidas por guión y dispuestas por orden alfabético, en nuestro caso será administradors_servidors (el plural este tan raro es el que hace Rails añadiendo simplemente una s)</p>
<pre class="lang:default decode:true">ubuntu@ronr:~/gestionips$ rails generate migration CreateAdministradors_ServidorsJoin
ubuntu@ronr:~/gestionips$ ubuntu@ronr:~/gestionips$ vim db/migrate/20161101175712_create_administradors_servidors_join.rb
  class CreateAdministradorsServidorsJoin &lt; ActiveRecord::Migration[5.0]
    def change
      create_table :administradors_servidors, :id =&gt; false do |t|
        t.integer("administrador_id")
        t.integer("servidor_id")
      end
      add_index :administradors_servidors, ["administrador_id","servidor_id"], :name =&gt; 'admin_index'
    end
  end
ubuntu@ronr:~/gestionips$ rake db:migrate</pre>
<p>En el index hemos tenido que añadir</p>
<pre class="lang:default decode:true ">, :name =&gt; 'admin_index'</pre>
<p>porque nos daba este error en el rake db:migrate</p>
<pre class="lang:default decode:true ">Index name 'index_administradors_servidors_on_administrador_id_and_servidor_id' on table 'administradors_servidors' is too long; the limit is 64 characters
/home/ubuntu/gestionips/db/migrate/20161101175712_create_administradors_servidors_join.rb:7:in `change'
</pre>
<p>Ahora en los dos modeles involucrados tendremos que <em>poner has_and_belongs_to_many :el_otro_modelo</em>.</p>
<pre class="">has_and_belongs_to_many :el_otro_modelo
</pre>
<pre class="lang:default decode:true ">ubuntu@ronr:~/gestionips/app/models$ vim administrador.rb 
  class Administrador &lt; ApplicationRecord
    belongs_to :nombre
    has_and_belongs_to_many :servidor
  end
ubuntu@ronr:~/gestionips/app/models$ vim servidor.rb 
  class Servidor &lt; ApplicationRecord
    has_many :direccion_ip
    has_and_belongs_to_many :administrador
  end
</pre>
<p>Y ahora vamos introduciendo datos a base de buscar un administrador, un servidor y enlazarlos</p>
<pre class="lang:default decode:true">irb(main):032:0&gt;<strong> administrador=Administrador.find_by_id(6)</strong>
  Administrador Load (0.9ms)  SELECT  `administradors`.* FROM `administradors` WHERE `administradors`.`id` = 6 LIMIT 1
=&gt; #&lt;Administrador id: 6, created_at: "2016-11-01 17:00:13", updated_at: "2016-11-01 17:00:13", nombre_id: "2"&gt;
irb(main):033:0&gt; <strong>servidor=Servidor.find(4)</strong>
  Servidor Load (0.8ms)  SELECT  `servidors`.* FROM `servidors` WHERE `servidors`.`id` = 4 LIMIT 1
=&gt; #&lt;Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11"&gt;
irb(main):034:0&gt; <strong>administrador.servidor &lt;&lt; servidor</strong>
   (0.6ms)  BEGIN
  SQL (0.6ms)  INSERT INTO `administradors_servidors` (`administrador_id`, `servidor_id`) VALUES (6, 4)
   (9.0ms)  COMMIT
  Servidor Load (0.9ms)  SELECT `servidors`.* FROM `servidors` INNER JOIN `administradors_servidors` ON `servidors`.`id` = `administradors_servidors`.`servidor_id` WHERE `administradors_servidors`.`administrador_id` = 6
=&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11"&gt;, #&lt;Servidor id: 4, nombre: "SRV-Rails4", created_at: "2016-11-01 16:54:11", updated_at: "2016-11-01 16:54:11"&gt;]&gt;</pre>
<p>En MySQL se vería así:</p>
<pre class="lang:mysql decode:true ">mysql&gt; select * from administradors_servidors;
+------------------+-------------+
| administrador_id | servidor_id |
+------------------+-------------+
|                5 |           1 |
|                5 |           2 |
|                5 |           3 |
|                6 |           4 |
|                7 |           2 |
|                7 |           3 |
|                7 |           4 |
|                8 |           4 |
+------------------+-------------+
8 rows in set (0,00 sec)
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">548</post-id>	</item>
		<item>
		<title>Rails y MySQL</title>
		<link>https://www.eduardocollado.com/2016/10/30/rails-y-mysql/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sun, 30 Oct 2016 14:14:34 +0000</pubDate>
				<category><![CDATA[Sistemas]]></category>
		<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[screencast video]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=495</guid>

					<description><![CDATA[Hoy vamos a ver como se crean, modifican y eliminan registros en una tabla de una base de datos Mysql en Rails, obviamente también todo&#8230;]]></description>
										<content:encoded><![CDATA[<p>Hoy vamos a ver como se crean, modifican y eliminan registros en una tabla de una base de datos Mysql en Rails, obviamente también todo el proceso para tener creada la base de datos.</p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/-gd2AR7mG9g?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
<p>Lo primero será crear el proyecto de Rails indicando que queremos mysql como motor de bases de datos, eso se hacía con la opción -d y luego mysql.</p>
<pre class="lang:default decode:true">$ rails new railsymysql -d mysql
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
[...]
Use `bundle show [gemname]` to see where a bundled gem is installed.
run bundle exec spring binstub --all
* bin/rake: spring inserted
* bin/rails: spring inserted

</pre>
<p><span style="line-height: 1.5;">El proyecto se llamará railsymysql y con esto ya tenemos creada la estructura de ficheros necesaria.</span></p>
<p>Ahora lo primero será generar un modelo, al que vamos a llamar Usuario (los modelos se generan en singular en Rails)</p>
<pre class="lang:default decode:true">~/railsmysql$ rails generate model Usuario
Running via Spring preloader in process 465
invoke active_record
create db/migrate/20161030125505_create_usuarios.rb
create app/models/usuario.rb
invoke test_unit
create test/models/usuario_test.rb
create test/fixtures/usuarios.yml</pre>
<p>Al crear el modelo creamos el fichero de migración inicial para definir nuestra base de datos y definimos el modelo en si como ActiveRecord</p>
<p>Antes de nada como tenemos vamos a usar MySQL tendremos que crear la base de datos y configurar el fichero /config/database.yml</p>
<pre class="lang:yaml decode:true">[...]
default: &amp;default
adapter: mysql2
encoding: utf8
pool: 5
username: edu
password: password
socket: /var/run/mysqld/mysqld.sock

development:
&lt;&lt;: *default
database: railsmysql_development
[...]</pre>
<p>En mi caso voy a usar de usuario edu y como contraseña password, así que configuramos esto en el mysql</p>
<pre class="lang:mysql decode:true">mysql&gt; CREATE DATABASE railsmysql_development;
Query OK, 1 row affected (0,00 sec)

mysql&gt; GRANT ALL PRIVILEGES ON railsmysql_development.* TO "edu"@"localhost" IDENTIFIED BY "password";
Query OK, 0 rows affected, 1 warning (0,00 sec)</pre>
<p>En este punto procedemos a crear una tabla usuarios (plural del modelo) con sus campos, en este caso db/migrate/20161030125505_create_usuarios.rb</p>
<pre class="lang:ruby decode:true">class CreateUsuarios &lt; ActiveRecord::Migration
  def change
    create_table :usuarios do |t|
      t.column "nombre", :string, :limit =&gt; 25, :null =&gt; false
      t.string "apellidos", :limit =&gt; 50
      t.string "email", :limit =&gt; 40
      t.timestamps null: false
    end
  end
end
</pre>
<p>Y generaremos la migración</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030125505 CreateUsuarios: migrating ===================================
-- create_table(:usuarios)
-&gt; 0.0474s
== 20161030125505 CreateUsuarios: migrated (0.0475s) ==========================</pre>
<p>Y comprobamos en MySQL que se haya aplicado todo bien:</p>
<pre class="lang:mysql decode:true">mysql&gt; use railsmysql_development;
Database changed
mysql&gt; show tables;
+----------------------------------+
| Tables_in_railsmysql_development |
+----------------------------------+
| schema_migrations                |
| usuarios                         |
+----------------------------------+
2 rows in set (0,00 sec)

mysql&gt; show columns from usuarios;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| nombre     | varchar(25) | NO   |     | NULL    |                |
| apellidos  | varchar(50) | YES  |     | NULL    |                |
| email      | varchar(40) | YES  |     | NULL    |                |
| created_at | datetime    | NO   |     | NULL    |                |
| updated_at | datetime    | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
6 rows in set (0,00 sec)</pre>
<p>Ahora vamos a añadir una nueva columna, que se llame nickname y que vaya después de apellidos</p>
<pre class="lang:default decode:true">ubuntu@ronr:~/railsmysql$ rails generate migration Nickname
Running via Spring preloader in process 753
invoke active_record
create db/migrate/20161030133824_nickname.rb</pre>
<p>Y editamos el fichero de la migración</p>
<pre class="lang:default decode:true">class Nickname &lt; ActiveRecord::Migration
 def change
 add_column("usuarios","nickname",:string, :limit =&gt; 40, :after =&gt; "email")
 end
end</pre>
<p>Y ejecutamos la migración comprobando que termina, que vuelve al inicio (VERSION=0) y que vuelve al final:</p>
<pre class="lang:default decode:true">ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030133824 Nickname: migrating =========================================
-- add_column("usuarios", "nickname", :string, {:limit=&gt;40, :after=&gt;"email"})
 -&gt; 0.0637s
== 20161030133824 Nickname: migrated (0.0638s) ================================

ubuntu@ronr:~/railsmysql$ rake db:migrate VERSION=0
== 20161030133824 Nickname: reverting =========================================
-- remove_column("usuarios", "nickname", :string, {:limit=&gt;40, :after=&gt;"email"})
 -&gt; 0.0683s
== 20161030133824 Nickname: reverted (0.0705s) ================================

== 20161030125505 CreateUsuarios: reverting ===================================
-- drop_table(:usuarios)
 -&gt; 0.0161s
== 20161030125505 CreateUsuarios: reverted (0.0163s) ==========================

ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030125505 CreateUsuarios: migrating ===================================
-- create_table(:usuarios)
 -&gt; 0.0410s
== 20161030125505 CreateUsuarios: migrated (0.0412s) ==========================

== 20161030133824 Nickname: migrating =========================================
-- add_column("usuarios", "nickname", :string, {:limit=&gt;40, :after=&gt;"email"})
 -&gt; 0.0643s
== 20161030133824 Nickname: migrated (0.0644s) ================================</pre>
<p>Ahora ya podemos ver como en MySQL se ha creado</p>
<pre class="lang:mysql decode:true">mysql&gt; show columns from usuarios;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| nombre     | varchar(25) | NO   |     | NULL    |                |
| apellidos  | varchar(50) | YES  |     | NULL    |                |
| email      | varchar(40) | YES  |     | NULL    |                |
| nickname   | varchar(40) | YES  |     | NULL    |                |
| created_at | datetime    | NO   |     | NULL    |                |
| updated_at | datetime    | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
7 rows in set (0,00 sec)
</pre>
<p>Una vez creado vamos a editar el campo nickname para que no pueda ser NULL y que sea un índice. Podríamos hacerlo deshaciendo los cambio y volviendo a una versión anterior, nuestro caso podríamos ver el status y luego decidir ir a la versión 20161030125505 y luego editar el fichero de migración, pero sería muy fácil.</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rake db:migrate:status

database: railsmysql_development

Status Migration ID Migration Name
--------------------------------------------------
up 20161030125505 Create usuarios
up 20161030133824 Nickname</pre>
<p>Lo que queremos es crear una nueva migración que no sea reversible, es decir, crear una tabla es reversible porque se borra, pero modificar un campo no es directamente reversible ya que hay que indicar el cambio que hay que hacer y ya no nos serviría el método change de la migración teniendo que definir el método up y el método down.</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rails generate migration ModificarNickname
Running via Spring preloader in process 1184
      invoke  active_record
      create    db/migrate/20161030135054_modificar_nickname.rb</pre>
<p>Y modificaríamos el fichero de migración cambiando el método change por up y por down, muy importante que down se ejecute de forma simétria a up, primero lo último que hizo up y terminar por lo primero que se ejecutó en el método up.</p>
<pre class="lang:ruby decode:true ">class ModificarNickname &lt; ActiveRecord::Migration
  def up
    change_column("usuarios","nickname",:string,:limited =&gt; 40, :null =&gt; false)
    add_index("usuarios","nickname")
  end
  def down
    remove_index("usuarios","nickname")
    change_column("usuarios","nickname",:string,:limited =&gt; 40, :null =&gt; true)
  end
end</pre>
<p>Y comprobamos que todo funciona perfectamente</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030135054 ModificarNickname: migrating ================================
-- change_column("usuarios", "nickname", :string, {:limited=&gt;40, :null=&gt;false})
   -&gt; 0.0636s
-- add_index("usuarios", "nickname")
   -&gt; 0.0381s
== 20161030135054 ModificarNickname: migrated (0.1019s) =======================

ubuntu@ronr:~/railsmysql$ rake db:migrate VERSION=0
== 20161030135054 ModificarNickname: reverting ================================
-- remove_index("usuarios", "nickname")
   -&gt; 0.0228s
-- change_column("usuarios", "nickname", :string, {:limited=&gt;40, :null=&gt;true})
   -&gt; 0.0779s
== 20161030135054 ModificarNickname: reverted (0.1009s) =======================

== 20161030133824 Nickname: reverting =========================================
-- remove_column("usuarios", "nickname", :string, {:limit=&gt;40, :after=&gt;"email"})
   -&gt; 0.0619s
== 20161030133824 Nickname: reverted (0.0651s) ================================

== 20161030125505 CreateUsuarios: reverting ===================================
-- drop_table(:usuarios)
   -&gt; 0.0242s
== 20161030125505 CreateUsuarios: reverted (0.0244s) ==========================

ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030125505 CreateUsuarios: migrating ===================================
-- create_table(:usuarios)
   -&gt; 0.0433s
== 20161030125505 CreateUsuarios: migrated (0.0434s) ==========================

== 20161030133824 Nickname: migrating =========================================
-- add_column("usuarios", "nickname", :string, {:limit=&gt;40, :after=&gt;"email"})
   -&gt; 0.0628s
== 20161030133824 Nickname: migrated (0.0629s) ================================

== 20161030135054 ModificarNickname: migrating ================================
-- change_column("usuarios", "nickname", :string, {:limited=&gt;40, :null=&gt;false})
   -&gt; 0.0714s
-- add_index("usuarios", "nickname")
   -&gt; 0.0295s
== 20161030135054 ModificarNickname: migrated (0.1012s) =======================</pre>
<p>Ahora ya tenemos la tabla creada en nuestra base de datos y lo que vamos a hacer es jugar con los datos es guardarlos, buscarlos, modificarlos y borrarlos.</p>
<p>Para introducir datos lo que vamos a hacer es crear un objeto instanciado con el modelo Usuario, tal y como lo hemos creado antes.</p>
<p>Para hacer todo esto lo haremos desde la consola de rails. Hay que fijarse que además nos muestra el comando SQL que ejecuta.</p>
<pre class="wrap:true lang:ruby decode:true">ubuntu@ronr:~/railsmysql$ rails console
Running via Spring preloader in process 1371
Loading development environment (Rails 4.2.6)
irb(main):001:0&gt; datos = Usuario.new(:nombre =&gt; "Eduardo", :apellidos =&gt; "Collado Cabeza", :email =&gt; "asd@asd.com", :nickname =&gt; "ecollado")
=&gt; #&lt;Usuario id: nil, nombre: "Eduardo", apellidos: "Collado Cabeza", email: "asd@asd.com", nickname: "ecollado", created_at: nil, updated_at: nil&gt;
irb(main):002:0&gt; datos.save
   (0.3ms)  BEGIN
  SQL (0.6ms)  INSERT INTO `usuarios` (`nombre`, `apellidos`, `email`, `nickname`, `created_at`, `updated_at`) VALUES ('Eduardo', 'Collado Cabeza', 'asd@asd.com', 'ecollado', '2016-10-30 14:07:44', '2016-10-30 14:07:44')
   (8.3ms)  COMMIT
=&gt; true
</pre>
<p>Y en MySQL veremos reflejada la inserción</p>
<pre class="lang:mysql decode:true ">mysql&gt; mysql&gt; select * from usuarios;
+----+---------+----------------+-------------+----------+---------------------+---------------------+
| id | nombre  | apellidos      | email       | nickname | created_at          | updated_at          |
+----+---------+----------------+-------------+----------+---------------------+---------------------+
|  1 | Eduardo | Collado Cabeza | asd@asd.com | ecollado | 2016-10-30 14:07:44 | 2016-10-30 14:07:44 |
+----+---------+----------------+-------------+----------+---------------------+---------------------+
1 row in set (0,00 sec)
</pre>
<p>Ahora ya sabemos insertar datos en la base de datos ahora tenemos que buscar, para ello podemos hacerlo con el campo clave, el ID que automáticamente nos ha generado rails o por cualquier campo.</p>
<p>Para bucar por campo ID o usando search_by_xxxx</p>
<pre class="lang:ruby decode:true ">irb(main):019:0&gt; Usuario.find(4)
  Usuario Load (0.7ms)  SELECT  `usuarios`.* FROM `usuarios` WHERE `usuarios`.`id` = 4 LIMIT 1
=&gt; #&lt;Usuario id: 4, nombre: "Björk", apellidos: "Guðmundsdóttir", email: "bguomindsdf@islandia.com", nickname: "sugarcubes", created_at: "2016-10-30 14:20:00", updated_at: "2016-10-30 14:20:00"&gt;
irb(main):020:0&gt; Usuario.find_by_apellidos("Gato")
  Usuario Load (0.8ms)  SELECT  `usuarios`.* FROM `usuarios` WHERE `usuarios`.`apellidos` = 'Gato' LIMIT 1
=&gt; #&lt;Usuario id: 5, nombre: "Isidoro", apellidos: "Gato", email: "elgatoisidoro@gately.com", nickname: "gatelycat", created_at: "2016-10-30 14:21:14", updated_at: "2016-10-30 14:21:14"&gt;
</pre>
<p>Vamos a moficar el apellido a Isidoro Gato, con el id número 5 y le vamos a poner de apellido Gato con Botas en vez de Gato</p>
<pre class="lang:ruby decode:true">irb(main):001:0&gt; a_modificar = Usuario.find_by_apellidos("Gato")
  Usuario Load (0.5ms)  SELECT  `usuarios`.* FROM `usuarios` WHERE `usuarios`.`apellidos` = 'Gato' LIMIT 1
=&gt; #&lt;Usuario id: 5, nombre: "Isidoro", apellidos: "Gato", email: "elgatoisidoro@gately.com", nickname: "gatelycat", created_at: "2016-10-30 14:21:14", updated_at: "2016-10-30 14:21:14"&gt;
irb(main):002:0&gt; a_modificar.apellidos="Gato con Botas"
=&gt; "Gato con Botas
irb(main):003:0&gt; a_modificar.save
   (0.4ms)  BEGIN
  SQL (1.1ms)  UPDATE `usuarios` SET `apellidos` = 'Gato con Botas', `updated_at` = '2016-10-30 14:29:07' WHERE `usuarios`.`id` = 5
   (6.6ms)  COMMIT
=&gt; true</pre>
<p>Y MySQL vemos el cambio</p>
<pre class="lang:mysql decode:true ">mysql&gt; select * from usuarios;
+----+---------+------------------+--------------------------+------------+---------------------+---------------------+
| id | nombre  | apellidos        | email                    | nickname   | created_at          | updated_at          |
+----+---------+------------------+--------------------------+------------+---------------------+---------------------+
|  1 | Eduardo | Collado Cabeza   | asd@asd.com              | ecollado   | 2016-10-30 14:07:44 | 2016-10-30 14:07:44 |
|  2 | Maria   | Peña Hernandez   | mph@asd.com              | mpena      | 2016-10-30 14:17:38 | 2016-10-30 14:17:38 |
|  3 | Alberto | Smith Garcia     | cholo@jotmeil.com        | cholo      | 2016-10-30 14:18:20 | 2016-10-30 14:18:20 |
|  4 | Björk   | Guðmundsdóttir   | bguomindsdf@islandia.com | sugarcubes | 2016-10-30 14:20:00 | 2016-10-30 14:20:00 |
|  5 | Isidoro | Gato con Botas   | elgatoisidoro@gately.com | gatelycat  | 2016-10-30 14:21:14 | 2016-10-30 14:29:07 |
+----+---------+------------------+--------------------------+------------+---------------------+---------------------+
5 rows in set (0,00 sec)</pre>
<p>Aquí el problema es que hemos tenido que hacer tres cosas</p>
<ol>
<li>Buscar</li>
<li>Modificar</li>
<li>Guardar</li>
</ol>
<p>Y lo podemos hacer juntando los pasos 2 y 3 mediante update_attributes, vamos a volver a ponerle de apellidos simplemente Gato</p>
<pre class="lang:ruby decode:true ">irb(main):004:0&gt; a_modificar = Usuario.find_by_apellidos("Gato con Botas")
  Usuario Load (0.7ms)  SELECT  `usuarios`.* FROM `usuarios` WHERE `usuarios`.`apellidos` = 'Gato con Botas' LIMIT 1
=&gt; #&lt;Usuario id: 5, nombre: "Isidoro", apellidos: "Gato con Botas", email: "elgatoisidoro@gately.com", nickname: "gatelycat", created_at: "2016-10-30 14:21:14", updated_at: "2016-10-30 14:29:07"&gt;
irb(main):005:0&gt; a_modificar.update_attributes(:apellidos =&gt; "Gato")
   (0.3ms)  BEGIN
  SQL (0.7ms)  UPDATE `usuarios` SET `apellidos` = 'Gato', `updated_at` = '2016-10-30 14:31:50' WHERE `usuarios`.`id` = 5
   (8.4ms)  COMMIT
=&gt; true</pre>
<p>El resultado en ambos casos sería el mismo, sólo que con update_attributes nos ahorramos el guardar.</p>
<p>Ya sólo nos quedaría borrar un registro, eso lo haremos con destroy, que no es lo mismo que delete, en nuestro caso usaremos siempre destroy.</p>
<pre class="lang:ruby decode:true ">irb(main):008:0&gt; a_modificar = Usuario.find_by_apellidos("Gato")
  Usuario Load (0.8ms)  SELECT  `usuarios`.* FROM `usuarios` WHERE `usuarios`.`apellidos` = 'Gato' LIMIT 1
=&gt; #&lt;Usuario id: 5, nombre: "Isidoro", apellidos: "Gato", email: "elgatoisidoro@gately.com", nickname: "gatelycat", created_at: "2016-10-30 14:21:14", updated_at: "2016-10-30 14:31:50"&gt;
irb(main):009:0&gt; a_modificar.destroy
   (0.1ms)  BEGIN
  SQL (0.4ms)  DELETE FROM `usuarios` WHERE `usuarios`.`id` = 5
   (11.8ms)  COMMIT
=&gt; #&lt;Usuario id: 5, nombre: "Isidoro", apellidos: "Gato", email: "elgatoisidoro@gately.com", nickname: "gatelycat", created_at: "2016-10-30 14:21:14", updated_at: "2016-10-30 14:31:50"&gt;</pre>
<p>Ya sólo nos quedaría algo para bordar este post, que serían los named scopes, que vendría a ser algo parecido a una macro de SQL que nos permitirá reutilizar código y hacer la lectura y escritura de nuestro código más sencilla.</p>
<p>Los named scopes se llaman como si fueran métodos de ActiveRelation y requieren sintaxis lambda.</p>
<pre>   scope :active, lambda {where(:active =&gt; true)}
</pre>
<p>O con parámetros</p>
<pre>   scope :with_content_type, lambda {|ctype| where(:content_type =&gt; true)}
</pre>
<p>Se definen en el directorio /app/models dentro de los modelos correspondientes, en nuestro caso definiremos una nueva columna en la base de datos y crearemos un scope para sacar todos aquellos visibles e invisbles:</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rails generate migration Visible
Running via Spring preloader in process 1506
      invoke  active_record
      create    db/migrate/20161030144303_visible.rb
ubuntu@ronr:~/railsmysql$ vim db/migrate/20161030144303_visible.rb</pre>
<p>Y configuraremos el fichero de esta manera</p>
<pre class="lang:ruby decode:true">class Visible &lt; ActiveRecord::Migration
  def change
    add_column("usuarios","visible", :boolean, :default =&gt;true, :after =&gt; "nickname")
  end
end</pre>
<p>Luego haremos la migración</p>
<pre class="lang:default decode:true ">ubuntu@ronr:~/railsmysql$ rake db:migrate
== 20161030144303 Visible: migrating ==========================================
-- add_column("usuarios", "visible", :boolean, {:default=&gt;true, :after=&gt;"nickname"})
   -&gt; 0.1167s
== 20161030144303 Visible: migrated (0.1168s) =================================</pre>
<p>Y configuraremos en el fichero del modelo, en nuestro caso app/models/usuario.rb</p>
<pre class="lang:default decode:true">class Usuario &lt; ActiveRecord::Base
        scope :visible, lambda {where(:visible =&gt; true)}
        scope :invisible, lambda {where(:visible =&gt; false)}
        scope :ordenado, lambda {order("usuarios.id ASC")}
        scope :nuevos_primero, lambda {order("usuarios.id DESC")}
end</pre>
<p>Así tendremos por ejemplo:</p>
<pre class="lang:ruby decode:true ">irb(main):009:0* Usuario.visible
  Usuario Load (0.8ms)  SELECT `usuarios`.* FROM `usuarios` WHERE `usuarios`.`visible` = 1
=&gt; #&lt;ActiveRecord::Relation [#&lt;Usuario id: 1, nombre: "Eduardo", apellidos: "Collado Cabeza", email: "asd@asd.com", nickname: "ecollado", visible: true, created_at: "2016-10-30 14:07:44", updated_at: "2016-10-30 14:07:44"&gt;, #&lt;Usuario id: 2, nombre: "Maria", apellidos: "Peña Hernandez", email: "mph@asd.com", nickname: "mpena", visible: true, created_at: "2016-10-30 14:17:38", updated_at: "2016-10-30 14:17:38"&gt;, #&lt;Usuario id: 3, nombre: "Alberto", apellidos: "Smith Garcia", email: "cholo@jotmeil.com", nickname: "cholo", visible: true, created_at: "2016-10-30 14:18:20", updated_at: "2016-10-30 14:18:20"&gt;, #&lt;Usuario id: 4, nombre: "Björk", apellidos: "Guðmundsdóttir", email: "bguomindsdf@islandia.com", nickname: "sugarcubes", visible: true, created_at: "2016-10-30 14:20:00", updated_at: "2016-10-30 14:20:00"&gt;]&gt;
irb(main):010:0&gt; Usuario.invisible
  Usuario Load (0.7ms)  SELECT `usuarios`.* FROM `usuarios` WHERE `usuarios`.`visible` = 0
=&gt; #&lt;ActiveRecord::Relation []&gt;
irb(main):011:0&gt; Usuario.ordenado
  Usuario Load (0.7ms)  SELECT `usuarios`.* FROM `usuarios`  ORDER BY usuarios.id ASC
=&gt; #&lt;ActiveRecord::Relation [#&lt;Usuario id: 1, nombre: "Eduardo", apellidos: "Collado Cabeza", email: "asd@asd.com", nickname: "ecollado", visible: true, created_at: "2016-10-30 14:07:44", updated_at: "2016-10-30 14:07:44"&gt;, #&lt;Usuario id: 2, nombre: "Maria", apellidos: "Peña Hernandez", email: "mph@asd.com", nickname: "mpena", visible: true, created_at: "2016-10-30 14:17:38", updated_at: "2016-10-30 14:17:38"&gt;, #&lt;Usuario id: 3, nombre: "Alberto", apellidos: "Smith Garcia", email: "cholo@jotmeil.com", nickname: "cholo", visible: true, created_at: "2016-10-30 14:18:20", updated_at: "2016-10-30 14:18:20"&gt;, #&lt;Usuario id: 4, nombre: "Björk", apellidos: "Guðmundsdóttir", email: "bguomindsdf@islandia.com", nickname: "sugarcubes", visible: true, created_at: "2016-10-30 14:20:00", updated_at: "2016-10-30 14:20:00"&gt;]&gt;
irb(main):012:0&gt; Usuario.nuevos_primero
  Usuario Load (0.7ms)  SELECT `usuarios`.* FROM `usuarios`  ORDER BY usuarios.id DESC
=&gt; #&lt;ActiveRecord::Relation [#&lt;Usuario id: 4, nombre: "Björk", apellidos: "Guðmundsdóttir", email: "bguomindsdf@islandia.com", nickname: "sugarcubes", visible: true, created_at: "2016-10-30 14:20:00", updated_at: "2016-10-30 14:20:00"&gt;, #&lt;Usuario id: 3, nombre: "Alberto", apellidos: "Smith Garcia", email: "cholo@jotmeil.com", nickname: "cholo", visible: true, created_at: "2016-10-30 14:18:20", updated_at: "2016-10-30 14:18:20"&gt;, #&lt;Usuario id: 2, nombre: "Maria", apellidos: "Peña Hernandez", email: "mph@asd.com", nickname: "mpena", visible: true, created_at: "2016-10-30 14:17:38", updated_at: "2016-10-30 14:17:38"&gt;, #&lt;Usuario id: 1, nombre: "Eduardo", apellidos: "Collado Cabeza", email: "asd@asd.com", nickname: "ecollado", visible: true, created_at: "2016-10-30 14:07:44", updated_at: "2016-10-30 14:07:44"&gt;]&gt;</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">495</post-id>	</item>
		<item>
		<title>Primera página en Rails</title>
		<link>https://www.eduardocollado.com/2016/10/25/primera-pagina-en-rails/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 25 Oct 2016 06:25:05 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[screencast]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=478</guid>

					<description><![CDATA[Preparativos Una vez se ha creado el entorno en Rails, en mi caso en una máquina LXC procedemos a empezar a trabajar con ella. Lo&#8230;]]></description>
										<content:encoded><![CDATA[<h2>Preparativos</h2>
<p>Una vez se ha <a href="//eduardocollado.com/profesional/2016/10/22/instalacion-de-rails-en-ubuntu-16-04">creado el entorno en Rails</a>, en mi caso en una máquina LXC procedemos a empezar a trabajar con ella.</p>
<p>Lo primero es crear un tunel para que cuando desde nuestra máquina abramos localhost:3000 se abra realmente el puerto 3000 del contenedor donde tenemos instalado Rails, en mi caso utilizo la aplicación gSTM (Gnome SSH Tunnel Manager) que podéis instalarla desde la fuente o con</p>
<blockquote><p>apt-get install gstm</p></blockquote>
<p>En la máquina donde hay que correr rails es importante saber que tenemos que instalar nuestra llave ssh para no tener que poner el password todo el rato.</p>
<blockquote><p>ssh-copy-id ubuntu@10.0.3.252</p></blockquote>
<p><img decoding="async" class="alignleft size-medium wp-image-481" src="http://eduardocollado.com/wp-content/uploads/2016/10/gstm-300x249.png" alt="gstm" width="300" height="249" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/10/gstm-300x249.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/10/gstm.png 612w" sizes="(max-width: 300px) 100vw, 300px" />Una vez hecho eso la configuración del gSTM quedará tal y como se ve en la imagen de la izquierda.</p>
<p>Otra cosa que tenemos que hacer es preparar nuestro editor de textos, en mi caso el Sublime 2, para ello la forma más fácil es montar por ssh esa máquina en nuestro Ubuntu usando el navegador de archivos de Ubuntu.</p>
<p>Una vez montado el directorio remoto nos lo dejará en un directorio del estilo</p>
<blockquote><p>/run/user/1000/gvfs/sftp:host=10.0.3.252,user=ubuntu/home/ubuntu/prueba</p></blockquote>
<p>Pues abrimos ese directorio con el Sublime y ya estaremos modificando los ficheros directamente en nuestra máquina virtual.</p>
<p>Y por si «metemos la gamba» en algún momento es interesante configurarse el git, para ello en el directorio donde esté nuestro proyecto:</p>
<blockquote><p>git init</p>
<p>git add . &amp;&amp; git commit -m &#8216;nuevo proyecto en rails&#8217;</p></blockquote>
<p>Pues llegados a este punto ya podemos empezar a escribir código</p>
<h2>Creando una página</h2>
<p>Con casi total seguridad lo primero que vamos a querer es escribir una página de inicio, para ello tendremos que crear un controlador y una acción que nos generará el primer fichero.</p>
<p>Desde el directorio raiz del proyecto:</p>
<blockquote><p>rails generate controller home index</p></blockquote>
<p>Donde home es el controlador e index es la acción. Esto nos va a generar el directorio <em>/app/views/home</em> y dentro encontraremos<em> index.html.erb</em> que será nuestra página.</p>
<p>Pero también nos va a generar el fichero donde definiremos las acciones que será <em>/app/controllers/concerns/home_controler.rb</em>.</p>
<p>Y por último saber que nos va a generar el layout que es donde vamos a controlar todos los aspectos genéricos, es decir, las cabeceras html de los ficheros. Ese fichero en este caso será <em>/app/views/layouts/application.html.rb</em>.</p>
<h2>Creando código</h2>
<p>La página por defecto de rails la querremos cambiar por el index que acabamos de crear, para ello en el fichero /app/config/routes.rb que encontraremos algo como:</p>
<blockquote><p>get &#8216;home#index&#8217;</p></blockquote>
<p>podremos</p>
<blockquote><p>root &#8216;home#index&#8217;</p></blockquote>
<p>el get de arriba lo quitaremos pues ya no lo necesitamos, y a partir de este momento la acción index del controlador home será nuestra página principal.</p>
<p>Y ya podemos modificar el fichero de acción de <em>/app/views/home/index.html.erb </em>la acción poniendo por ejemplo</p>
<blockquote><p>&lt;h1&gt;Bienvenidos&lt;/h1&gt;<br />
&lt;p&gt;Esta es mi primera página en rails y se modifica en: /app/views/home/index.html.erb&lt;/p&gt;</p></blockquote>
<p>y al abrir el navegador en el puerto 3000 veremos justo esta página.</p>
<p>Si quisieramos crear otra acción dentro del mismo controlador tendríamos que crear un fichero nuevo en el directorio del controlador que será la acción correspondiente, por ejemplo <em>blog.html.erb</em> dentro de <em>/app/views/home</em>, luego tendríamos que modificar el fichero <em>routes.rb</em> poniendo una línea como esta:</p>
<blockquote><p> get &#8216;/blog&#8217; =&gt; &#8216;home#blog&#8217;</p></blockquote>
<p>Y, aunque no es necesario si es bueno hacerlo, modificando el home_controller.rm y añadiendo una acción vacía</p>
<blockquote><p>def blog</p>
<p>end</p></blockquote>
<p>Y ahora al ver la página http://localhost:3000/blog veremos la página que hemos creado, en este caso como no hemos creado contenido estará en blanco.</p>
<p>Y ahora si queremos añadir elementos comunes a las dos páginas lo que podemos hacer es editar el fichero <em>/app/views/layouts/application.html.erb</em> y poner un pequeño menú:</p>
<blockquote><p>&lt;a href=»/»&gt;Inicio&lt;/a&gt; | &lt;a href=»/blog»&gt;Blog&lt;/a&gt;</p></blockquote>
<p>O incluso cambiar el CSS incluyendo el bootstrap tirando de CDN metiendo este otro código</p>
<blockquote><p>&lt;!&#8211; Latest compiled and minified CSS &#8211;&gt;<br />
&lt;link rel=»stylesheet» href=»https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css» integrity=»sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u» crossorigin=»anonymous»&gt;</p></blockquote>
<p>Esto ahora lo podemos ver en un screencast que seguro que queda más claro.</p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/xQlMzVYShrY?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">478</post-id>	</item>
		<item>
		<title>Instalación de Rails en Ubuntu 16.04</title>
		<link>https://www.eduardocollado.com/2016/10/22/instalacion-de-rails-en-ubuntu-16-04/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sat, 22 Oct 2016 15:45:33 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[lxc]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[screencast]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=470</guid>

					<description><![CDATA[Rails es un framework para Ruby que nos permite generar aplicaciones web y que cada vez es más usado. Como el saber no ocupa lugar&#8230;]]></description>
										<content:encoded><![CDATA[<p>Rails es un framework para Ruby que nos permite generar aplicaciones web y que cada vez es más usado. Como el saber no ocupa lugar y no viene mal saber al menos instalar el entorno para empezar a tocarlo así que hoy os traigo un pequeño screencast sobre un tutorial llamado «<a href="//gorails.com/setup/ubuntu/16.04" target="_blank">Setup Ruby On Rails on Ubuntu 16.04 Xenial Xerus</a>» que a mi me ha parecido muy bueno y claro.</p>
<p>En el screencast instalo sobre una Ubuntu 16.04 limpia corriendo en LXC Ruby versión 2.3.1 con rbenv y Rails versión 4.2.6 con Mysql.</p>
<p>Si queréis ver como funciona LXC podéis ver mi post anterior titulado <a href="//eduardocollado.com/profesional/2016/08/26/lxc-en-ubuntu-16-04/">LXC en Ubuntu 16.04</a> y si queréis profundizar un poco más podéis leer <a href="//eduardocollado.com/profesional/2016/08/31/control-de-recursos-en-lxc-memoria-y-cpu/">Control de recursos en LXC, memoria y CPU</a>.</p>
<p><iframe loading="lazy" class="youtube-player" width="800" height="450" src="https://www.youtube.com/embed/3XREJSpKD2k?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=es-ES&#038;autohide=2&#038;wmode=transparent" allowfullscreen="true" style="border:0;" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">470</post-id>	</item>
		<item>
		<title>Cómo crear un clon de Twitter usando WordPress</title>
		<link>https://www.eduardocollado.com/2016/09/15/como-crear-un-clon-de-twitter-usando-wordpress/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 15 Sep 2016 16:17:03 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=448</guid>

					<description><![CDATA[Es posible crear un clon de Twitter usando WordPress ¿por qué no?, un clon como el de la foto: Obviamente si queréis le podéis poner&#8230;]]></description>
										<content:encoded><![CDATA[<p>Es posible crear un clon de Twitter usando WordPress ¿por qué no?, un clon como el de la foto:</p>
<p><img decoding="async" class="alignnone size-large wp-image-449" src="http://eduardocollado.com/wp-content/uploads/2016/09/clon-1024x709.png" alt="clon twitter" width="700" height="485" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/09/clon-1024x709.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/09/clon-300x208.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/09/clon-768x531.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/09/clon-700x484.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/09/clon.png 1026w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Obviamente si queréis le podéis poner los mismos colores que Twitter y así tendréis un clon perfecto, al final es poco más que una plantilla.</p>
<p>Todo tiene su público y hay gente que usa Twitter, gente que usa status, o cualquier otra opción de microblogging, o incluso gente que usa otras aplicaciones de microblogging.</p>
<p>También es posible que queramos en nuestra empresa, escuela o comunidad tener una herramienta de este estilo y que funcione en nuestra intranet, en fin, hay muchísimas posibildiades, cada uno tendrá las suyas y si esto le vale pues perfecto.</p>
<p>Yendo al grano os comento, yo tengo creado uno en <a href="//micro.eduardocollado.com" target="_blank">micro.eduardocollado.com</a> y lo instalé porque quería tomar notas que no salieran en Twitter, no todo tiene porque estar en Twitter.</p>
<p>El tema en concreto ser llama P2 y lo podéis descargar desde <a href="//wordpress.com/themes/p2" target="_blank">este enlace</a>, donde pone «<em><a href="https://public-api.wordpress.com/rest/v1/themes/download/p2.zip">Descarga P2 Classic</a> para tu sitio de WordPress alojado en otra empresa.</em>«</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">448</post-id>	</item>
		<item>
		<title>Como tener un Worpdress Multisite</title>
		<link>https://www.eduardocollado.com/2016/09/14/como-tener-un-wordpress-multisite/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 14 Sep 2016 18:46:55 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=426</guid>

					<description><![CDATA[El proceso para convertir nuestro WordPress en un WordPress Multisite nos permite por ejemplo darle un blog a cada empleado de nuestra empresa, a cada&#8230;]]></description>
										<content:encoded><![CDATA[<p>El proceso para convertir nuestro WordPress en un WordPress Multisite nos permite por ejemplo darle un blog a cada empleado de nuestra empresa, a cada usuario de nuestra comunidad o lo que queramos y permite una gestión centralizada de las actualizaciones y elementos comunes.</p>
<p>Los pasos serían los siguientes:</p>
<h3>Paso 1: Modificar el fichero wp-config.php</h3>
<p>El primer paso consiste en editar el fichero wp-config.php en nuestro servidor y poner las siguientes dos líneas:</p>
<blockquote><p>/* Multisite */<br />
define( &#8216;WP_ALLOW_MULTISITE&#8217;, true );</p></blockquote>
<h3>Paso 2: Desactivar los plugins, todos</h3>
<p>Para poder continuar tenemos que desactivar todos los plugins, y cuando digo todos es todos, posteriormente los podremos volver a activar, así que no hay que preocuparse.</p>
<h3>Paso 3: Finalizar la configuración del wp-config.php y modificar el .htaccess</h3>
<p>Ahora si vamos a Herramientas &#8211; Configuración de Red nos indicará los cambios que tenemos que hacer en el wp-config.php y el .htaccess.</p>
<p>En mi caso en el wp-config.php tuve que añadir las siguientes líneas justo encima de la línea con el contenido /* ¡Eso es todo, deja de editar! Feliz blogging */</p>
<p>Esta información se nos proporciona en Ajustes &#8211; Configuración de la red.</p>
<p><img decoding="async" class="alignnone size-large wp-image-432" src="http://eduardocollado.com/wp-content/uploads/2016/09/htaccess-1024x507.png" alt="Modificaciones en .htaccess y wp-config.php" width="700" height="347" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/09/htaccess-1024x507.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/09/htaccess-300x148.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/09/htaccess-768x380.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/09/htaccess-700x346.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/09/htaccess.png 1399w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Y quedó así:</p>
<blockquote><p>[&#8230;]<br />
define(&#8216;MULTISITE&#8217;, true);<br />
define(&#8216;SUBDOMAIN_INSTALL&#8217;, true);<br />
define(&#8216;DOMAIN_CURRENT_SITE&#8217;, &#8216;eduardocollado.com&#8217;);<br />
define(&#8216;PATH_CURRENT_SITE&#8217;, &#8216;/&#8217;);<br />
define(&#8216;SITE_ID_CURRENT_SITE&#8217;, 1);<br />
define(&#8216;BLOG_ID_CURRENT_SITE&#8217;, 1);</p></blockquote>
<p>También se nos indica que tenemos que modificar el fichero .htaccess y ponerle este contenido:</p>
<blockquote><p>RewriteEngine On<br />
RewriteBase /<br />
RewriteRule ^index\.php$ &#8211; [L]</p>
<p># add a trailing slash to /wp-admin<br />
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]</p>
<p>RewriteCond %{REQUEST_FILENAME} -f [OR]<br />
RewriteCond %{REQUEST_FILENAME} -d<br />
RewriteRule ^ &#8211; [L]<br />
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]<br />
RewriteRule ^(.*\.php)$ $1 [L]<br />
RewriteRule . index.php [L]</p></blockquote>
<p>No os preocupéis por el .htaccess antiguo, aunque si queréis podéis guardar una copia.</p>
<h3>Paso 4: Terminar de configurar nuestro WordPress Multisite</h3>
<p>Para terminar de configurar nuestro WordPress Multisite tendremos que ir a Ajustes &#8211; Ajustes de red y rellenar ahí las opciones que queramos, como por ejemplo quien puede crear nuevos blogs, cuotas por usuarios, etc&#8230; A esto es importarle dedicarle un rato para configurar adecuadamente nuestro WordPress Multisite.</p>
<h3><img decoding="async" class="alignnone size-large wp-image-434" src="http://eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24-1024x576.png" alt="configuración de la red" width="700" height="394" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24-1024x576.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24-300x169.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24-768x432.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24-700x394.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/09/Captura-de-pantalla-de-2016-09-14-20-30-24.png 1600w" sizes="(max-width: 700px) 100vw, 700px" />Paso 5: Configurar el servidor (DNSs y Apache)</h3>
<p>Para explicar este punto voy a utilizar la configuración de los servidores cloud de Neodigit y no otros, pero al final la idea subyacente es la misma, solo que en Neodigit siempre será muchísimo más sencillo de hacer.</p>
<p>Para configurar el DNS simplemente irémos a la zona DNS de nuestro dominio y crearemos una entrada comodín (wildcard) para que resuelvan todos los subdominios. La configuración será la siguiente:</p>
<p><img decoding="async" class="alignnone size-full wp-image-436" src="http://eduardocollado.com/wp-content/uploads/2016/09/registrowildcard.png" alt="Registro comodín" width="468" height="450" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/09/registrowildcard.png 468w, https://www.eduardocollado.com/wp-content/uploads/2016/09/registrowildcard-300x288.png 300w" sizes="(max-width: 468px) 100vw, 468px" /></p>
<p>Y ahora configuraremos el alias de host para nuestro dominio en Multidominio/Cloud &#8211; Alojamiento que corresponda &#8211; Subdominio &#8211; Alias de Host:</p>
<p><img decoding="async" class="alignnone size-large wp-image-437" src="http://eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias-1024x473.png" alt="Configuración alias" width="700" height="323" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias-1024x473.png 1024w, https://www.eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias-300x138.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias-768x354.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias-700x323.png 700w, https://www.eduardocollado.com/wp-content/uploads/2016/09/configuracion_alias.png 1439w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Y podremos una entrada del tipo:</p>
<blockquote><p>*.dominio.tld</p></blockquote>
<p>Nota: Obviamente es necesario tener contratado un servidor cloud o un multidominio.</p>
<h3>Paso 6: Empezar a trabajar</h3>
<p>Aquí nos volveremos a logar en nuestro wordpress y nos iremos a nuestro blog primigenio para volver a activar los plugins desactivados.</p>
<p>Y una vez hecho eso irémos a Mis Sitios &#8211; Blog y podremos entrar en el blog que queramos.</p>
<p>Simple y fácil <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">426</post-id>	</item>
		<item>
		<title>Control de recursos en LXC, memoria y CPU</title>
		<link>https://www.eduardocollado.com/2016/08/31/control-de-recursos-en-lxc-memoria-y-cpu/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Wed, 31 Aug 2016 08:33:06 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[lxc]]></category>
		<category><![CDATA[virtualización]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=371</guid>

					<description><![CDATA[El otro día publiqué una entrada en la que explicaba como levantar un contenedor LXC, el siguiente paso es configurar los recursos para que nuestros&#8230;]]></description>
										<content:encoded><![CDATA[<p>El otro día publiqué una entrada en la que explicaba <a href="http://www.eduardocollado.com/profesional/2016/08/26/lxc-en-ubuntu-16-04/" target="_blank">como levantar un contenedor LXC</a>, el siguiente paso es configurar los recursos para que nuestros contenedores no tengan todos toda la memoria y CPU de nuestra máquina física.</p>
<p>Para limitar memoria y CPU tenemos que utilizar el comando <strong>lxc-cgroup</strong> y utilizar los modificadores de kernel que vienen descritos en: <a href="http://www.mjmwired.net/kernel/Documentation/cgroups/memory.txt" target="_blank">http://www.mjmwired.net/kernel/Documentation/cgroups/memory.txt</a> que son los siguientes</p>
<blockquote>
<pre>tasks # attach a task(thread) and show list of threads
 cgroup.procs # show list of processes
 cgroup.event_control # an interface for event_fd()
 memory.usage_in_bytes # show current usage for memory
 (See 5.5 for details)
 memory.memsw.usage_in_bytes # show current usage for memory+Swap
 (See 5.5 for details)
 memory.limit_in_bytes # set/show limit of memory usage
 memory.memsw.limit_in_bytes # set/show limit of memory+Swap usage
 memory.failcnt # show the number of memory usage hits limits
 memory.memsw.failcnt # show the number of memory+Swap hits limits
 memory.max_usage_in_bytes # show max memory usage recorded
 memory.memsw.max_usage_in_bytes # show max memory+Swap usage recorded
 memory.soft_limit_in_bytes # set/show soft limit of memory usage
 memory.stat # show various statistics
 memory.use_hierarchy # set/show hierarchical account enabled
 memory.force_empty # trigger forced move charge to parent
 memory.pressure_level # set memory pressure notifications
 memory.swappiness # set/show swappiness parameter of vmscan
 (See sysctl's vm.swappiness)
 memory.move_charge_at_immigrate # set/show controls of moving charges
 memory.oom_control # set/show oom controls.
 memory.numa_stat # show the number of memory usage per numa node

memory.kmem.limit_in_bytes # set/show hard limit for kernel memory
 memory.kmem.usage_in_bytes # show current kernel memory allocation
 memory.kmem.failcnt # show the number of kernel memory usage hits limits
 memory.kmem.max_usage_in_bytes # show max kernel memory usage recorded

memory.kmem.tcp.limit_in_bytes # set/show hard limit for tcp buf memory
 memory.kmem.tcp.usage_in_bytes # show current tcp buf memory allocation
 memory.kmem.tcp.failcnt # show the number of tcp buf memory usage hits limits
 memory.kmem.tcp.max_usage_in_bytes # show max tcp buf memory usage recorded</pre>
</blockquote>
<p>Para limitar en un contenedor la memoria a 128M lo haríamos con el comando:</p>
<blockquote>
<pre>lxc-cgroup -n nombre_contenedor memory.limit_in_bytes 128M</pre>
</blockquote>
<p>Si nuestro servidor tiene 4 cores (0,1,2,3)  y queremos asignar el core 1 y 3 a un contenedor lo haríamos con el comando:</p>
<blockquote>
<pre>lxc-cgroup -n nombre_contenedor cpuset.cpus 1 3</pre>
</blockquote>
<p>Y llegamos al momento de limitar la swap que debería de ser algo del estilo:</p>
<blockquote>
<pre>lxc-cgroup -n nombre_contenedor memory.memsw.limit_in_bytes 128M</pre>
</blockquote>
<p>Sin embargo <strong>a mi esto no me ha funcionado</strong>, y no he encontrado otra forma de hacerlo, seguramente algo del kernel que tengo instalado en mi portátil. La idea es limitar la memoria total incluyendo swap a la memoria RAM para que de facto la memoria swap sea 0, pero como ya he comentado no me funciona, si alguien consigue que funcione que lo comente por favor.</p>
<p>Tenemos que tener en cuenta que todos los comandos que hemos usado hasta ahora sólo nos sirven para la ejecución en vivo, pero no para el arranque, si queremos que arranquen con estas opciones habría que modificar el fichero de configuración que se encuentra en</p>
<blockquote>
<pre>/var/lib/lxc/nombre_contenedor/config</pre>
</blockquote>
<p>Y ahí añadiríamos las opciones deseadas, siguiendo este formato y usando las opciones de arriba:</p>
<blockquote>
<pre>#Limite de memoria
lxc.cgroup.memory.limit_in_bytes = 256M

#Limite de CPU a 1 core
lxc.cgroup.cpuset.cpus = 1</pre>
</blockquote>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">371</post-id>	</item>
		<item>
		<title>LXC en Ubuntu 16.04</title>
		<link>https://www.eduardocollado.com/2016/08/26/lxc-en-ubuntu-16-04/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Fri, 26 Aug 2016 06:53:10 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[lxc]]></category>
		<category><![CDATA[virtualización]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=349</guid>

					<description><![CDATA[Vamos a levantar un contenedor LXC con las opciones por defecto en un Ubuntu 16.04, para ello lo instalaremos y haremos todo el proceso. Lo&#8230;]]></description>
										<content:encoded><![CDATA[<p>Vamos a levantar un contenedor LXC con las opciones por defecto en un Ubuntu 16.04, para ello lo instalaremos y haremos todo el proceso.</p>
<p>Lo primero será instalar el lxc, para ello simplemente:</p>
<pre class="">sudo apt-get install lxc</pre>
<p>Una vez instalado comprobaremos que esté todo bien, habilitado y soportado en el kernel:</p>
<p><img decoding="async" class="alignnone size-full wp-image-353" src="http://eduardocollado.com/wp-content/uploads/2016/08/lxc-checkconfig.png" alt="lxc-checkconfig" width="770" height="710" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/08/lxc-checkconfig.png 770w, https://www.eduardocollado.com/wp-content/uploads/2016/08/lxc-checkconfig-300x277.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/08/lxc-checkconfig-768x708.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/08/lxc-checkconfig-700x645.png 700w" sizes="(max-width: 770px) 100vw, 770px" /></p>
<p>Una vez está instalado podemos proceder a ver las plantillas que tenemos ya preinstaladas:</p>
<p><img decoding="async" class="alignnone size-full wp-image-355" src="http://eduardocollado.com/wp-content/uploads/2016/08/plantillas.png" alt="plantillas" width="689" height="78" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/08/plantillas.png 689w, https://www.eduardocollado.com/wp-content/uploads/2016/08/plantillas-300x34.png 300w" sizes="(max-width: 689px) 100vw, 689px" /></p>
<p>Y procedemos a instalar una de ellas, en nuestro caso una ubuntu con:</p>
<pre class="">edu@thinkpad:~$ sudo lxc-create -n ubuntu-lxc -t ubuntu</pre>
<p>Aquí <em>ubunut-lxc</em> es el nombre del contenedor y puede ser cualquier cosa. Si hubiermos escrito al final</p>
<pre class="">-- --release xenial</pre>
<p>le estaríamos diciendo la release concreta que quisieramos.</p>
<p>Una vez veamos por pantalla</p>
<pre class="">##
# The default user is 'ubuntu' with password 'ubuntu'!
# Use the 'sudo' command to run tasks as root in the container.
##</pre>
<p>ya tenemos preparado el contenedor para ser usado.</p>
<p>Para ver los contenedores que tenemos podemos poner</p>
<pre class="">sudo lxc-ls --fancy</pre>
<p><img decoding="async" class="alignnone size-full wp-image-360" src="http://eduardocollado.com/wp-content/uploads/2016/08/listado_contenedores.png" alt="listado contenedores" width="398" height="44" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/08/listado_contenedores.png 398w, https://www.eduardocollado.com/wp-content/uploads/2016/08/listado_contenedores-300x33.png 300w" sizes="(max-width: 398px) 100vw, 398px" /></p>
<p>Y podremos trabajar con ellos, los comandos básicos para trabajar con los lxc serían los siguiente (ubuntu-lxc es el nombre de mi contenedor, cambiar por el nombre que se quiera):</p>
<pre><strong>sudo lxc-ls --fancy</strong>: Listado de contenedores
<strong>sudo lxc-create -n ubuntu-lxc -t ubuntu -- --release xenial</strong>: Crear contenedor 
<strong>sudo lxc-start -n ubuntu-lxc -d</strong>: Arrancar contenedor 
<strong>sudo lxc-console -n ubuntu-lxc</strong>: Conectar a la consola, para salir de la misma Ctrl-a + q
<strong>sudo lxc-stop -n ubuntu-lxc</strong>: Parar el contenedor
<strong>sudo lxc-destroy -n ubuntu-lxc</strong>: Destruir el contenedor
<strong>sudo lxc-clone -o ubuntu-lxc -n nuevo-ubuntu-lxc</strong>: Clonar el contenedor</pre>
<p>Aquí os dejo un pequeño vídeo para que podáis ver el proceso,  veréis que he instado dos contenedores, el primero se ha bajado todo de ubuntu y el segundo como ya estaban los ficheros en la caché local ha tardado un par de segundos en instalarse.</p>
<p>Y que no os pase como a mi, para salir de la consola es Ctrl-a + q <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
<iframe loading="lazy" width="640" height="360" src="https://www.youtube.com/embed/4TzMl6mkqWU" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">349</post-id>	</item>
		<item>
		<title>Compartir la conexión a Internet con un Linux</title>
		<link>https://www.eduardocollado.com/2016/07/24/compartir-la-conexion-a-internet-con-un-linux/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Sun, 24 Jul 2016 14:09:16 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[redes]]></category>
		<category><![CDATA[software libre]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=311</guid>

					<description><![CDATA[A veces puede ocurrir que en un lugar donde solo tengáis wifi necesitéis pinchar algo con ethernet y justo en ese momento no dispongáis de&#8230;]]></description>
										<content:encoded><![CDATA[<p>A veces puede ocurrir que en un lugar donde solo tengáis wifi necesitéis pinchar algo con ethernet y justo en ese momento no dispongáis de ningún adaptador, pero sí de un portátil.</p>
<p>Por poner un ejemplo, quizás parezca un poco absurdo, pero creerme que no lo es, imaginad que os vais a pasar unos días fuera de casa y os lleváis vuestro teléfono IP, el cual no tiene wifi, pero os lo lleváis porque estáis muy contentos con él y los softphones que hay para linux son bastante peores, ya que no disponen de cancelación de ruido de fondo entre otras cosas.</p>
<p>Estáis fuera y con un móvil podéis hacer teetering y generar una Wifi, a la cual os conectáis con el portátil, pero &#8230; ¿cómo os conectáis con el teléfono?, no se puede a priori.</p>
<p>Bueno, sí se puede, para ello os comparto una de mis recetas de usos veraniegos <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<ol>
<li>Instalar un servidor de DHCP, ojo, no es necesario que arranque siempre por defecto, puede ser que no estemos siempre con la necesidad de generar DHCP.</li>
<li>Instalar un firewall para hacer NAT del teléfono (o red local generada).</li>
<li>Importantísimo, habilitar el fordwarding en el linux.</li>
</ol>
<p>Estos tres pasos los tengo hechos en mi portátil con una Ubuntu 16.04.</p>
<p>Para instalar un servidor de DHCP:</p>
<pre class="lang:default decode:true ">sudo apt-get install isc-dhcp-server</pre>
<p>Esto obviamente no es ciencia, ahora la configuración aunque no es muy complicada, os pego la que he usado en mi caso, os pego sólo lo que he añadido en el fichero /etc/dhcp/dhcpd.conf:</p>
<pre class="lang:default decode:true ">option subnet-mask 255.255.255.0;
option broadcast-address 192.168.89.255;
option routers 192.168.89.1;
option domain-name-servers 8.8.8.8,8.8.4.4;
option domain-name "eduangi.com";

subnet 192.168.89.0 netmask 255.255.255.0 {
range 192.168.89.10 192.168.89.100;
}</pre>
<p>En mi caso la red que he levantado para usar el teléfono y crear una lan donde me haga falta es la 192.168.89.0/24.</p>
<p>También hay que añadir al fichero /etc/default/isc-dhcp-server donde yo he añadido</p>
<pre class="lang:default decode:true ">INTERFACES="enx803f5d093ea8"</pre>
<p>Sí, mi ethernet se llama así :(, es un adaptador USB.</p>
<p>Y ahora lo más importante es que el servicio no arranque por defecto, para ello simplemente</p>
<pre class="lang:default decode:true ">sudo update-rc.d isc-dhcp-server disable</pre>
<p>Genial, ahora vamos a por el siguiente paso, el NAT, para ello necesitaremos tener instalado iptables y agregar la regla siguiente:</p>
<pre class="lang:default decode:true ">sudo iptables -t nat -A POSTROUTING -s 192.168.89.0/24 -o tun0 -j MASQUERADE</pre>
<p>Obviamente esta regla hace referencia a la red que yo me he dado de alta para tener mi teléfono corriendo y cada uno deberá de modificarsela. En cuanto a <em>-o tun0</em> hace referencia a que quiero que el tráfico quiero que salga por la Open VPN  que tengo corriendo en el portátil porque como ya he comentado la voy a usar para conectar un teléfono y obviamente la centralita no tiene IP pública.</p>
<p>Y para habilitar el forwarding simplemente ejecutaremos como root:</p>
<pre class="lang:default decode:true ">echo 1 &gt; /proc/sys/net/ipv4/ip_forward</pre>
<p>Ahora, como configurar esto va por gustos, en mi caso como hay he comentado antes al arrancar si quiero usar esa red me gusta levantarla a mano y esto es:</p>
<pre class="lang:default decode:true  ">sudo /etc/init.d/isc-dhcp-server start
sudo iptables -t nat -A POSTROUTING -s 192.168.89.0/24 -o tun0 -j MASQUERADE
sudo -i
echo 1 &gt; /proc/sys/net/ipv4/ip_forward</pre>
<p>Así que si tenéis la necesidad de levantar alguna red ethernet y conectarla a la wifi de vuestro linux ya sabéis como, aunque si sois gente «<em>normal</em>» quizás no necesitéis esto jamás, pero &#8230; nunca se sabe.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">311</post-id>	</item>
		<item>
		<title>Bienvenido Nextcloud</title>
		<link>https://www.eduardocollado.com/2016/06/16/bienvenido-nextcloud/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 16 Jun 2016 14:57:53 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[Nextcloud]]></category>
		<category><![CDATA[owncloud]]></category>
		<category><![CDATA[software libre]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=210</guid>

					<description><![CDATA[Nextcloud es un fork de Owncloud que, al menos a día de hoy, se ha quedado con el puesto que tenía Owncloud. De momento Nextcloud&#8230;]]></description>
										<content:encoded><![CDATA[<p><a href="https://nextcloud.com" target="_blank">Nextcloud</a> es un fork de Owncloud que, al menos a día de hoy, se ha quedado con el puesto que tenía Owncloud.</p>
<p>De momento Nextcloud proporciona el software pare el servidor y cliente para <del>móvil</del> Android, el cliente de escritorio todavía está en camino, pero irá llegando poco a poco.</p>
<p>De momento Nextcloud, que se ha formado como empresa independiente en Alemania, ofrece un servicio muy similar a Owncloud, pero prometen mejorar todo lo anterior.</p>
<p>De momento si queréis actualizar de Owncloud a Nextcloud el proceso es extremadamente fácil, lo único que hay que hacer es subir Nextcloud al servidor y poner ahí los directorios <strong>data</strong> y <strong>config</strong> el resto funcionará o debería de funcionar solo.</p>
<p>De momento yo ya he actualizado mi owncloud personal a nextcloud a ver qué tal funciona, de momento muy bien, y ya iremos hablando más sobre este fantástico producto que se puede instalar en proveedores como <a href="http://neodigit.net" target="_blank">Neodigit</a> para poder almacenar nuestros datos en un buen CPD.</p>
<p>Os dejo el Hangout para que podáis verlo y enteraros de primera mano.</p>
<p><iframe loading="lazy" src="https://www.youtube.com/embed/iMfokaX2r8g?feature=player_embedded" width="640" height="360" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">210</post-id>	</item>
		<item>
		<title>Máquinas virtuales con direccionamiento /32</title>
		<link>https://www.eduardocollado.com/2016/05/12/maquinas-virtuales-con-direccionamiento-32/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 12 May 2016 14:00:56 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[brs]]></category>
		<category><![CDATA[quagga]]></category>
		<category><![CDATA[red virtual]]></category>
		<category><![CDATA[redes]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=159</guid>

					<description><![CDATA[El modelo de 3 capas de Cisco (Acceso, Distribución y Core) es un buen modelo, pero a veces podemos optar en determinadas situaciones por modelos&#8230;]]></description>
										<content:encoded><![CDATA[<p>El <a href="http://www.ciscopress.com/articles/article.asp?p=2202410&amp;seqNum=4" target="_blank" rel="noopener">modelo de 3 capas de Cisco</a> (Acceso, Distribución y Core) es un buen modelo, pero a veces podemos optar en determinadas situaciones por modelos muy diferentes.</p>
<p>En entornos empresariales el modelo de una red de nivel 2 es fantástico pues permite tener los dispositivos en la misma red y que todos se vean entre si, además hablamos de dispositivos físicos como impresoras o PCs que rara vez van a moverse de sitio.</p>
<p>Ahora imaginemos un entorno de máquinas virtuales donde cada máquina es de un cliente y que no quiere que otros clientes vean su máquina por nivel 2, además, queremos poder mover la máquina de hipervisor, e incluso de rack o CPD. Imaginemos un entorno en el que lo queremos limpio sin multitud de vlans ni problemas de spanning tree.</p>
<p>Existen soluciones parciales, como trill u otras cerradas similares. Luego tenemos soluciones que nos permiten mover máquinas virtuales entre hipervisores, pero todas tienen una cosa en común, hay que «<em>casarse con el proveedor de red y/o virtualización</em>» y eso es algo que va en contra de la forma de trabajar que tenemos en <a href="http://tecnocratica.net" target="_blank" rel="noopener">Tecnocrática</a> o en <a href="http://neodigit.net" target="_blank" rel="noopener">Neodigit</a>.</p>
<p>Nosotros nos encontramos con ese problema en el momento de definir la plataforma de virtualización ya que queríamos ofrecer una serie de servicios que o no podíamos ofrecer con plataformas como VMWare o simplemente no eran soluciones competitivas ni en tiempo ni en dinero.</p>
<p>Ante esa situación lo que hicimos fue encerrarnos durante unos meses para intentar encontrar una solución, y al final la solución salió, por una parte una solución propia para el tema de los hipervisores de la que no puedo ofrecer muchos detalles al no estar directamente en mi área, pero totalmente automatizada y la solución de red que voy a pasar a describir a continuación y que se basa en anunciar rutas /32 dentro de nuestra red, una para cada servidor.</p>
<p>Al anunciar /32 lo que conseguimos es una granularidad total de la red, el problema es que el modelo de 3 capas de Cisco, que hasta ese día para mi era algo sagrado dejó de servir.</p>
<p>La forma de hacerlo consiste en ejecutrar uno o varios routers virtuales en cada hipervisor y hacer ahí los anuncios de routing, es decir, la solución fue llevar el nivel 3 directamente al hipervisor, sin vlans, sin nivel 2. Sin querer nos encontramos con un servicio nivel 3 puro desde el punto de tránsito hasta la propia máquina virtual, pero extremadamente flexible.</p>
<p>Una vez teníamos la teoría y alguna maqueta rudimentaria el siguiente paso era la automatización desde el <a href="https://panel.neodigit.net" target="_blank" rel="noopener">panel de control</a> que desarrollamos para nuestros servicios y que fuera el panel de control el que configurara los servidores virtuales y los routers.</p>
<p>Por supuesto no valía eso de crear plantillas y clonar pues eso requería de un trabajo de mantenimiento de plantillas totalmente absurdo pudiendo tener otras soluciones como PXE que sirve para configurar servidores, y ojo, fijaros que cosa tan curiosa, pero con PXE también podíamos levantar máquinas <a href="http://eduardocollado.com/2016/05/instalacion-de-quagga-en-debian/" target="_blank" rel="noopener">Debian con Quagga</a>, es decir, routers de forma automática.</p>
<p><figure id="attachment_161" aria-describedby="caption-attachment-161" style="width: 927px" class="wp-caption alignnone"><img decoding="async" class="wp-image-161 size-full" src="https://www.eduardocollado.com/wp-content/uploads/2016/05/mapa1.jpg" alt="Mapa general de red" width="927" height="572" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/05/mapa1.jpg 927w, https://www.eduardocollado.com/wp-content/uploads/2016/05/mapa1-300x185.jpg 300w, https://www.eduardocollado.com/wp-content/uploads/2016/05/mapa1-768x474.jpg 768w, https://www.eduardocollado.com/wp-content/uploads/2016/05/mapa1-700x432.jpg 700w" sizes="(max-width: 927px) 100vw, 927px" /><figcaption id="caption-attachment-161" class="wp-caption-text">Red pura de nivel 3</figcaption></figure></p>
<p>En nuestra solución el servidor que se aprovisionaba tenía que pasar por varios estados, el primero era autoconfigurarse por PXE y una vez configurado tenía que levantar con el direccionamiento público.</p>
<p>Una vez configurado el servidor éste arrancaba con la siguiente configuración de red.</p>
<blockquote><p># cat /etc/network/interfaces<br />
# This file describes the network interfaces available on your system<br />
# and how to activate them. For more information, see interfaces(5).</p>
<p># The loopback network interface<br />
auto lo<br />
iface lo inet loopback</p>
<p># The primary network interface<br />
allow-hotplug eth0<br />
iface eth0 inet static<br />
address 31.47.76.xxx<br />
netmask 255.255.255.255<br />
# dns-* options are implemented by the resolvconf package, if installed<br />
dns-nameservers xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx<br />
dns-search neodigit.net</p>
<p>post-up route add 10.10.10.10 dev eth0<br />
post-up route add default gw 10.10.10.10</p></blockquote>
<p>Como podéis ver la máquina tiene una IP y una máscara /32 y un gateway 10.10.10.10.</p>
<p>Para hacer esto todos los routers son iguales y tienen una pata, donde se conectan las máquinas virtuales que tienen la IP: 10.10.10.10/24 y la MAC: 00:80:10:10:10:10, todos iguales, por cierto, la mac es de un Commodore, por si alguien quiere ver qué router usamos la MAC le dirá que un Commodore, esta fue una licencia poética, pero nos permite que si movemos una máquina de hipervisor su gateway esté donde esté tendrá la misma IP y la misma MAC.</p>
<p>Ahora, el interfaz del router con al IP 10.10.10.10 correrá proxy arp. Antes de que nadie lo diga existe una opinión muy extendida que el rendimiento con proxy arp baja, pero claro, en este escenario podemos levantar tantos routers como queramos, así que el rendimiento nos da básicamente lo mismo porque nos cuesta lo mismo tener un router cada 200 máquinas que cada 10, así que en este escenario el rendimiento no es un problema, además es todo automático, nosotros no tocamos manualmente ningún equipo.</p>
<p>Para anunciar el servidor lo único que hacemos es inyectar una ruta /32 a la IP del servidor por el interfaz de proxy arp y esta se redistribuye automáticamente en el protocolo de routing, en nuestro caso y de momento OSPF, pero como es independiente a la plataforma es cambiable por otros.</p>
<p>Si queremos mover una máquina de hipervisor, o de país, lo único que hacemos es mover la máquina virtual borrar la ruta del router viejo y añadirla al nuevo, esta se redistribuirá automáticamente y a funcionar.</p>
<p>Además se pueden dar otro tipo de soluciones más imaginativas, por ejemplo un hipervisor en Madrid, otro en Miami, el de Miami, los dos con la misma IP y sincronizándose por otro interfaz, el de Madrid se anuncia con un coste y el Miami con un coste muy penalizado, si cae el de Madrid automáticamente la máquina de Miami cogería todo el tráfico y ya tendríamos un servicio de BRS.</p>
<p>Las posibilidades como podéis ver son enormes y nos abren un mundo de posibilidades casi infinito.</p>
<p>Este post es un resumen de una presentación hecha en el esNOG 17 en Barcelona el 12 de Mayo de 2016. La presentación la podéis descargar desde el siguiente enlace: <a href="http://eduardocollado.com/wp-content/uploads/2016/05/Modelo-de-distribución-sin-VLANs-para-centros-de-datos-virtualizados-El-enfoque-tecnócrata.pdf" target="_blank" rel="noopener">Modelo de distribución sin VLANs para centros de datos virtualizados: El enfoque tecnócrata</a>.</p>
<p>15 Mayo de 2016 &#8211; <strong>ACTUALIZACIÓN</strong></p>
<p>Ya tengo el enlace al vídeo de la charla, así que aquí os la dejo.</p>
<p><iframe loading="lazy" width="640" height="360" src="//www.youtube.com/embed/ra9cEayuwdw?start=3440" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">159</post-id>	<enclosure length="2423966" type="application/pdf" url="http://eduardocollado.com/wp-content/uploads/2016/05/Modelo-de-distribución-sin-VLANs-para-centros-de-datos-virtualizados-El-enfoque-tecnócrata.pdf"/><itunes:explicit>no</itunes:explicit><itunes:subtitle>El modelo de 3 capas de Cisco (Acceso, Distribución y Core) es un buen modelo, pero a veces podemos optar en determinadas situaciones por modelos&amp;#8230;</itunes:subtitle><itunes:summary>El modelo de 3 capas de Cisco (Acceso, Distribución y Core) es un buen modelo, pero a veces podemos optar en determinadas situaciones por modelos&amp;#8230;</itunes:summary><itunes:keywords>Blog Profesional, brs, quagga, red virtual, redes</itunes:keywords></item>
		<item>
		<title>Instalación de Quagga en Debian</title>
		<link>https://www.eduardocollado.com/2016/05/09/instalacion-de-quagga-en-debian/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Mon, 09 May 2016 05:00:13 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[ospf]]></category>
		<category><![CDATA[quagga]]></category>
		<category><![CDATA[redes]]></category>
		<category><![CDATA[software libre]]></category>
		<category><![CDATA[zebra]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=132</guid>

					<description><![CDATA[La instalación de quagga en Debian es bastante sencilla, pero tiene alguna cosilla que hay que tener en cuenta para finalizar con éxito este paso.&#8230;]]></description>
										<content:encoded><![CDATA[<p><img decoding="async" class="size-full wp-image-134 alignright" src="http://eduardocollado.com/wp-content/uploads/2016/05/Quagga-OpenSourceRouting-e1462733254517.png" alt="Quagga" width="301" height="245" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/05/Quagga-OpenSourceRouting-e1462733254517.png 301w, https://www.eduardocollado.com/wp-content/uploads/2016/05/Quagga-OpenSourceRouting-e1462733254517-300x244.png 300w" sizes="(max-width: 301px) 100vw, 301px" />La instalación de quagga en Debian es bastante sencilla, pero tiene alguna cosilla que hay que tener en cuenta para finalizar con éxito este paso.</p>
<p>Lo primero es saber qué es quagga, además de una especie de cebra extinta. Quagga se creó como fork de Zebra hace ya algunos años, si no recuerdo mal en el 2001 ó 2002, quizás algún año después, tras una discusión en la lista bastante agria sobre el uso que estaba haciendo el creador de Zebra con el software y las pocas actualizaciones que sufría el mismo, tampoco voy a meterme en esos charcos ya que esto lo comento de memoria y hace algunos años de aquello y tampoco voy a dedicar tiempo en buscar esos correos.</p>
<p>Quagga es un software formado por un conjunto de demonios que ejecutan distintos protocolos de routing y que convierten cualquier caja con GNU/Linux en un router totalmente funcional. Esto cuando salió el software era un poco extraño usarlo, pero el precio de los routers de la época lo justificaba, hoy en día el uso de routers en máquinas virtuales le dan una nueva vida al software y abren un buen abanico de posibilidades que ya iremos comentando.</p>
<p>Pues vamos a ver el proceso de instalación paso a paso.</p>
<p>Lo primero sería tener una distribución de Linux instalada, en mi caso voy a utilizar una Debian 8, obivamente si por alguna razón queréis instalar este software en distribuciones basadas en RedHat, Arch u otras tendréis que tener en cuenta que habrá diferencias.</p>
<p>Pero antes de instalar el software tenemos que tener una cosa clara, estamos instalando un router, es decir, el tráfico va a entrar por un interfaz y va a salir por otro, es decir, hay que habilitar el ip forwarding, que no se nos olvide:</p>
<blockquote><p># echo «1» &gt; /proc/sys/net/ipv4/ip_forward</p></blockquote>
<p>Y para que arraqneu siempre por defecto sin que tengamos que volver a configurar nada:</p>
<blockquote><p># echo «net.ipv4.ip_forward = 1» &gt;&gt; /etc/sysctl.conf</p></blockquote>
<p>Si no tenemos el ip forwarding habilitado en nuestra caja linux Quagga no funcionará bien, a ver, funcionará pero no enviará tráfico, será como un pisapapeles software, podremos comprobarlo con <em>show ip forwarding</em> en zebra o con vtysh, que ya lo veremos otro día, esto es malo:</p>
<blockquote><p>root@debian:/etc/quagga# vtysh -c «show ip forwarding»<br />
<strong>IP forwarding is off</strong></p></blockquote>
<p>Esto es bueno:</p>
<blockquote><p>root@debian:/etc/quagga# vtysh -c «show ip forwarding»<br />
<strong>IP forwarding is on</strong></p></blockquote>
<p>Bien, ya podemos dejarnos de cosas raras y proceder a instalar el software y los ficheros de ejemplo:</p>
<blockquote><p>apt-get install quagga quagga-doc</p></blockquote>
<p>Ahora prepararemos los ficheros de configuración que vamos a necesitar, para este ejemplo vamos a utilizar zebra.conf y ospfd.conf. Los ficheros estarán en el directorio /usr/share/doc/quagga/examples/</p>
<blockquote><p>root@debian:/usr/share/doc/quagga/examples# ls<br />
babeld.conf.sample isisd.conf.sample ripd.conf.sample zebra.conf.sample<br />
bgpd.conf.sample ospf6d.conf.sample ripngd.conf.sample<br />
bgpd.conf.sample2 ospfd.conf.sample vtysh.conf.sample</p></blockquote>
<p>De todos estos ficheros copiaremos zebra.conf.sample y ospfd.conf.sample y los llevaremos a /etc/quagga, obviamente los renombraremos quitando el .sample</p>
<blockquote><p># cp/usr/share/doc/quagga/examples/zebra.conf.sample /etc/quagga/zebra.conf<br />
# cp /usr/share/doc/quagga/examples/ospfd.conf.sample ospfd.conf</p></blockquote>
<p><strong>Texto obsoleto y eliminado el 10/05/2018<br />
</strong></p>
<p><span style="color: #d1d1d1;"><del>Ahora ya podemos habilitar los demonios que vamos a utilizar, para ello editaremos el fichero /etc/quagga/daemons</del></span></p>
<blockquote><p><span style="color: #d1d1d1;"><del>vim /etc/quagga/daemons</del></span></p>
<p><span style="color: #d1d1d1;"><del><strong>zebra=yes</strong></del></span><br />
<span style="color: #d1d1d1;"><del> bgpd=no</del></span><br />
<span style="color: #d1d1d1;"><del> <strong>ospfd=yes</strong></del></span><br />
<span style="color: #d1d1d1;"><del> ospf6d=no</del></span><br />
<span style="color: #d1d1d1;"><del> ripd=no</del></span><br />
<span style="color: #d1d1d1;"><del> ripngd=no</del></span><br />
<span style="color: #d1d1d1;"><del> isisd=no</del></span><br />
<span style="color: #d1d1d1;"><del> babeld=no</del></span></p></blockquote>
<p><strong>Actualización texto añadido el 10/05/2018</strong></p>
<p>Ahora ya podemos habilitar los demonios que vamos a utilizar, para ello ejecutaremos los siguientes comandos:</p>
<blockquote><p>/usr/sbin/zebra –dk<br />
/usr/sbin/ospfd –d<br />
/usr/sbin/bgpd –d<br />
/usr/sbin/isisd -d<br />
/usr/sbin/ripd -d<br />
/usr/sbin/&#8230;</p></blockquote>
<p>donde <strong>-d</strong> significa arrancar en modo demonio y <strong>-k</strong> significa que no puedan ser eliminadas las rutas del kernel</p>
<p>Y reiniciamos quagga</p>
<blockquote><p># /etc/init.d/quagga restart</p></blockquote>
<p>Y ya podemos entrar por telnet a la configuración de zebra y de ospf. Hay que tener en cuenta que a cada demonio se entra por un puerto diferente, aunque también podemos utilizar el nombre del puerto.</p>
<blockquote><p>zebra:2601<br />
ripd: 2602<br />
ripng: 2603<br />
ospfd: 2604<br />
bgpd: 2605<br />
ospf6d:  2606</p></blockquote>
<p>Ahora sí, vamos a por esa configuración.</p>
<blockquote><p>root@debian:/etc/quagga# telnet localhost zebra<br />
Trying ::1&#8230;<br />
Trying 127.0.0.1&#8230;<br />
Connected to localhost.<br />
Escape character is &#8216;^]&#8217;.</p>
<p>Hello, this is Quagga (version 0.99.23.1).<br />
Copyright 1996-2005 Kunihiro Ishiguro, et al.<br />
User Access Verification</p>
<p>Password:</p></blockquote>
<p>La contraseña por defecto es zebra (se puede ver en el fichero zebra.conf) y como podéis ver la configuración es muy similar a la configuración de IOS de Cisco, con lo cual si estáis mínimamente acostumbrados a tratar con routers Cisco la parte de configuración resulta trivial</p>
<blockquote><p>Router&gt; en<br />
Password:<br />
Router# sh run<br />
Router# sh running-config</p>
<p>Current configuration:<br />
!<br />
hostname Router<br />
password zebra<br />
enable password zebra<br />
!<br />
interface eth0<br />
ipv6 nd suppress-ra<br />
!<br />
interface eth1<br />
ipv6 nd suppress-ra<br />
!<br />
interface lo<br />
!<br />
!<br />
!<br />
line vty<br />
!<br />
end</p></blockquote>
<p>Y a partir de aquí podemos trabajar, en mi caso en la misma red que el interfaz eth1 tengo otros dos routers corriendo OSPF para poder ver algo con este router, así que configuraremos en el eth1 la IP 1.1.1.3/24 y luego una configuración estándar de OSPF.</p>
<p>Sin embargo hay que tener en cuenta una cosa y es que Quagga tiene un pequeño problema en la instalación, al menos en Debian y es que Quagga no tiene permisos para escribir sus propios ficheros de configuración, así que para solucionar eso tenéis que cambiar el propietario de los ficheros en el directorio /etc/quagga y ajustar los permisos:</p>
<blockquote><p># chown -R quagga:quaggavty<br />
# chmod 640 /etc/quagga/*.conf</p></blockquote>
<p>Por favor, no hagáis eso tan horrible de chmod 777, es bastante desagradable ;-).</p>
<p>Una vez hecho esto ya podemos guardar configuraciones</p>
<blockquote><p>root@debian:/etc/quagga# telnet localhost 2601<br />
Trying ::1&#8230;<br />
Trying 127.0.0.1&#8230;<br />
Connected to localhost.<br />
Escape character is &#8216;^]&#8217;.</p>
<p>Hello, this is Quagga (version 0.99.23.1).<br />
Copyright 1996-2005 Kunihiro Ishiguro, et al.<br />
User Access Verification</p>
<p>Password:<br />
Router&gt; en<br />
Password:<br />
Router# conf t<br />
Router(config)# int eth1<br />
Router(config-if)# ip ad 1.1.1.3/24<br />
Router(config-if)# exit<br />
Router(config)# exit<br />
Router# wr<br />
Configuration saved to /etc/quagga/zebra.conf<br />
Router#</p></blockquote>
<p>Y una vez hecho esto a la configuración del OSPF, para el ejemplo pongo la más sencilla posible.</p>
<blockquote><p>root@debian:/etc/quagga# telnet localhost 2604<br />
Trying ::1&#8230;<br />
Trying 127.0.0.1&#8230;<br />
Connected to localhost.<br />
Escape character is &#8216;^]&#8217;.</p>
<p>Hello, this is Quagga (version 0.99.23.1).<br />
Copyright 1996-2005 Kunihiro Ishiguro, et al.<br />
User Access Verification</p>
<p>Password:<br />
ospfd&gt; en<br />
ospfd# conf t<br />
ospfd(config)# router ospf<br />
ospfd(config-router)# network 0.0.0.0/0 area 0<br />
ospfd(config-router)# exit<br />
ospfd(config)# exit<br />
ospfd# wr</p></blockquote>
<p>Y ahora si vamos a zebra y hacemos un show ip route veremos lo siguiente:</p>
<blockquote><p>Router# sh ip rou<br />
Codes: K &#8211; kernel route, C &#8211; connected, S &#8211; static, R &#8211; RIP,<br />
O &#8211; OSPF, I &#8211; IS-IS, B &#8211; BGP, A &#8211; Babel,<br />
&gt; &#8211; selected route, * &#8211; FIB route</p>
<p>O 0.0.0.0/0 [110/11] via 1.1.1.1, eth1, 00:00:14<br />
K&gt;* 0.0.0.0/0 via 192.168.1.1, eth0<br />
O 1.1.1.0/24 [110/10] is directly connected, eth1, 00:00:15<br />
C&gt;* 1.1.1.0/24 is directly connected, eth1<br />
O&gt;* 31.47.76.123/32 [110/30] via 1.1.1.2, eth1, 00:00:14<br />
C&gt;* 127.0.0.0/8 is directly connected, lo<br />
O&gt;* 127.0.0.1/32 [110/10] is directly connected, lo, 00:00:20<br />
K&gt;* 169.254.0.0/16 is directly connected, eth0<br />
O 192.168.1.0/24 [110/10] is directly connected, eth0, 00:00:20<br />
C&gt;* 192.168.1.0/24 is directly connected, eth0<br />
Router#</p></blockquote>
<p>Como podéis ver tenemos rutas con la O de OSPF aprendidas por este router. Por supuesto podemos ver los vecinos de OSPF de la misma manera que los veríamos en un router Cisco:</p>
<p><img decoding="async" class="aligncenter size-full wp-image-144" src="https://www.eduardocollado.com/wp-content/uploads/2016/05/vecinos.png" alt="" width="812" height="96" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/05/vecinos.png 812w, https://www.eduardocollado.com/wp-content/uploads/2016/05/vecinos-300x35.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/05/vecinos-768x91.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/05/vecinos-700x83.png 700w" sizes="(max-width: 812px) 100vw, 812px" /></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">132</post-id>	</item>
		<item>
		<title>Ataques de DDoS y Blackhole</title>
		<link>https://www.eduardocollado.com/2016/04/28/ataques-de-ddos-y-blackhole/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Thu, 28 Apr 2016 05:30:22 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[ataques]]></category>
		<category><![CDATA[DDoS]]></category>
		<category><![CDATA[denegación de servicio]]></category>
		<category><![CDATA[redes]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=117</guid>

					<description><![CDATA[Los DDoS (ataques de denegación de servicio) son cada día más grandes y baratos de hacer y las opciones para defenderse de ellos no son&#8230;]]></description>
										<content:encoded><![CDATA[<p>Los DDoS (ataques de denegación de servicio) son cada día más grandes y baratos de hacer y las opciones para defenderse de ellos no son del todo efectivas.</p>
<p>Un ataque de DDoS no consiste en algo más complejo que mandar mucho tráfico hacia un destino más o menos concreto, puede ser una IP o un grupo de las mismas y lo peor es que es relativamente fácil hacerlo, contratarlo mejor dicho.</p>
<p>Existen servicios online, llamados pruebas de estrés, que te permiten contratar una gran avalancha de tráfico para poder probar el comportamiento de tu red ante ese tipo de situaciones, lo que pasa es que nadie te pregunta si <del>el ataque</del> la prueba de estrés que estás contratando es contra tu red o contra la de un tercero.</p>
<p>El ataque puede ser de muchos tipos, pero al final lo más habitual consiste en llenar los tránsitos (conexiones a Internet) de los ISPs de basura y muchos ISPs lamentablemente no saben defenderse ante eso y mueren, al menos durante un rato.</p>
<p>La solución mágica pasa por tener uno o varios equipos que supuestamente sirven para eso y lo que hacen es limpiar el tráfico, pero tienen un pequeño problema, el tránsito ya te lo han llenado con lo que por mucho tráfico que limpien ya no va a quedar hueco para que el tráfico bueno pase. Este tipo de soluciones sirven para aquellos que tienen redes enormes.</p>
<p>Otra opción es que los tránsitos te ofrezcan el servicio de mitigación, lo que pasa es que las soluciones que ofrecen pasan por entregarte el tráfico mitigado a través de un túnel <a href="https://es.wikipedia.org/wiki/GRE" target="_blank">GRE</a>, en fin, prefiero no opinar sobre una solución en la que te entregan el tráfico encapsulado en un túnel GRE. Por supuesto el tráfico mitigado tendrá un coste totalmente inasumible para la mayoría de ISPs.</p>
<p>Y luego está la opción del Blackhole, que es la más simple, barata y efectiva, sólo tiene un pequeño problema, que consiste en que el atacado es sacado de Internet, por decirlo de otra manera se borra la existencia del atacado de Internet entonces ya no le pueden atacar, pero claro, tampoco puede prestar servicio.</p>
<p>El proceso de blackhole consiste en utilizar la propiedad transistiva del atributo opcional <em>community</em> de BGP. De esta manera lo que hacemos es anunciar a nuestros tránsitos un prefijo /32 a la IP atacada con una community que defina esa IP como blackhole y nuestro transito pondrá dentro de su red una ruta a null, o lo que estime, de forma que esa IP no será accesible desde Internet.</p>
<p>Ahora la gracia, desde que empieza el ataque hasta que los tránsitos están llenos el tiempo que tenemos para reaccionar es muy poquito y va desde unos pocos segundos hasta dos o tres minutos, pero normalmente no va más allá, así que hay que ser muy rápido en detectar y aplicar el blackhole.</p>
<p>Podríamos automatizarlo, pero tendríamos que tener muy claro que no estamos incurriendo en un falso positivo, recordemos que el proceso de blackhole tiene el efecto de tirar a nuestro cliente y eso no se puede hacer a la ligera, tenemos que tener muy claro que no estamos incurriendo en falsos positivos.</p>
<p>También podríamos hacerlo de forma manual, pero claro, eso implica que alguien tiene que estar pendiente el tráfico constantemente y como hemos dicho el tiempo de reacción es realmente bajo.</p>
<p>Por supuesto ni que decir tiene que si uno es un ISP pequeñito y no tiene gente siempre dentro de la red si le atacan, como le saturarán los tránsitos, no podrá entrar para poner medidas a no ser que tenga algún sistema un tanto original porque la típica VPN para acceder por nuestra red no sirve, claro, la red está saturada.</p>
<p>Y ahora la segunda parte, has conseguido meter el blackhole y has parado el ataque, pero claro, tienes el cliente tirado, ¿cómo sabes si el ataque ya ha parado?, pues no, no lo sabes, así que con muchísimo cuidado tienes que probar levantar el blackhole y esperar a ver qué pasa, por supuesto teniendo preparado todo para volver a meter el blackhole de nuevo. Por supuesto se puede hacer de forma automática o no.</p>
<p>Por supuesto existen otras soluciones, a veces más imaginativas, a veces abocadas a un fracaso estrepitoso, pero que no sea por falta de ganas.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">117</post-id>	</item>
		<item>
		<title>Instalación de un Mikrotik Virtual CHR</title>
		<link>https://www.eduardocollado.com/2016/04/26/instalacion-de-un-mikrotik-virtual-chr/</link>
		
		<dc:creator><![CDATA[Eduardo Collado]]></dc:creator>
		<pubDate>Tue, 26 Apr 2016 09:37:03 +0000</pubDate>
				<category><![CDATA[Blog Profesional]]></category>
		<category><![CDATA[CHR]]></category>
		<category><![CDATA[Core Hosted Router]]></category>
		<category><![CDATA[mikrotik]]></category>
		<category><![CDATA[redes]]></category>
		<guid isPermaLink="false">http://eduardocollado.com/?p=104</guid>

					<description><![CDATA[Existen momentos en los que podemos necesitar un router instalado en una máquina virtual por ejemplo para encaminar varias vlans virtuales o porque directamente queremos&#8230;]]></description>
										<content:encoded><![CDATA[<p>Existen momentos en los que podemos necesitar un router instalado en una máquina virtual por ejemplo para encaminar varias vlans virtuales o porque directamente queremos más funcionalidades de las que nos puedan dar las plataformas de virtualización para routing.</p>
<p>Lo primero será bajar la imagen para instalar, para ello tenemos dos opciones la primera sería la imagen de <em>x86</em>, que aunque se puede instalar en una máquina virtual no es lo recomendable, y la opción buena que sería la de instalar la imagen de  <em>Cloud Hosted Router</em>. En cuanto a diferencias, además de los drivers, están el licenciamiento, el <em>Cloud Hosted Router</em> tiene la opción de licenciar de por vida, eso sí, limita el ancho de banda efectivo a 1Mbps, pero para hacer pruebas es más que suficiente, siempre y cuando no requieras otras características, en mi caso prefiero usar licencias de 60 días para pruebas sin limitaciones ni de ancho de banda ni de protocolos.</p>
<p><figure id="attachment_107" aria-describedby="caption-attachment-107" style="width: 777px" class="wp-caption aligncenter"><img decoding="async" class="wp-image-107 size-full" src="http://eduardocollado.com/wp-content/uploads/2016/04/licencia_chr.png" alt="Licencias del Cloud Hosted Router de Mikrotik" width="777" height="496" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/04/licencia_chr.png 777w, https://www.eduardocollado.com/wp-content/uploads/2016/04/licencia_chr-300x192.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/04/licencia_chr-768x490.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/04/licencia_chr-700x447.png 700w" sizes="(max-width: 777px) 100vw, 777px" /><figcaption id="caption-attachment-107" class="wp-caption-text">Licencias del Cloud Hosted Router de Mikrotik</figcaption></figure></p>
<ul>
<li>Imagen: <a href="http://www.mikrotik.com/download" target="_blank">http://www.mikrotik.com/download</a></li>
<li>Licencia: <a href="https://www.mikrotik.com/client/" target="_blank">https://www.mikrotik.com/client/</a></li>
</ul>
<p>&nbsp;</p>
<p>Pero antes de nada tenemos que instalarlo, en mi caso voy a instalarlo en un <a href="https://www.virtualbox.org/wiki/Downloads" target="_blank">Virtualbox</a>, aunque podemos utilizar cualquier otro software de virtualización.</p>
<p>Empezaremos creando la máquina virtual definida con Linux y Otro Linux 64-bits.</p>
<p><img decoding="async" class="alignnone wp-image-110 size-full" src="http://eduardocollado.com/wp-content/uploads/2016/04/paso1.png" alt="paso1" width="648" height="410" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/04/paso1.png 648w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso1-300x190.png 300w" sizes="(max-width: 648px) 100vw, 648px" /></p>
<p>En cuanto a la memoria dependiendo del servicio que vaya a ejecutar, pero para pruebas con 512Mb es más que suficiente, realmente con 64Mb es más que suficiente para la mayoría de servicios que no requieren trabajar con tablas de routing grandes.</p>
<p><img decoding="async" class="alignnone wp-image-111 size-full" src="http://eduardocollado.com/wp-content/uploads/2016/04/paso2.png" alt="paso2" width="648" height="410" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/04/paso2.png 648w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso2-300x190.png 300w" sizes="(max-width: 648px) 100vw, 648px" /></p>
<p>El disco duro lo bajaremos de la sección de <a href="http://www.mikrotik.com/download" target="_blank">descargas</a> de la web de mikrotik, en mi caso he seleccionado VDI.</p>
<p><img decoding="async" class="alignnone wp-image-112 size-full" src="http://eduardocollado.com/wp-content/uploads/2016/04/paso3.png" alt="paso3" width="648" height="410" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/04/paso3.png 648w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso3-300x190.png 300w" sizes="(max-width: 648px) 100vw, 648px" /></p>
<p>Y quedaría terminar de definir la máquina, en mi caso le he definido 4 redes, una de ellas un adaptador puente y he deshabilitado tanto el USB como el puerto serie.</p>
<p><img decoding="async" class="alignnone wp-image-113 size-full" src="http://eduardocollado.com/wp-content/uploads/2016/04/paso4-e1461662775783.png" alt="paso4" width="806" height="426" srcset="https://www.eduardocollado.com/wp-content/uploads/2016/04/paso4-e1461662775783.png 806w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso4-e1461662775783-300x159.png 300w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso4-e1461662775783-768x406.png 768w, https://www.eduardocollado.com/wp-content/uploads/2016/04/paso4-e1461662775783-700x370.png 700w" sizes="(max-width: 806px) 100vw, 806px" /></p>
<p>Y al arrancar ya tendremos nuestra máquina virtual funcionando entrando con usuario <strong>admin</strong> y sin contraseña.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">104</post-id>	</item>
	</channel>
</rss>