Redes de Computadores Trabalho Prático III DCC Deep Web 1 Introdução Neste trabalho iremos desenvolver uma plataforma de roteamento cebola.1 Estas plataformas permitem que clientes se conectem a servidores sem revelar sua identidade para os servidores e para os outros clientes na rede. Para isso, clientes criam uma tuneis de forma que vários clientes se interpõem entre a origem e o destino de cada pacote. Nossa plataforma irá permitir que vários clientes se conheçam, estabeleçam túneis para roteamento cebola, e comuniquem dados com um servidor remoto de forma (pseudo-)anônima.2 2 Protocolo e funcionamento As mensagens do DCC Deep Web possuem o seguinte formato de cabeçalho: 0 1 2 3 4 +-------+-------+-------+-------+ | CODE | TID | TTL | RSRVD | +-------+-------+-------+-------+ | DESTINATION IP | +-------------------------------+ | DEST PORT | LENGTH | +---------------+---------------+ | PAYLOAD | | ... | O protocolo do DCC Deep Web possui mensagens de quatro tipos distintos: (i) mensagens de entrada na rede e disseminação de dispositivos, (ii) mensagem para teste de presença na rede, (iii) mensagens para criação e fechamento de túneis, e (iv) mensagens para transmissão de dados em um túnel. 1 2 Um exemplo deste tipo de aplicação é o Tor. A comunicação não será totalmente segura pois não iremos criptografar os dados. 2.1 Entrada e disseminação de clientes Existem três mensagens para disseminação de informações sobre clientes que compõem a rede: peer-announce (1): Essa mensagem é a primeira enviada por um novo cliente quando ele entra no sistema. Ela é enviada a um cliente qualquer préviamente conhecido que já está no sistema. Os campos TID e TTL não são utilizados e devem ter o valor zero. O campo length deve ter o valor zero pois mensagens peer-announce não têm corpo, apenas cabeçalho. Os campos IP e port devem conter o IP e porta onde o novo cliente irá receber conexões do DCC Deep Web. Quando um cliente recebe uma mensagem peer-announce ele armazena o IP e porta recebidos na sua lista de clientes conhecidos. peer-request (2): Esta mensagem requisita a lista de clientes conhecidos. Os campos TID, TTL, IP e port não são utilizados e devem ter o valor zero. (O cliente realizando a requisição é identificado pelo soquete de rede onde a requisição foi recebida.) O campo length deve ter o valor zero pois mensagens peer-request não têm corpo, apenas cabeçalho. Um cliente que recebe uma mensagem peer-request deve responder ao requisitante enviando uma mensagem peer-list. peer-list (3): Esta mensagem é a resposta para mensagens peer-request. Os campos TID, TTL, IP e port não são utilizados e devem ter o valor zero. O campo length terá um valor igual a 6n bytes, onde n é o número de clientes conhecidos. Para cada cliente conhecido serão enviados 6 bytes contendo o endereço IP e a porta onde aquele cliente recebe conexões do DCC Deep Web; o mesmo IP e porta passados pelo cliente na mensagem peer-announce quando ele entrou na rede. Um cliente que recebe uma mensagem peer-list deve colocar todos IPs e portas recebidos na sua lista de clientes conhecidos. Quando um novo cliente entra na rede, ele primeiro envia uma requisição peer-announce a outro cliente que já entrou no sistema para anunciar sua presença. O novo cliente deve também pedir uma lista de outros clientes que estão na rede enviando uma requisição peer-request. O novo cliente pode enviar mensagens peer-announce e peer-request para todos os clientes em sua lista de clientes conhecidos. Durante sua permanência na rede, clientes devem enviar requisições peerannounce e peer-request periodicamente para anunciar sua presença na rede e descobrir a presença de outros clientes na rede. Quando novos clientes são descobertos na rede, conexões do DCC Deep Web devem ser estabelecidas com estes clientes. Cada cliente conhecido deve estar associado a um soquete de rede utilizado para fazer comunicação com aquele cliente. 2.2 Mensagens de teste de presença e comunicação O DCC Deep Web suporta duas mensagens de teste que funcionam de forma similar a mensagens de ping (echo request) e pong (echo reply) na Internet: peer-ping (4): Esta mensagem testa se um membro ainda está ativo. O teste pode ser realizado periodicamente ou sob demanda (e.g., antes de encaminhando uma mensagem tunnel-create), a cargo da implementação. O campo TID é utilizado para identificar a requisição e pode ter qualquer valor. Os campos TTL, IP e port não são utilizados e devem ter valor zero. O campo length deve ter o valor zero pois mensagens peer-ping não têm corpo, apenas cabeçalho. Um cliente que recebe uma mensagem peer-ping deve responder com uma mensagem peer-pong. peer-pong (5): Esta mensagem é enviada como resposta às mensagens peerping. A mensagem peer-pong é enviada apenas ao remetente da mensagem peer-ping. O campo TID da mensagem peer-pong deve ter o mesmo valor da mensagem peer-ping que responde. Os campos TTL, IP e port não são utilizados e devem ter valor zero. O campo length deve ter o valor zero pois mensagens peer-pong não têm corpo, apenas cabeçalho. 2.3 Mensagens para criação e fechamento de túneis Considere que os clientes participantes do DCC Deep Web sejam enumerados por C1 , C2 , . . . , Cn . A comunicação anônima é estabelecida através de túneis criados através dos seguintes passos: 1. Um cliente Ci envia uma requisição para um outro cliente Cj escolhido aleatoriamente para estabelecer um túnel. Esta requisição estabelece a comunicação entre Ci e Cj para o túnel. 2. Se Cj não for o último cliente no túnel, voltamos à etapa anterior fazendo i ← j para construir o resto do túnel. Se Cj for o último cliente no túnel, passamos para a etapa seguinte. 3. Cj , o último cliente no túnel, deve abrir uma conexão com o servidor indicado na requisição de criação do túnel e confirmar a criação do túnel para o nó anterior a ele no túnel. 4. Um cliente Ci , ao receber a confirmação de criação do túnel, repassa a confirmação para o nó anterior a ele no túnel. A confirmação irá percorrer todo o túnel até chegar ao cliente que originou a requisição de criação do túnel. 5. Após o recebimento da confirmação de criação do túnel, o cliente pode utilizar o túnel normalmente. 6. Quando o túnel não for mais necessário, o cliente que requisitou a criação do túnel irá enviar uma mensagem de fechamento do túnel, que irá percorrer todo o túnel até o último dispositivo no túnel. Durante o estabelecimento de um túnel (etapas 1–4), cada cliente deve preencher uma tabela de roteamento utilizada para rotear pacotes recebidos nos túneis. A tabela de roteamento dos túneis deve mapear (Cin, TIDin ) → (Cout , TIDout ). Cin e TIDin são o cliente e o TID de onde a requisição foi recebida. Cout e TIDout são o identificador do próximo cliente no túnel e o TID combinado com o próximo cliente. O cliente que requisitou a criação de um túnel usa valores especiais de Cin e TIDin para identificar que é o inı́cio do túnel. De forma similar, o último cliente no túnel usa valores especiais de Cout e TIDout para identificar que é o último cliente no túnel. De forma gráfica, a tabela deve conter as seguintes informações: +---------+---------+---------+---------+ | C in | TID in | C out | TID out | +---------+---------+---------+---------+ Os identificadores de túnel, TIDs, são transmitidos no campo TID no cabeçalho dos pacotes do DCC Deep Web. Os identificadores de cliente (Cin e Cout ) ficam a cargo da implementação; podem ser utilizados, e.g., o IP e porta do cliente ou seu soquete de rede. As etapas 1–4 acima são implementadas através das mensagens seguintes: tunnel-create (6): Esta mensagem envia uma requisição para criação de um túnel no DCC Deep Web. Quando um cliente deseja criar um novo túnel, ele inicia o processo de criação do túnel enviando uma requisição tunnel-create para um cliente conhecido escolhido aleatoriamente. O campo TID deve conter o identificador que será utilizado para comunicação entre o transmissor (Ci ) e o destinatário (Cj ) no túnel sendo criado. O campo TTL deve ser inicializado aleatoriamente com um valor entre 4 e 32. O campo IP e port devem conter o IP e a porta do servidor ao qual o último cliente no túnel irá se conectar. O campo length deve ter o valor zero pois mensagens tunnel-create não têm corpo, apenas cabeçalho. Quando um cliente recebe uma mensagem tunnel-create, ele verifica se o TTL tem valor zero. Se o TTL tiver valor zero, o cliente é o último cliente no túnel. O cliente deve estabelecer uma conexão com um servidor externo no IP e porta indicados nos campos IP e port da mensagem tunnel-create. Se a conexão com o servidor externo for estabelecida com sucesso, o cliente deve atualizar sua tabela de roteamento para redirecionar dados recebidos no túnel para o servidor e dados recebidos do servidor para o túnel. O cliente deve também confirmar a criação do túnel enviando uma mensagem tunnel-ok ao cliente anterior (i.e., o cliente do qual recebeu a mensagem tunnel-create). Quando um cliente recebe uma mensagem tunnel-create e o valor do campo TTL é maior do que zero, ele é um nó intermediário no túnel. O cliente deve decrementar o valor do campo TTL e escolher um conhecido aleatório para continuar a requisição de criação de túnel. A mensagem tunnel-create repassada deve: conter os mesmos valores para os campos IP, port e length da mensagem tunnel-create original; ter o valor do campo TTL decrementado; utilizar qualquer TID que o cliente tiver livre (o TID é local, não é global). Ao repassar pedidos de criação de túneis, clientes devem atualizar suas tabelas de roteamento. tunnel-ok (7): Esta mensagem é enviada na direção contrária das mensagens tunnel-create para confirmar que um túnel foi estabelecido com sucesso. Esta mensagem deve conter os mesmos valores nos campos TID, IP e port que a mensagem tunnel-create recebida. Estes campos são utilizados para identificar qual túnel foi estabelecido com sucesso. O campo TTL não é utilizado e deve ter o valor zero. O campo length deve ter o valor zero pois mensagens tunnel-create não têm corpo, apenas cabeçalho. Um cliente que recebe uma mensagem tunnel-ok, deve repassar a mensagem ao cliente anterior no túnel. Após receber a mensagem tunnel-ok, o cliente que originou a criação do túnel pode começar a utilizá-lo usando as mensagens descritas na seção 2.4. Se um túnel não for confirmado com mensagens tunnel-ok dentro de 60 segundos, sua criação deve ser abortada; os recursos reservados ao túnel devem ser liberados, mas não é preciso enviar nenhuma mensagem. Quando um túnel não é mais necessário, o cliente deve terminá-lo enviando a seguinte mensagem: tunnel-destroy (8): Esta mensagem fecha um túnel. O campo TID deve conter o identificador do túnel; os campos IP e port devem conter o IP e porta do servidor externo utilizados quando da criação do túnel (nas mensagens tunnel-create). O campo TTL não é utilizado e deve ter valor zero. O campo length deve ter o valor zero pois mensagens tunnel-create não têm corpo, apenas cabeçalho. Ao receber uma mensagem tunnel-destroy, o cliente deve liberar todos os recursos associados ao túnel (entradas na tabela de roteamento, TIDs, soquetes com servidores externos). Caso o cliente não seja o último cliente no túnel, ele deve atualizar o valor do campo TID e repassar a mensagem tunnel-destroy ao próximo cliente no túnel. 2.4 Transmissão de dados A transmissão de dados em túneis é realizada pelas seguintes mensagens: tunnel-data (9): Esta mensagem carrega dados que devem ser encaminhados em um túnel. O campos TID deve conter o identificador de um túnel préviamente criado através das mensagens tunnel-create e tunnel-ok. Os campos TTL, IP e port não são utilizados e devem ter valor zero. O campo length deve conter o tamanho do payload (em bytes). Ao receber uma mensagem tunnel-data um dispositivo deve repassar a mensagem à outra ponta do túnel. O cliente que originou o túnel repassa dados recebidos da aplicação para o túnel e os dados recebidos do túnel para a aplicação. O último cliente no túnel, que está conectado ao servidor externo, repassa dados recebidos do túnel para o servidor externo e repassa os dados recebidos do servidor externo no túnel. 3 Implementação e avaliação Este trabalho deve ser realizado em grupo de até quatro alunos. Os grupos deverão implementar o protocolo descrito acima e formar uma rede de roteamento cebola. Seu cliente deve interoperar com outros clientes (teste com clientes dos colegas), inclusive com o cliente de referência a ser implementado pelo professor. O professor irá executar um cliente do DCC Deep Web no computador george.dcc.ufmg.br na porta 80. O cliente pode ser implementado em Python, C, C++ ou Java, mas deve interoperar com clientes escritos em outras linguagens. A avaliação do código será feita criando uma rede do DCC Deep Web com clientes de cada grupo e clientes implementados pelo professor. Cada grupo deverá entregar documentação em PDF de até 4 páginas (duas folhas), sem capa, utilizando fonte tamanho 10, e figuras de tamanho adequado ao tamanho da fonte. A documentação deve discutir desafios, dificuldades e imprevistos de projeto, bem como as soluções adotadas para os problemas. 4 Extras Verificação de clientes entrando no sistema. Um cliente que já está no sistema pode verificar, ao receber uma mensagem peer-announce, se a mensagem está sendo recebida num soquete de rede usando o IP e porta contidos na mensagem peer-announce. Esta verificação evita que um cliente envie informações falsas ou incorretas.