2. Arquitetura

2.1 Funcionamento

 

A Freenet sofreu uma mudança drástica em 2008, com o lançamento da versão 0.7. Até então, a Freenet operava em um modo que oferecia uma forte segurança para os seus usuários, mas que ainda não utilizava todo o potencial tecnológico para prover uma privacidade completa. Este modo é atualmente chamado de Opennet, e o criado para melhorar as questões de privacidade e segurança é chamado de Darknet. Atualmente a Freenet permite que o usuário trafregue na rede utilizando qualquer um dos dois modos.

O sistema é feito a partir da criação de uma rede onde os usuários estabelecem conexões entre si para transmitir informações pela rede. Um usuário não tem conexão com a rede inteira, mas sim apenas com alguns outros usuários, e através de mecanismos de roteamento ele consegue transmitir e buscar dados na rede inteira.

Cada usuário (também chamado de nó) recebe um identificador especial ao ser inserido na rede, que é um valor circular entre 0 e 1 (portanto 0 e 1 correspondem ao mesmo identificador). O mapa da rede é então dado através de um círculo onde os usuários são alocados em seu perímetro. Dessa forma, a distância máxima entre dois usuários é de 0.5.

Modelo simplificado da rede com 5 nós

Modelo simplificado da rede com 6 nós.

2.1.1 Opennet

 

A Opennet, também chamada de “P2P” ou “Peer-to-Peer”, é o modus operandi onde o usuário é inserido em um “local” aleatório na rede, estando diretamente conectado com vizinhos desconhecidos, porém que nada podem saber sobre a sua identidade a priori. Embora todos os mecanismos de segurança e eficiência continuem funcionando perfeitamente no modo P2P, existem algumas questões que tornam ele menos seguro que o modo Darknet.

A questão de principal importância é a do caso onde os usuários com quem você está conectado verificam e analisam as mensagens encaminhadas para a rede através deles, de origem sua. Mesmo que seja uma tarefa difícil devido aos protocolos utilizados para criptografia, é possível que o usuário vizinho possa vir a descobrir que tipo de informações e dados você requisita e envia.

2.1.2 Darknet

 

Já a Darknet é conhecida como “F2F” ou “Friend-to-Friend”. Os mecanismos e protocos são iguais aos do modo P2P, porém com a diferença que o usuário é inserido na rede sem conexão nenhuma com outros usuários, estando completamente desconectado da rede em si.

Neste caso, o usuário tem a opção de adicionar vizinhos novos através de identificadores privados. A idéia principal do modo P2P é que o usuário apenas se conecte com pessoas que ele confie e conheça pessoalmente, garantindo uma rede onde, idealmente, nenhum vizinho tenha intenções maliciosas de monitorar o tráfego de informações dos usuários próximos

2.2 Roteamento

 

O método de roteamento e da construção da rede veio de uma idéia chamada “Six Deegres of Separation” (Seis Graus de Separação) de que duas pessoas na Terra estão á uma distância de seis pulos uma da outra, em termos de uma cadeia de amigos. Esse fenômeno foi amplamente estudado em redes sociais e na sociedade humana, resultando em conclusões de que uma rede muito grande pode ser razoavelmente conexa a partir de poucas ligações entre usuários.

2.2.1 – O Modelo Small-World

 

A partir da idéia dos Seis Graus de Sepração, o pesquisador Jon Kleinberg criou um modelo chamado de Small-World, tentando aplicar a idéia de interconectar uma rede grande utilizando poucas conexões entre usuários. Com isso, um único usuário não poderia obter informações sobre a rede como um todo, mas sim apenas sobre os seus vizinhos imediatos.

Esta idéia foi utilizada como um dos fundamentos para a criação da Freenet pois ela concilia a privacidade e a escalabilidade da rede, impossibilitando que um usuário possa se conectar livremente com outros nós da rede, e mantendo uma velocidade aceitável de comunicação através de nós distantes.

Modelo mundo pequeno

Visão da rede do ponto de vista do usuário A.

2.2.2 Redes DHT

 

A Freenet também tomou como base o modelo de redes DHT (Distributed Hash Tables), cujas implementações incluem a rede eDonkey e o sistema BitTorrent. As DHT são estruturas que permitem uma busca eficiente de dados em uma rede P2P através da posse por parte de cada nó de uma tabela contendo pares chave-valor, responsáveis por direcionar pedidos de dados para outros nós.

O mecanismo de redes baseadas em estruturas DHT é basicamente fundamentado através da busca da função hash aplicada em cima do dado a ser procurado. Caso um usuário queira buscar por um dado “FooBar2012”, este aplica uma função hash (normalmente SHA-1) em cima do dado a ser busaco, e envia a chave resultante em uma mensagem de pedido para um nó vizinho. Este vizinho, por sua vez, verifica o hash requisitado e, a partir de uma checagem na sua própria tabela, encaminha a requisição para o vizinho indicado.

Essas tabelas são feitas para que o roteamento ocorra com o menor número de pulos possíveis entre nós, mas sem dar informações sobre a rede inteira para os seus usuários. Normalmente as DHT são aplicadas em algoritmos ambiciosos (greedy) e que envolvem skiplists.

Um dos grandes problemas de redes DHT é o fato delas partirem do pressuposto de que um nó poderá sempre se conectar à um outro nó, ignorando casos onde uma conexão não pode ocorrer devido à firewalls ou NATs. Por isso, a Freenet adotou um sistema similar à DHTs, porém diferente em alguns aspectos. Foi devido à este sistema que a idéia de um identificador especial para cada usuário tornou-se necessária.

2.3 Armazenamento

 

O armazenamento dos dados inseridos na rede são realizados nos próprios nós: ao integrar-se na rede Freenet, o usuário deve oferecer um mínimo de 512MB de espaço no seu disco rídigo para armazenamento de dados em geral. Esse sistema é responsável pela característica distribuída e descentralizada da rede, no escopo de dados.

Esse espaço é então dividido em duas partições: a Short-Term Storage Cache e a Belonging Storage Cache. Ambas partições possuem procedimentos de limpeza frequentes que excluem dados de maneira aleatória.

O sistema de armazenamento da Freenet tem dois objetivos: primeiramente, ele deve ser criado de forma à favorecer a prevalência e redundância de dados populares na rede, e finalmente ele deve ser dado de forma à otimizar o sistema de routing para a busca de dados.

Tabela que indica a relação entre a frequência de dados duplicados na rede com a quantidade de nós.

2.3.1 Short-Term Storage Cache

 

A Freenet foi criada de forma que é impossível que um dado seja excluido por um usuário. O motivo disso é que, desta maneira, não existe métodos de criar censuras ou controle de conteúdo dentro da rede. Esse sistema necessitou que dados mais requisitados tenham um privilégio em termos de prevalência na rede, para que então os dados pouco requisitados eventualmente sejam excluídos pela limpeza aleatória que ocorre em cada cache.

O Short-Term Storage Cache foi criado exatamente para que esse sistema funcione. Qualquer dado que passa pelo nó é armazenado no seu Short-Term Cache logo em seguida, portanto caso o nó B tenha recebido uma requisição do seu vizinho A, encaminhado ao seu vizinho C, o qual retornou o dado requisitado, então o nó B automaticamente armazenará o dado requisitado por A neste seu cache ao repassar ele de volta ao nó requisitor.

Exemplo inserção

Exemplo de inserção de dado no Short-Term Storage Cache.

2.3.2 Belonging Storage Cache

 

Para contornar o problema de roteamento das redes DHT, foi criado um método diferente para a busca e inserção de dados que tinha como base um número identificador entre 0 e 1. Cada usuário possui um número identificador próprio, que define o seu “lugar” no mapa circular da rede Freenet. Paralelamente, cada dado também possui um identificador especial que depende das tags que o definem, como “politics, philosophy, programming”.

O sistema adotado foi o de criar o Belonging Storage Cache, que tem a função de armazenar dados cujo número identificador seja próximo ao do nó em questão. Portanto, se um usuário possui um número identificador que corresponde à tags “programming, lisp”, o seu Belonging Cache tenderá a armazenar majoritariamente dados que tenham conteúdo ligado à programção em LISP, ou seja, dados similares.

Essa partição possibilita o que chamam de sinkstores, que são clusters de nós que possuem dados similares. Isso é possível pois nós vizinhos (ligados) costumam estar próximos no mapa de redes, ou seja, têm um número identificador parecido.

Para a inserção de arquivos no Belonging Storage Cache é utilizado um algoritmo onde um nó envia um dado para o seu vizinho armazenar caso o vizinho seja mais semelhante ao dado do que ele.

Exemplo de sinkstores

2.4 Criptografia

 

A rede Freenet utiliza 3 tipos de chaves criptográficas compostas para representar dados fixos, freesites e outros objetos da rede. O uso destas chaves é compulsório pois através de mecanismos como busca por hash, o usuário tem a garantia de que o arquivo recebido é exatamente igual ao arquivo que ele requisitou através de uma comparação de hashs de cada um. Além disso, é necessário que cada tipo de dado seja devidamente criptografado para que a pessoa que o armazena não seja responsável pelo tipo de conteúdo do dado.

A chave mais básica utilizada na rede é chamada de CHK, ou Content Hash Keys. Ela é dada pelo formato "CHK@filehash,decrypkey,cryptosettings" e representa dados fixos de até 32kB. O elemento "filehash" contém o hash do arquivo em questão, que é utilizado tanto como parâmetro principal para a busca quanto para checar se o arquivo recebido não foi alterado durante a transferência entre nós. O elemento "decrypkey" é uma chave simétrica utilizada para decriptar o dado quando ele for recebido, e finalmente "cryptosettings" é utilizado para informar que tipo de criptografia foi utilizada durante a encriptação do arquivo.

Outra chave crucial para o sistema Freenet é a SSK, ou Signed Subspace Keys, que é utilizada para representar freesites de até 1kB. A principal novidade em relação a CHK é que a SSK possibilita que o dado seja atualizado, portanto é ideal para a representação de freesites e microblogs. O seu formato é "SSK@pubkeyhash,decrypkey,cryptosettings" e ela é composta por um par de chaves assimétricas e uma chave simétrica. O elemento "pubkeyhash" é o hash da chave pública que é utilizada como endereço do freesite, portanto é utilizado para realizar a busca em si. Os elementos "decrypkey" e "cryptosettings" possuem o mesmo uso do da chave CHK. A chave privada do par assimétrico é utilizado pelo criador do freesite para realizar alterações, possibilitando que o conteúdo seja atualizável.

Finalmente, temos a KSK, ou Keyword Signed Keys, que são chaves pouco seguras e vulneráveis a ataques de dicionário. O seu formato é "SSK@nome.txt" (por exemplo), e ela é composta apenas por um string, que representa o nome do arquivo em questão. Não existe também controle de colisão, portanto podem existir inúmeros arquivos representados pela mesma SSK, e não existe maneira de determinar a priori qual arquivo será retornado no caso de uma requisição.

2.5 Protocolos e Algoritmos

 

Como dito anteriormente, o Freenet funciona de acordo com o modelo Small World, o que implica que cada nó tem conhecimento apenas dos seus nós vizinhos. Portanto, uma request de busca ou de inserção é enviada a um nó vizinho ao nó que a gerou e, em seguida, repassado para um próximo nó vizinho, se este possuir um hash com valor mais parecido com o da request. A esse caminho percorrido é dado o nome de routing table e ele é de extrema importância, pois o resultado da request (sucesso ou falha) o percorrerá de volta até o nó de origem.

Para que routing table não fique muito grande, existe um número definido pelo usuário ao realizar uma request chamado HTL (Hops-to-live) que especifica o número máximo de “pulos” que a request dará entre um nó e outro. Entretanto, existem formas de proteção do próprio sistema que alteram o HTL sem o consentimento do usuário (mais informações na (Seção 5.2).

Os nós são chamados nós inteligentes por guardarem informações sobre as requests mais recentes e, a partir disso, decidirem para qual nó devem repassar de forma que maximize a possibilidade de sucesso. Esse mecanismo viabiliza que na maioria das buscas e inserções ocorra o melhor caso, ou seja, uma request retorne sucesso com o menor número de “pulos” possível, ao invés do pior caso, em que o HTL chega a zero sem retornar sucesso.

O que caracteriza um sucesso ou uma falha varia entre os casos de busca e inserção, e será explicado nas seções seguintes.

Existe também um número pseudo-aleatório denominado identificador, gerado com cada request. Esse número serve para os nós identificarem se determinada request já foi analisada ou não, sem que precise comparar o hash.

Antes de enviar uma request para outro nó é necessário o chamado handshake, que consiste em saber se esse nó está disponível (online) ou não (offline).

2.5.1 Busca

 

Para buscar um arquivo o usuário digita os parâmetros de busca, especifica o tipo de chave que será usada (CSK, SSK, KSK ou USK) e determina o HTL. Essas informações são encriptadas de acordo com a chave escolhida, gerando um hash ao qual será atribuído um identificador. Em seguida, esse hash é enviado para o próprio nó, com o objetivo de checar se o mesmo já não possui o arquivo procurado.

Na busca, uma falha ocorre se nenhum arquivo com um hash suficientemente similar for encontrado ou se o HTL chegar a zero.

Request = Falha

Por outro lado, o sucesso é atingido se a busca encontrar um arquivo similar ou igual antes que o HTL se esgote. Como os nós inteligentes, ou seja, possuem conhecimentos sobre seus vizinhos, caso um nó A receba uma request com um HTL muito baixo sobre um arquivo F que ele não possui, mas sabe de um nó próximo que o tenha, ele irá mandar uma mensagem (Reply.Restart) de volta para o nó de origem requisitando o aumento do HTL.

Request = Sucesso

2.5.2 Inserção

 

O início do procedimento de inserção é similar ao de busca. Antes de acontecer a inserção de fato, ocorre um pedido de inserção.


Insert = Sucesso

Obs: Reply.Restart pode ser usado da mesma forma.

Há falha se o arquivo for encontrado em algum nó da routing table.

Insert = Falha

A imagem a seguir mostra os vários campos transmitidos dentro de cada tipo de mensagem.

Inserção

Note que a identidade do nó que iniciou a request não está contida em nenhum tipo de mensagem. Portanto, mesmo que um nó A tenha recebido uma request diretamente de seu criador B, ele nunca saberá se B é ou não quem a gerou, mantendo o anonimato.

 

próximo