
Tunelar dados IPv4 através de servidores DNS para contornar restrições de firewall e fornecer acesso de rede encoberto para testes de penetração.
Este é um software que permite tunelar dados IPv4 através de um servidor DNS. Isso pode ser útil em diferentes situações em que o acesso à internet é bloqueado por firewall, mas consultas DNS são permitidas.
O Iodine não possui script de configure. Há dois recursos opcionais para Linux
(suporte a SELinux e systemd) que serão habilitados automaticamente se os
arquivos de cabeçalho relevantes forem encontrados em /usr/include.
(Veja o script em ./src/osflags)
Execute make para compilar os binários do servidor e do cliente.
Execute make install para copiar os binários e a página de manual para o diretório de destino.
Execute make test para compilar e executar os testes de unidade. (Requer a biblioteca check)
Experimente dentro da sua própria rede local! Siga estes passos simples:
./iodined -f 10.0.0.1 test.com.
Se você já usa a rede 10.0.0.0, use outra rede interna como
172.16.0.0../iodine -f -r 192.168.0.1 test.com.
Substitua 192.168.0.1 pelo endereço IP do seu servidor.10.0.0.2 e o servidor tem 10.0.0.1.Para usá-lo de fato através de um servidor de nomes intermediário, veja abaixo.
Nota: servidor e cliente precisam falar exatamente o mesmo protocolo. Na maioria dos casos, isso significa executar a mesma versão do iodine. Infelizmente, implementar compatibilidade de protocolo retroativa e futura geralmente não é viável.
Para usar este túnel, você precisa ter controle sobre um domínio real (como mydomain.com)
e um servidor com endereço IP público para executar o iodined. Se esse servidor
já executa um programa DNS, altere a porta de escuta e use a opção -b do iodined
para permitir que ele encaminhe as consultas DNS. (Observe que este procedimento
não é recomendado em ambientes de produção, pois o encaminhamento DNS do iodined
não é completamente transparente, por exemplo, transferências de zona não funcionarão.)
Alternativamente, você pode encaminhar o subdomínio do seu servidor DNS para o iodined,
que deve então ser executado em uma porta diferente (-p).
Em seguida, delegue um subdomínio (digamos, t1.mydomain.com) ao servidor iodined.
Se você usa BIND para o seu domínio, adicione duas linhas como estas ao arquivo de zona:
t1 IN NS t1ns.mydomain.com. ; note the dot!
t1ns IN A 10.15.213.99
A linha NS é tudo o que é necessário para rotear consultas do subdomínio t1
para o servidor t1ns. Usamos um nome curto para o subdomínio, para manter o máximo
de espaço possível disponível para o tráfego de dados. No final da linha NS
está o nome do seu servidor iodined. Esse nome pode ser qualquer nome, apontando para qualquer lugar,
mas neste caso é facilmente mantido no mesmo arquivo de zona. Deve ser um nome
(não um endereço IP), e esse nome deve ter um registro A
(não um CNAME).
Se o seu servidor iodined tiver IP dinâmico, use um provedor de DNS dinâmico. Simplesmente
aponte a linha NS para ele e omita a linha A:
t1 IN NS myname.mydyndnsprovider.com. ; note the dot!
Em seguida, recarregue ou reinicie o seu programa de servidor de nomes. Agora, quaisquer consultas
DNS para domínios que terminam em t1.mydomain.com serão enviadas ao seu servidor iodined.
Por fim, inicie o iodined no seu servidor. O primeiro argumento é o endereço IP
dentro do túnel, que pode ser de qualquer faixa que você ainda não use (por
exemplo, 192.168.99.1), e o segundo argumento é o domínio designado (neste
caso, t1.mydomain.com). Usar a opção -f mantém o iodined em execução em
primeiro plano, o que ajuda durante os testes. O iodined abrirá uma interface virtual
("dispositivo tun") e também começará a escutar consultas DNS na porta UDP 53.
Digite uma senha na linha de comando (-P senha) ou após o servidor iniciar.
Agora está tudo pronto para o cliente.
Se houver chance de você usar um túnel iodine a partir de ambientes inesperados,
inicie o iodined com a opção -c.
Linha de comando resultante nesta situação de exemplo:
./iodined -f -c -P secretpassword 192.168.99.1 t1.mydomain.com
Toda a configuração está pronta, basta iniciar o iodine. Ele aceita um ou dois argumentos: o
primeiro é o servidor DNS intermediário local (opcional) e o segundo é o domínio
que você usou (t1.mydomain.com). Se você não especificar o primeiro argumento, a
configuração DNS atual do sistema será consultada.
Se consultas DNS são permitidas para qualquer computador, você pode passar diretamente o
endereço do servidor iodined como primeiro argumento (no exemplo: t1ns.mydomain.com ou
10.15.213.99). Nesse caso, também pode acontecer que qualquer tráfego seja permitido
para a porta DNS (53 UDP) de qualquer computador. O iodine detectará isso e mudará
para tunelamento UDP bruto se possível. Para forçar o tunelamento DNS em qualquer caso, use a
opção -r (especialmente útil ao testar dentro da sua própria rede).
A interface de túnel do cliente receberá um IP próximo ao do servidor (neste
caso, 192.168.99.2 ou .3, etc.) e uma MTU adequada. Digite a mesma senha
do servidor, seja como opção de linha de comando ou após o cliente iniciar.
Usar a opção -f mantém o cliente iodine em execução em primeiro plano.
Linha de comando resultante nesta situação de exemplo; adicionar -r força o tunelamento DNS
mesmo que o tunelamento UDP bruto fosse possível:
./iodine -f -P secretpassword t1.mydomain.com
De qualquer um dos lados, agora você deve conseguir dar ping no endereço IP da outra
extremidade do túnel. Neste caso, ping 192.168.99.1 a partir do cliente iodine, e
192.168.99.2 a partir do servidor iodine.
Os dados dentro do túnel são apenas IPv4.
Por padrão, o servidor escuta em IPv4 e IPv6 para solicitações de entrada.
Use as opções -4 ou -6 para escutar apenas em um protocolo. O modo bruto será
tentado no mesmo protocolo usado para o login.
O cliente pode usar servidores de nomes IPv4 ou IPv6 para se conectar ao iodined. Os servidores
de nomes intermediários traduzirão entre protocolos automaticamente, se necessário. Use
as opções -4 ou -6 para forçar o cliente a usar uma versão IP específica para suas consultas
DNS.
Se o seu servidor estiver escutando em IPv6 e for acessível, adicione um registro AAAA para ele na sua configuração DNS. Estendendo o exemplo acima, ficaria assim:
t1 IN NS t1ns.mydomain.com. ; note the dot!
t1ns IN A 10.15.213.99
t1ns IN AAAA 2001:db8::1001:99
É possível rotear todo o tráfego através do túnel DNS. Para fazer isso, primeiro adicione uma rota de host para o servidor de nomes usado pelo iodine pela interface com fio/sem fio, usando o gateway padrão como gateway. Em seguida, substitua o gateway padrão pelo endereço IP do servidor iodined dentro do túnel DNS e configure o servidor para fazer NAT.
No entanto, observe que o tráfego de dados tunelado não é criptografado de forma alguma e pode ser lido e alterado por terceiros com relativa facilidade. Para máxima segurança, execute uma VPN através do túnel DNS (= tunelamento duplo) ou use acesso via shell seguro (SSH), possivelmente com encaminhamento de porta. Este último também pode ser usado para navegação web, quando você executa um proxy web (por exemplo, Privoxy) no seu servidor.
O servidor iodined responde a solicitações NS enviadas para subdomínios do domínio
do túnel. Se o seu subdomínio iodined for t1.mydomain.com, envie uma solicitação NS para
foo123.t1.mydomain.com para ver se a delegação funciona.
dig é uma boa ferramenta para isso:
% dig -t NS foo123.t1.mydomain.com
ns.io.citronna.de.
Além disso, o servidor iodined responderá a solicitações que começam com 'z' para qualquer um dos tipos de solicitação suportados, por exemplo:
dig -t TXT z456.t1.mydomain.com
dig -t SRV z456.t1.mydomain.com
dig -t CNAME z456.t1.mydomain.com
A resposta deve parecer texto embaralhado em todos esses casos.
No Mac OS X 10.6 e posterior, o iodine suporta os dispositivos utun nativos integrados ao
sistema operacional - use -d utunX.
O tamanho do fragmento de resposta DNS é normalmente detectado automaticamente para obter a largura de banda máxima.
Para forçar um valor específico (e acelerar as coisas), use a opção -m.
Os nomes de host DNS são normalmente usados até seu comprimento máximo, 255 caracteres.
Descobriu-se que alguns relays DNS respondem a consultas de comprimento total de forma bastante
não confiável, dando resultados muito variados (e na maioria das vezes muito ruins) na
detecção automática do tamanho do fragmento em tentativas repetidas. Nesses casos, use a opção -M
para reduzir o comprimento do nome de host DNS para, por exemplo, 200 caracteres, o que torna
esses relays DNS muito mais estáveis. Isso também é útil em alguns relays DNS
"desotimizadores" que preenchem a resposta com duas cópias completas da consulta, deixando
muito pouco espaço para dados downstream (e também não suportam EDNS0). A opção -M
pode trocar alguma largura de banda upstream por largura de banda downstream. Observe que
o valor mínimo de -M é cerca de 100, pois o protocolo pode dividir pacotes (máx. 1200
bytes) em apenas 16 fragmentos, exigindo pelo menos 75 bytes reais de dados por
fragmento.
Os dados upstream são enviados compactados com gzip e codificados em Base32; ou Base64 se o servidor
de relay suportar letras maiúsculas/minúsculas e + em nomes de domínio; ou Base64u se _ for
suportado em vez disso; ou Base128 se caracteres de byte alto forem suportados.
Essa codificação upstream é autodetectada. O protocolo DNS permite uma consulta por
pacote, e uma consulta pode ter no máximo 256 caracteres. Cada parte do nome de domínio pode ter no
máximo 63 caracteres. Portanto, seu nome de domínio e subdomínio devem ser o mais curtos possível
para permitir a máxima vazão upstream.
Vários tipos de solicitação DNS são suportados, sendo que os tipos NULL e PRIVATE
devem fornecer a maior largura de banda downstream. O tipo PRIVATE usa o
valor 65399 na faixa de uso privado. Outros tipos disponíveis são TXT, SRV,
MX, CNAME e A (retornando CNAME), em ordem decrescente de largura de banda.
Normalmente, o "melhor" tipo de solicitação é autodetectado e usado. No entanto, relays DNS
podem impor limites, por exemplo, em NULL e TXT, tornando SRV ou MX a melhor escolha.
Isso não é autodetectado, mas pode ser forçado usando a opção -T.
É aconselhável tentar várias alternativas, especialmente quando o tipo de solicitação
autodetectado fornece um tamanho de fragmento downstream inferior a 200 bytes.
Observe que consultas SRV, MX e A (retornando CNAME) podem ou irão causar
consultas adicionais por servidores de nomes com cache "inteligente" para obter um endereço IP real,
o que pode atrasar ou falhar completamente.
Respostas DNS para consultas que não são NULL/PRIVATE podem ser codificadas com o mesmo conjunto de
codecs dos dados upstream. Isso também é normalmente autodetectado, mas não são feitos testes
totalmente exaustivos, então alguns problemas podem não ser notados ao selecionar
codecs mais avançados. Nesse caso, você verá falhas/corrupção na
detecção automática do tamanho do fragmento. Em particular, descobriu-se que vários relays DNS
convertem respostas que retornam nomes de host (SRV, MX, CNAME, A) para minúsculas apenas
quando esse nome de host excede aprox. 180 caracteres. Nesses casos e similares, use
a opção -O para tentar outros codecs downstream; Base32 deve funcionar sempre.
A operação normal agora é o servidor não responder a uma solicitação DNS até que a
próxima solicitação DNS chegue, também conhecido como ser "preguiçoso". Dessa forma, o servidor
sempre terá uma solicitação DNS à mão quando novos dados downstream precisarem ser enviados.
Isso melhora muito o desempenho (interativo) e a latência, e permite reduzir
as solicitações de ping em repouso para intervalos de 4 segundos por padrão, e possivelmente
muito mais lentos. Na verdade, o principal propósito dos pings agora é forçar
uma resposta ao ping anterior e evitar timeouts do servidor DNS (geralmente de
pelo menos 5 a 10 segundos, conforme RFC1035). Alguns servidores DNS são mais impacientes e
darão erros SERVFAIL (timeouts) em períodos sem tráfego de dados tunelado. Todos
os dados ainda devem passar nesses casos, mas o iodine reduzirá o intervalo de ping
para 1 segundo mesmo assim (-I1) para reduzir o número de mensagens de erro. Isso
pode não ajudar para relays DNS muito impacientes como dnsadvantage.com (ultradns),
que dão timeout em 1 segundo ou até menos. Ainda assim, os dados passarão, e
você pode ignorar os erros SERVFAIL.
Se você estiver executando em uma rede local sem nenhum servidor DNS no meio,
tente -I 50 (iodine e iodined fecham a conexão após 60 segundos de silêncio).
A única vez em que você notará uma desaceleração é quando pacotes de resposta DNS se perderem;
o servidor iodined então precisa esperar um novo ping para reenviar os dados. Você pode
acelerar isso gerando algum tráfego upstream (tecla pressionada, ping). Se isso
acontecer com frequência, verifique sua rede em busca de gargalos e/ou execute com -I1.
A resposta atrasada no modo preguiçoso fará com que alguns relays DNS comerciais
"carrier grade" reenviem repetidamente a mesma consulta DNS ao servidor iodined.
Se o relay DNS for implementado como um pool de servidores paralelos,
solicitações duplicadas podem até chegar de múltiplas fontes. Esse efeito
só será visível no tráfego de rede no servidor iodined e não
afetará a conexão do cliente. O Iodined notará esses duplicados e enviará
a mesma resposta (quando chegar a hora) tanto para a consulta original quanto para o
duplicado mais recente. Depois disso, a resposta completa é armazenada em cache por um curto período.
Duplicados atrasados que chegam ao servidor ainda mais tarde recebem uma resposta que o
cliente iodine ignorará (se ela alguma vez chegar lá).
Se você tiver problemas, tente inspecionar o tráfego com ferramentas de monitoramento de rede
como tcpdump ou ethereal/wireshark, e certifique-se de que o servidor DNS intermediário
não tenha armazenado a resposta em cache. Uma mensagem de erro em cache pode significar que você
iniciou o cliente antes do servidor. A opção -D (e -DD) no servidor
também pode mostrar consultas recebidas e enviadas.
Se a sua porta 53 estiver ocupada em uma interface específica por um aplicativo que
não a usa, use -p no iodined para especificar uma porta alternativa (como -p 5353)
e use, por exemplo, iptables (no Linux) para encaminhar o tráfego:
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to :5353
(Enviado por Tom Schouten)
O Iodined rejeitará dados de clientes que não estiveram ativos (dados/pings) por mais de 60 segundos. Da mesma forma, o iodine será encerrado quando nenhum dado downstream for recebido por 60 segundos. Em caso de uma queda de rede prolongada ou similar, basta reiniciar o iodine (refazer login), possivelmente várias vezes até recuperar seu endereço IP antigo. Depois disso, espere um pouco, e você eventualmente verá o tráfego TCP tunelado continuar fluindo de onde parou antes da queda.
Com a introdução da fila de pacotes downstream no servidor, seu uso de memória aumentou em vários megabytes na configuração padrão. Para uso em ambientes com pouca memória (por exemplo, executando no seu roteador DSL), você pode diminuir USERS e remover a definição de OUTPACKETQ_LEN em user.h sem consequências negativas, assumindo que no máximo um cliente estará conectado por vez. Um DNSCACHE_LEN pequeno ainda é recomendado, preferencialmente 2 ou mais; no entanto, você também pode remover sua definição para economizar mais alguns kilobytes.
Um único servidor iodine pode lidar com vários domínios. Configure diferentes registros NS
no mesmo domínio, todos apontando para o mesmo host, e use um curinga
no início do argumento de domínio de topo (exemplo *.mydomain.com). O iodine
aceitará tráfego de túnel para todos os domínios que correspondam a esse padrão. O curinga
deve estar no início do argumento de domínio de topo e ser seguido por um ponto.
Esta seção tabula algumas medições de desempenho. Para visualizar corretamente, use uma fonte de largura fixa como Courier.
As medições foram feitas no protocolo 00000502 em modo preguiçoso; codificação upstream
sempre Base128; iodine -M255; iodined -m1130. As condições de rede não eram
extremamente favoráveis; os resultados não são benchmarks, mas uma indicação realista do
desempenho no mundo real que pode ser esperado em situações semelhantes.
A vazão upstream/downstream foi medida copiando com scp um arquivo previamente
lido de /dev/urandom (ou seja, incompressível) e medindo o tamanho com
ls -l ; sleep 30 ; ls -l em uma conexão separada sem túnel. Dado o
grande tamanho de bloco do scp de 16 kB, isso dá uma resolução de 4,3 kbit/s, o que
explica por que alguns valores são exatamente iguais.
Os tempos de ida e volta do ping foram medidos com ping -c100; os valores apresentados são o rtt médio
e o desvio médio (indicando a dispersão em torno da média), em milissegundos.
Laptop -> Wifi AP -> Servidor doméstico -> Provedor DSL -> Datacenter iodine DNS "relay" bind9 DNS cache iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
iodine -> Wifi AP :53
-Tnull (= -Oraw) 982 43.6 131.0 28.0 4.6 26.8 3.4
iodine -> Home server :53
-Tnull (= -Oraw) 1174 48.0 305.8 26.6 5.0 26.9 8.4
iodine -> DSL provider :53
-Tnull (= -Oraw) 1174 56.7 367.0 20.6 3.1 21.2 4.4
-Ttxt -Obase32 730 56.7 174.7*
-Ttxt -Obase64 874 56.7 174.7
-Ttxt -Obase128 1018 56.7 174.7
-Ttxt -Oraw 1162 56.7 358.2
-Tsrv -Obase128 910 56.7 174.7
-Tcname -Obase32 151 56.7 43.6
-Tcname -Obase128 212 56.7 52.4
iodine -> DSL provider :53
wired (no Wifi) -Tnull 1174 74.2 585.4 20.2 5.6 19.6 3.4
[174.7* : these all have 2frag/packet]
Laptop -> Wifi+vpn / com fio -> Servidor doméstico iodine iodined
downstr. upstream downstr. ping-up ping-down
fragsize kbit/s kbit/s avg +/-mdev avg +/-mdev
-----------------------------------------------------------------------------
wifi + openvpn -Tnull 1186 166.0 1022.3 6.3 1.3 6.6 1.6
wired -Tnull 1186 677.2 2464.1 1.3 0.2 1.3 0.1
O desempenho está fortemente acoplado a tempos de ping baixos, pois o iodine exige confirmação para cada fragmento de dados antes de passar para o próximo. Permitir múltiplos fragmentos em voo, como o TCP, poderia aumentar o desempenho, mas provavelmente causaria sobrecarga séria nos servidores DNS intermediários. O protocolo atual escala o desempenho com a responsividade do DNS, pois os servidores DNS lidam, em média, com no máximo uma solicitação DNS por cliente.
O iodine foi testado em Linux (arm, ia64, x86, AMD64 e SPARC64), FreeBSD (ia64, x86), OpenBSD (x86), NetBSD (x86), MacOS X (ppc e x86, com http://tuntaposx.sourceforge.net/) e Windows (com o driver OpenVPN TAP32, veja o arquivo readme do win32). Deve ser fácil portá-lo para outros sistemas semelhantes a Unix que tenham suporte a tunelamento TUN/TAP. Informe-nos se você conseguir executá-lo em outras plataformas.
O nome iodine foi escolhido porque começa com IOD (IP Over DNS, IP sobre DNS) e porque o iodo tem número atômico 53, que por acaso é o número da porta DNS.
Copyright (c) 2006-2014 Erik Ekman [email protected], 2006-2009 Bjorn Andersson [email protected]. Também com grandes contribuições de Anne Bezemer.
É concedida permissão para usar, copiar, modificar e/ou distribuir este software para qualquer finalidade, com ou sem taxa, desde que o aviso de copyright acima e este aviso de permissão apareçam em todas as cópias.
ESTE SOFTWARE É FORNECIDO "NO ESTADO EM QUE SE ENCONTRA" E O AUTOR SE ISENTA DE TODAS AS GARANTIAS COM RELAÇÃO A ESTE SOFTWARE, INCLUINDO TODAS AS GARANTIAS IMPLÍCITAS DE COMERCIABILIDADE E ADEQUAÇÃO. EM NENHUM CASO O AUTOR SERÁ RESPONSÁVEL POR QUAISQUER DANOS ESPECIAIS, DIRETOS, INDIRETOS OU CONSEQUENCIAIS, OU POR QUAISQUER DANOS RESULTANTES DE PERDA DE USO, DADOS OU LUCROS, SEJA EM AÇÃO DE CONTRATO, NEGLIGÊNCIA OU OUTRA AÇÃO DANOSA, DECORRENTES DE OU EM CONEXÃO COM O USO OU DESEMPENHO DESTE SOFTWARE.
Implementação de MD5 por L. Peter Deutsch (licença e fonte em src/md5.[ch])
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. Todos os direitos reservados.