Descubriendo los problemas de HBO Go

Esta semana fue El Segundo episodio de Game of Thrones, yo estaba decidido a dejar el cable, porque ya nunca veo tele, e irme 100% a internet gracias a la magnifica experiencia que estaba teniendo con Netflix. Hoy intenté ver El Segundo episodio en vivo y me di cuenta que no podía acceder a la aplicación, hablar de frustración es poco...

Hace unas horas decidí buscar la razón del problema y me puse a investigar, primero intentando hacer una reproducción desde el navegador y buscar el manifiesto.

Web Console

Esta dirigia a footprint.net, este es un servicio CDN de Level3, al hacer un nmap me doy cuenta que solo resuelve a un registro A en vez de un CNAME. 

Consola

Ahi comenzamos con el primer problema, asignar una carga CDN a una sola IP pública, en vez de un CNAME, hace que no contemos con un ambiente realmente distribuido, esto es una preocupación y debería ser el primer jalon de orejas para Level3. Pero HBO no quizo confiar solamente en un proveedor y también uso los servicios de Cloudflare, de tal forma que su estrategia de distribución es STATIC CloudFlare y DYNAMIC MEDIA Level3, sin embargo a la hora de la verdad ambos fallan. La pregunta es, es culpa únicamente de los CDN?

El site confia en una serie de servicios que no están manejados por el CDN sino directamente por HBO llamados hbopaseo.com

HBO

Y es ahi donde detectamos El Segundo problema, primero el nameserver del dominio hbopaseo.com usa unicast (wikipedia https://es.wikipedia.org/wiki/Unidifusión) eso significa que en caso de muchos usuarios solo un difusor soporta la carga, haciendo un sticky sessions test, vemos que ese único difusor es un servidor DNS standalone, al cambiar la url desde la vista de inspección puedo confirmar que el sitio deja de funcionar por completo, incluso cuando todo lo demás sigue en perfecto estado. El Streaming usa el servicio de Microsoft IIS 8.5 de Transmisión adaptativa, sin embargo, en la entrega el reproductor lo maneja como transmisión fragmentada, lo que hace que se cree un buffer por particiones futuras, es decir, se descarga el capitulo completo en todos los usuarios al mismo tiempo en vez de descargar solo la siguiente secuencia y así sucesivamente.

Al final todos estos son problemas de arquitectura y de una mala aplicación de la tecnología. Algunos aprendizajes para mejorar en las siguientes transmisiones:

  1. Usar la nube, HBO esta confiando 100% en sus servicios on-premises los cuales no tienen la capacidad para manejar la demanda de la serie mas exitosa de la historia, intentan mitigarlos por CDN pero el CDN no hace magia, solo nos ayuda a optimizar las rutas y el consumo total de ancho de banda, igual esto no sirve para los llamados a las APIs que se manejan por un DNS Server en unicast. Los proveedores de nube de hiperescala (Azure, AWS o GCE) siempre tendrán mejor ancho de banda del que jamás podrá tener un centro de datos privado.
  2. Cambiar registros A por CNAME, crear ambientes distribuidos de forma global con DNS distribuido usando Anycast, todo manejado por distribuidores de trafico en topología round robin arriba y un CDN Akamai con restricciones regionales para manejar las geografias permitidas.
  3. Instanciar cada grupo de viewers como containers independientes con su propia PIP generando su propio DNS Name que es destruido al finalizar la sesión esto permite que las visualizaciones se manejen de forma independiente, en casos de problemas estos afectan a grupos reducidos de personas, y se solucionan destruyendo y recreando el contenedor. Los estados de cada viewer se guardaran en un No-SQL con distribución global.
  4. Las imágenes, estilos y JS los tienen en Adobe, yo las pondría Storage account de distintas nubes, con un manejador de trafico encima y un CDN con compresión. 

Hacer transmisión en nube es perfectamente posible, pero no se trata solo de tecnología, se trata también de buenos arquitectos.

 ACLARACION 1: El servicio de CDN de Level3 si esta balanceado, la cuestión es que resuelve inmediatamente a un registro A en vez de a un CNAME, eso responde a que no usan Nested Balancers. Si comparamos con Netflix nos vamos a topar con al menos 3 CNAMES antes de obtener una PIP

ACLARACION 2: Todo este diagnóstico está basado en la información que tenemos, hay cosas a las que obviamente no podemos acceder pero los invito a sugerirlas en los comentarios.

Cómo crear reglas de comunicación entre Azure subnets bajo el modelo de 4 capas usando PowerShell

Queridos muertos vivientes, si lo que necesitas es proteger tu red y aplicar las mejores prácticas para ganar mayor control y menos dolores de cabeza, usualmente pensamos en algo así:

Sin embargo, lograrlo es distinto a pensarlo :) es por eso que les traigo este script para asegurar tu entorno sin morir en el intento, no olvides completar las variables.

nsgazure.ps1

##################################################################################################################
# REGISTRAR LOS PARAMETROS CORRECTOS
##################################################################################################################
$NombreVNET = "VNETEU2DEMO01" #NOMBRE DE VNET
$ResourceGroup = "RGName" #NOMBRE DE GRUPO DE RECURSOS DE VNET
$Location = "eastus2" #CODIGO DE REGION
$FrontEndName = "EU2DESAFrontEnd02" #NOMENCLATURA SIN INCLUIR TIPO DE RECURSO
$FrontEndSubnet = "10.0.0.0/24" #SEGMENTO DE RED DE FrontEnd
$BackEndName = "EU2DESABackEnd02" #NOMENCLATURA SIN INCLUIR TIPO DE RECURSO
$BackEndSubnet = "10.1.0.0/24" #SEGMENTO DE RED DE BackEnd
$DataEndName = "EU2DESADataEnd02" #NOMENCLATURA SIN INCLUIR TIPO DE RECURSO
$DataEndSubnet = "10.2.0.0/24" #SEGMENTO DE RED DE DataEnd
$ADMSubnet = "10.3.0.0/24" #SEGMENTO DE RED DE ADMINISTRACION
##################################################################################################################
# RED DataEnd
##################################################################################################################
##################################################################################################################
# INBOUND
##################################################################################################################
$rule1 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_BackEnd_ALLOW -Description "RULE_IN_BackEnd_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 100 `
    -SourceAddressPrefix $BackEndSubnet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
$rule2 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ADM_ALLOW -Description "RULE_IN_ADM_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 110 `
    -SourceAddressPrefix $ADMSubnet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
$rule3 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ALL_DENY -Description "RULE_IN_ALL_DENY" `
    -Access Deny -Protocol * -Direction Inbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# OUTBOUND
##################################################################################################################
$rule4 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_OUT_ALL_DENY -Description "RULE_OUT_ALL_DENY" `
    -Access Deny -Protocol * -Direction Outbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# CREAR NSG
##################################################################################################################
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroup -Location $Location -Name "NSG$DataEndName" `
    -SecurityRules $rule1,$rule2,$rule3,$rule4
##################################################################################################################
# ASOCIAR NSG A SUBNET
##################################################################################################################
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroup -Name $NombreVNET
Set-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name "SNET$DataEndName" `
    -AddressPrefix $DataEndSubnet -NetworkSecurityGroup $nsg
##################################################################################################################
# RED BackEnd
##################################################################################################################
##################################################################################################################
# INBOUND
##################################################################################################################
$rule1 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_FrontEnd_ALLOW -Description "RULE_IN_FrontEnd_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 100 `
    -SourceAddressPrefix $FrontEndSubnet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
$rule2 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ADM_ALLOW -Description "RULE_IN_ADM_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 110 `
    -SourceAddressPrefix $ADMSubnet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
$rule3 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ALL_DENY -Description "RULE_IN_ALL_DENY" `
    -Access Deny -Protocol * -Direction Inbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# OUTBOUND
##################################################################################################################
$rule4 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_OUT_DataEnd_ALLOW -Description "RULE_OUT_DataEnd_ALLOW" `
    -Access Deny -Protocol * -Direction Outbound -Priority 100 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix $DataEndSubnet -DestinationPortRange *
$rule5 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_OUT_ALL_DENY -Description "RULE_OUT_ALL_DENY" `
    -Access Deny -Protocol * -Direction Outbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# CREAR NSG
##################################################################################################################
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroup -Location $Location -Name "NSG$BackEndName" `
    -SecurityRules $rule1,$rule2,$rule3,$rule4,$rule5
##################################################################################################################
# ASOCIAR NSG A SUBNET
##################################################################################################################
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroup -Name $NombreVNET
Set-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name "SNET$BackEndName" `
    -AddressPrefix $BackEndSubnet -NetworkSecurityGroup $nsg
##################################################################################################################
# RED FrontEnd
##################################################################################################################
##################################################################################################################
# INBOUND
##################################################################################################################
$rule1 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_HTTP_ALLOW -Description "RULE_IN_HTTP_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 100 `
    -SourceAddressPrefix * -SourcePortRange 80 `
    -DestinationAddressPrefix * -DestinationPortRange 80
$rule1A = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_HTTPS_ALLOW -Description "RULE_IN_HTTPS_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 110 `
    -SourceAddressPrefix * -SourcePortRange 443 `
    -DestinationAddressPrefix * -DestinationPortRange 443
$rule2 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ADM_ALLOW -Description "RULE_IN_ADM_ALLOW" `
    -Access Allow -Protocol * -Direction Inbound -Priority 120 `
    -SourceAddressPrefix $ADMSubnet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
$rule3 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_IN_ALL_DENY -Description "RULE_IN_ALL_DENY" `
    -Access Deny -Protocol * -Direction Inbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# OUTBOUND
##################################################################################################################
$rule4 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_OUT_DataEnd_ALLOW -Description "RULE_OUT_BackEnd_ALLOW" `
    -Access Deny -Protocol * -Direction Outbound -Priority 100 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix $BackEndSubnet -DestinationPortRange *
$rule5 = New-AzureRmNetworkSecurityRuleConfig -Name RULE_OUT_ALL_DENY -Description "RULE_OUT_ALL_DENY" `
    -Access Deny -Protocol * -Direction Outbound -Priority 3000 `
    -SourceAddressPrefix * -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange *
##################################################################################################################
# CREAR NSG
##################################################################################################################
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $ResourceGroup -Location $Location -Name "NSG$FrontEndName" `
    -SecurityRules $rule1,$rule1A,$rule2,$rule3,$rule4,$rule5
##################################################################################################################
# ASOCIAR NSG A SUBNET
##################################################################################################################
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $ResourceGroup -Name $NombreVNET
Set-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name "SNET$FrontEndName" `
    -AddressPrefix $FrontEndSubnet -NetworkSecurityGroup $nsg

##################################################################################################################
# GUARDANDO CAMBIOS                                                                                             #
##################################################################################################################
Set-AzureRmVirtualNetwork -VirtualNetwork $vnet
##################################################################################################################
# FIN DE SCRIPT                                                                                                  #
##################################################################################################################

 

Cómo automatizar la creación y configuración de clientes en Azure VPN Point-to-Site

Estimados muertos vivientes, Espero que este script les sea de utilidad, no se olviden modificar las variables del inicio para que funcione correctamente.

Pre-requisitos:

  • Azure Powershell actualizado
  • Cuenta de Azure
  • VPN Gateway creado.

Me costó algo de trabajo automatizar el proceso así que Espero les sea de ayuda :)

EjecutarVPN.ps1

##################################################################################################
# EDITAR VARIABLES DE CONFIGURACION AQUÍ                                                         #
##################################################################################################
$directorioTrabajo = "C:\trabajo"
$subscriptionName = "Consumo interno de Microsoft Azure"
$vpnClientPool = "172.17.201.0/24"
$vpnGWName = "LitWareGW2"
$rgName = "VNET2RG"
##################################################################################################
# NO EDITAR DESDE ESTE PUNTO                                                                     #
##################################################################################################
$nombreusuario=[Environment]::UserName
$rootCertName = "$nombreusuario.cer" 
$urlMakeCert = "http://opsgilityweb.blob.core.windows.net/makecert/makecert.exe"
##################################################################################################
write-host -foregroundcolor green "------------------------------------------------------------"
write-host -foregroundcolor green "CREANDO VPN POINT TO SITE"
write-host -foregroundcolor green "DESARROLLADO POR JOSE YAPUR"
write-host -foregroundcolor green "------------------------------------------------------------"
mkdir $directorioTrabajo
write-host -foregroundcolor green "-----creando certificado"
cd $directorioTrabajo
Invoke-WebRequest -Uri $urlMakeCert.Replace("""","") -OutFile "$directorioTrabajo\makecert.exe"
.\makecert.exe -sky exchange -r -n "CN=$nombreusuario""ROOT" -pe -a sha1 -len 2048 -ss My .\$rootCertName
.\makecert.exe -n "CN=$nombreusuario""Client" -pe -sky exchange -m 96 -ss My -in $nombreusuario"Root" -is my -a sha1
certutil -encode $rootCertName $nombreusuario"PublicKeyFile.cer"
 
$valorCert = Get-Content -Path $nombreusuario"PublicKeyFile.cer"
 
$publicCertData = $valorCert[0..($valorCert.count - 2)]
$publicCertData = $publicCertData[1..($publicCertData.count - 1)] | Out-String
 
write-host -foregroundcolor green "-----añadiendo cuenta de azure"
Add-AzureRmAccount
Select-AzureRmSubscription -SubscriptionName $subscriptionName
 
$vpnGW = Get-AzureRmVirtualNetworkGateway -ResourceGroupName $rgName -Name $vpnGWName  
Set-AzureRmVirtualNetworkGatewayVpnClientConfig -VirtualNetworkGateway $vpnGW -VpnClientAddressPool $vpnClientPool 
 
Add-AzureRmVpnClientRootCertificate -VpnClientRootCertificateName $rootCertName -VirtualNetworkGatewayName $vpnGWName -ResourceGroupName $rgName -PublicCertData $publicCertData
 
$downloadUrl = Get-AzureRmVpnClientPackage -ResourceGroupName $rgName -VirtualNetworkGatewayName $vpnGWName -ProcessorArchitecture Amd64  
write-host -foregroundcolor green "-----instalando cliente vpn"
Invoke-WebRequest -Uri $downloadUrl.Replace("""","") -OutFile "$directorioTrabajo\VPNclient.exe"
 
.\VPNclient.exe
write-host -foregroundcolor green "------------------------------------------------------------"
write-host -foregroundcolor green "SCRIPT FINALIZADO, VAYA A REDES Y CONECTESE A LA VPN, CONSULTAS A JOSE.YAPUR@L"
write-host -foregroundcolor green "------------------------------------------------------------"



Construyendo una solución de envío de SMS y llamadas en Azure

Hola Muertos vivientes, hoy les traigo un how-to para todos los spammers en potencia, cómo enviar SMS y llamadas a celulares de todo el mundo usando Azure y voz generada por texto. Para ello tenemos que ir a http://Twilio.com y crearnos una cuenta, ahi solicitaremos:

  • Un número de telefonico.
  • Un api key de cuenta.

El primer paso es crear una clase Twimlo.aspx.cs que genere el texto en SSML:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Notificaciones
{
    public partial class Twimlo : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.ContentType = "text/xml";
            Response.Write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Say voice=\"man\" language=\"es\" loop=\"2\">"+Request["mensaje"]+"</Say></Response>");
            Response.End();
        }
    }
}

Y en el Default.aspx yo he creado 4 controles, 2 cajas de texto, un checkbox y un botón, tal como se muestra en la imagen:

Luego en mi proyecto de Visual Studio he agregado desde NuGet el paquete de Twilio:

Install-Package Twilio

Ahora, vamos al code behind de Default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Twilio;

namespace Notificaciones
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e){}

        protected void Button1_Click(object sender, EventArgs e)
        {
 
            string accountSID = "ID de cuenta";
            string authToken = "token de cuenta";

            TwilioRestClient client;
            client = new TwilioRestClient(accountSID, authToken);
            if (CheckBox1.Checked)
            {
                String Url = "http://{nombredeSitio}.azurewebsites.net/Twimlo.aspx?mensaje=" + TextBox2.Text.Replace(" ", "%20");
                CallOptions options = new CallOptions();
                options.From = "{numero generado}";
                options.To = TextBox1.Text;
                options.Url = Url;
                var call = client.InitiateOutboundCall(options);
            }

            else
            {
                    client.SendMessage(
                        "{numero generado}", // From number, must be an SMS-enabled Twilio number
                        "{numero destino}",     // To number, if using Sandbox see note above
                        TextBox1.Text);                // message content
            }
        }
    }
}

Ahora solo queda publicar a un Azure WebApp y listo!

Soporte Gratis para los clientes de Azure EA

Muchos de nosotros usamos Azure como una extensión del centro de datos de nuestra empresa, al hacerlo ganamos muchísima flexibilidad, sin embargo también nos vemos enfrentados al hecho de que algunas cosas necesitan un cierto nivel técnico y algún tiempo de lectura para hacer que funcionen siguiendo las mejores prácticas.

Hoy, Microsoft ha dado un paso súper importante, ha hecho el soporte de $3600 y $12000 gratuito para clientes que tengan un EA.

El enlace donde se publica es https://azure.microsoft.com/es-es/blog/announcing-azure-support-upgrade-for-enterprises/

Mi material del DevDays 2016

Como lo prometido es deuda, comparto con ustedes lo presentado en el DevDays 2016

Presentación Azure Openess

Demo Script

#primer paso, crear grupo de recursos
azure group create AInterop "East US"
#crear cuenta de storage
azure storage account create demoperu0003
#plus, como crear un file share SMB 3.0
azure storage account connectionstring show demoperu0003

export AZURE_STORAGE_ACCOUNT=<account_name>
export AZURE_STORAGE_ACCESS_KEY=<key>
export AZURE_STORAGE_CONNECTION_STRING="<connection_string>"

azure storage share create sharedemo
azure storage directory create sharedemo prueba

#como automatizarlo en python
nano demo.py
#dentro de nano escribir
regiones = "East US"
grupo = "AInterop"
aplicacion = "demoperu00009"

from subprocess import call
call('azure storage account create '+aplicacion+' -l "'+regiones+'" -g "'+grupo+'"', shell=True)
#ctrl+x y luego Y
##########################
#containers, conectarse a la vm por ssh
ssh nomvm.cloudapp.net -l eladmin
#buscar repos
docker search debian
#correr un contenedor con debian
docker run -i -t debian /bin/bash
apt-get install zip
zip
exit
zip
#correr un contenedor con XAMPP
docker run -p 41061:22 -p 41062:80 -d -v ~/my_web_pages/my_testing_page1:/www tomsik68/xampp
#conectarse y modificar el index
ssh root@localhost -p 41061
cd /www
nano index.php



docker run -p 41072:22 -p 41078:80 -d -v ~/my_web_pages/my_testing_page1:/www tomsik68/xampp


 

Presentación de 0 a 100 en Azure ARM

Url usadas:

#Abrir la pagina de templates
https://github.com/Azure/azure-quickstart-templates/ 
#Navegar a la creacion de 2 vm con LB
https://github.com/Azure/azure-quickstart-templates/tree/master/201-2-vms-internal-load-balancer