Azure + Relay Binding + HTTPS mutual authentication? Talán egyszer… (I. rész)

Nemrég felmerült egy igény, miszerint egy készülő REST stílusú szervizt esetleg Azure AppFabric Service Bus Relay szervizen keresztül kellene megjeleníteni. Ez nem tűnt nagy problémának, hiszen a WCF-nek köszönhetően, egy-két apróság mellett, csak a WebHttpBinding-ot kell WebHttpRelayBinding-ra kicserélni. Legalábbis elviekben.

Ennek a cikknek nem az Azure Relay szerviz kritizálása a célja. A probléma áttekintése inkább csak egy vezérfonal, hogy több más területtel megismerkedhessünk.

Mi az a relay szerviz?

Legkönnyebben azok érthetik meg, hogy mire jó a relay szerviz, akik nagyobb gépparkkal rendelkező cégnél dolgoznak, vagy az iskolájuk gépterme sok számítógéppel van felszerelve. Ezeken a helyeken általában már alkalmaznak egy renszergazdát, aki megfelelően beállította a hálózatot.

Ha most azzal a feladattal kerülünk szembe, hogy a munkahelyi/iskolai gépünkön egy szervizt kell indítani, amelyet a világ más pontjáról is elérnek, akkor nem egyszerű a dolgunk. A gépünk “kívülről” nem fog látszódni. Már egy IP címet sem fogunk tudni mondani, amin keresztül a világ elérhet, a gépünk címe csak a lokális hálózaton értelmes.

Ha arra gondolunk, hogy a skype szerverek is tudnak üzenetet továbbítani számunkra, illetve az index.hu webszervere is megtalálja a gépünket a kért oldalak adataival, akkor az csalóka. Ezekben az esetekben ugyanis a mi gépünk kezdeményez kapcsolatot a külvilággal, és a külvilág egy erre az esetre kidolgozott trükkel talál vissza hozzánk. Hogy mi ez a trükk, fontos megérteni, hogy lássuk, mi az elve a relay szerviznek.

Amikor lekérünk egy web-oldalt, akkor a gépünk IP csomagokat kezd küldeni az oldalt tartalmazó számítógépnek (1). Ebben a csomagban szerepel a gépünk címe is (meg egy port szám), mint a csomag forrása, ide jöhetnek a válasz csomagok. Ezt a csomagküldést azonban legtöbb esetben nem tudja közvetlenül megtenni a gépünk. Amit a gépünk tud, hogy mi az az “átjáró”, amin keresztül a küldött csomag eljuttatható a kívánt helyre. (2)

Az átjáró a küldött csomagban átírja a gépünk lokális címét és a portot egy másikra, mégpedig a saját címére és egy addig szabad portjára. Ezen kívül megjegyzi ezt az átírást későbbre (State). Miért fontos megjegyezni?

Mert a célszámítógép a válaszokat most az átjárónak fogja visszaküldeni az átjáró által megadott portra (a célgép azt hiszi, ez a csomag forrása) (3). Amikor a válasz visszaérkezik az átjáróhoz, akkor az előbbi átírásnál feljegyzett adatokból az átjáró tudni fogja, hova kell a lokális hálózaton küldeni az csomagot. (4)

Klikk a képre a nagyobb változatért

Ha csak úgy beesik egy adat a külvilágból az átjáróhoz, akkor az nemigen fog a gépünkhöz odatalálni. Emiatt nehéz a dolgunk, ha a munkahelyi gépünkön nyilvános szervert akarunk üzemeltetni.

A megoldáshoz az egyik módszer, hogy megkérjük a rendszergazdát, konfigurálja úgy a hálózatot, hogy a gépünk kapjon egy kívülről is látható IP címet. Ezzel az a probléma, hogy ilyen esetekben általában a rendszergazda első válaszként infarktust kap, majd gólemként újraéledve leharapja a fejünket, és a légcsövünkbe vizel. Biztonsági/karbantarthatósági okokból nem szívesen nyitnak kívülről elérhető portokat a hálózaton.

Egy másik lehetőség az Azure AppFabric Service Bus Relay szolgáltatás használata. Az alapötlet az, hogy a gépünk felveszi a kapcsolatot az Azure relay szervizzel (1). Ekkor, mivel a gépünk kezdeményezte a kapcsolatot, a korábban említett átjáró vissza fogja engedni (és tudja hova kell irányítani) az adatokat a relay szerviztől, mivel azok válasz üzenetnek minősülnek. (2) Ezáltal egy kétirányú kommunikációs csatorna nyílik meg. Működni kezd továbbá egy kommunikációs végpont, amelyhez a külvilág csatlakozni tud. Ennek a végpontnak a címe jellegzetes, servicebus.windows.net végű. (3).

A működő végponthoz ekkor csatlakozhatnak kliensek (4), ahonnan a Relay Service a kéréseket a gépünknek továbbítja (5)

Klikk a képre a nagyobb változatért

Innentől kezdve a karbantartási munkák/biztonsági intézkedések az Azure fenntartójának a felelősége. Ez nem azt jelenti, hogy ez a megoldás teljesen kockázatmentes a céges/iskolai hálózat szempontjából, simán írhatunk olyan szervizt, ami a lokális SVN/TFS szervert kijátssza a külső hálózatra.

Nehéz relay szervizt használni?

Hogy a gyakorlatban is lássuk miről van szó, implementálunk egy szervizt, előbb Azure Relay szolgáltatás nélkül, majd azt áttesszük Azure Relay mögé.

A szerviz egyetlen dolgot tud majd, névreszóló tanácsot tud generálni. Az implementációnál nem foglalkozunk azzal, hogy a kód szép legyen, így a szervizosztályon lesz a kontrakt, és kódból lesz felkonfigurálva az egész, ezenkívül kódból host-olunk. Cserébe az eredmény kisebb lesz, és a vállalkozó kedvűek egy egyszerű copy-paste-tal kipróbálhatják a kódot. A kicsi szervizünk így a következőképpen néz ki:

using System;

using System.ServiceModel;
using System.ServiceModel.Web;
    
[ServiceContract]
class AdviceGenerator
{
    [WebGet(UriTemplate = "Advice/{name}")]
    string AdviceFor(string name)
    {
        return string.Format("Be good, {0}!", name);
    } // AdviceFor()
} // class AdviceGenerator

class Program
{
    static void Main()
    {
        var host = new WebServiceHost(
                        typeof(AdviceGenerator), 
                        new Uri("http://localhost:999/"));

        var binding = new WebHttpBinding();

        host.AddServiceEndpoint(
                typeof(AdviceGenerator), 
                binding, 
                string.Empty);

        host.Open();

        Console.WriteLine("Advice service is running.");
        Console.WriteLine("Press enter to stop.");
        Console.ReadLine();

        host.Close();
    } // Main
} // class Program

A programot elindítva, ki lehet próbálni, a következőhöz hasonló eredményt kapunk:

Klikk a képre a nagyobb változatért

Azure-osítás

A fenti szerver szépen működik, azonban a munkahelyi gépemen futtatva azt maximum a kollegáim tudják elérni. Itt jön hát el az Azure ideje, meg fogjuk látni, milyen szemtelenül könnyű mindenki számára elérhetővé tenni a szervizt. Ahhoz, hogy elinduljunk, szükség lesz egy Azure előfizetésre. Lehetőség van három hónapig ingyen kipróbálni, én is ennek segítségével írtam meg ezt a cikket.

Ahhoz, hogy a szerviz működjön Azure Relay szervizen keresztül, a Management Portal-on bizonyos beállításokat el kell végezni. Nem szeretném az ehhez szükséges kattintásokat végig screen shot-ozni, az alábbihoz hasonló eredményt kellene elérni:

Klikk a képre a nagyobb változatért

Első lépésként a bal oldali sávban alul a “Service Bus, Access Control & Caching” elemre kell kattintani, majd a bal felső sarokban a “new” ikonra. A feljövő ablakban megadunk egy namespace-t, ez majd megjelenik az URL-ünkben (nálam proctology), ezen kívül a “Service Bus”-t kell kipipálni, az alábbihoz hasonlóan:

Ha ez megvan, akkor pár sort át kell írni az eredeti szervizen, hogy az a Relay szervizt használja. Az első, hogy innentől más lesz a szerviz base address-sze:

var host = new WebServiceHost(
                typeof(AdviceGenerator),
                new Uri("http://proctology.servicebus.windows.net/"));

Ezt az információt a WCF mögötti mechanizmus a szerviz busznak továbbítja, innen tudja majd, hogy milyen url-en kell fogadni a bejövő kéréseket. Ahhoz, hogy a szervizünk relay módban működjön, egy erre szolgáló WCF binding-ot kell használni a WebHttpBinding helyett:

var binding = new WebHttpRelayBinding(
                    EndToEndWebHttpSecurityMode.None, 
                    RelayClientAuthenticationType.None);

Az első paraméter segítségével tudjuk beállítani, hogy a kliensek HTTP vagy HTTPS protokolon keresztül tudjanak kapcsolódni. A None flag a mezitlábas HTTP-t jelenti, az egyszerűség kedvéért most maradjunk ennél. Később ezt majd bekapcsoljuk.

A második paraméter a kapcsolódó kliensek authentikációjának módját állítja be. Lehetőség van rá beállítani, hogy a kliensnek egy Security Token-t kelljen bemutatni. Mi nem használjuk ki ezt a lehetőséget, hiszen a HTTPS – amit majd használni szeretnénk – remek kliens authentikációs lehetőséget rejt magában.

Ha a klienseknek nem is, a mi WCF szervizünknek authentikálni kell magát a szerviz busszal. Erre a legegyszerűbb módszer talán a “shared secret”, amihez szükséges információkat könnyen megszerezzük az alábbi gombra kattintva:

Ha meg van a közös titok, akkor azt egy TransportClientEndpointBehavior-on keresztül a végpontunkon be tudjuk állítani. A teljes kód a relay-elt szervizhez így a következőképpen alakul:

static void Main()
{
    var host = new WebServiceHost(
                    typeof(AdviceGenerator),
                    new Uri("http://proctology.servicebus.windows.net/"));

    var binding = new WebHttpRelayBinding(
                        EndToEndWebHttpSecurityMode.None, 
                        RelayClientAuthenticationType.None);

    var endpoint = host.AddServiceEndpoint(
                            typeof(AdviceGenerator),
                            binding,
                            string.Empty);

    var tokenProvider =        
            TokenProvider.CreateSharedSecretTokenProvider(
                "owner",
                "bsVEetD4FLkdnERfM7M1fglWcoJ6mkD0xNaHJDpnt+c=");

    var clientBehavior =
            new TransportClientEndpointBehavior(tokenProvider);

    endpoint.Behaviors.Add(clientBehavior);


    host.Open();

    Console.WriteLine("Advice service is running.");
    Console.WriteLine("Press enter to stop.");
    Console.ReadLine();

    host.Close();
} // Main

A titkot egyébként átírtam, szóval a fenti kód nem fog tudni bejelentkezni a proctology.servicebus.windows.net-hez. A szervizt most elindítva a elérhetővé válik a világ bármely pontjáról a http://proctology.servicebus.windows.net/ címen:

Klikk a képre a nagyobb változatért

Az alapfeladat tehát nagyon könnyen-kényelmesen megoldódott. Ez azonban csak egy egyszerűsített változata az eredeti igénynek. Eredetileg a szerviz HTTPS-en keresztül érhető el, és a kliens authnetikáció is a HTTPS-re épül.

Ahhoz, hogy folytatni tudjuk, egy kicsit mélyebben meg kell ismerni a HTTPS, illetve az alatta levő TLS protokol működését. Ezt bemutatom egy következő önálló cikkben, utána folytathatjuk a kísérletezést az Azure-ral.

  1. #1 by leventemihaly on 2012. March 29. - 13:33

    Szuper cikk, köszi. Várom a folytatást!🙂

  1. Szimmetrikus titkosító algoritmusok - pro C# tology - devPortal

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: