IPTables - consulta DNS de bloco de cadeia hexadecimal

1

Eu tenho um cliente que está enviando muitas consultas para um domínio específico no meu servidor DNS. Eu quero bloquear as consultas e encontrei a string hexadecimal que é possível de ser implementada. Essa é a string:

iptables -I INPUT 1 -p udp --dport 53 --match string --algo kmp --hex-string '|77 70 61 64 2e 64 6f 6d 61 69 6e 2e 6e 61 6d 65|' -j DROP

-

0     0 DROP       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:53 STRING match  "wpad.domain.name" ALGO name kmp TO 65535

Mas parece que não funciona, porque quando eu consultar esse nome contra esse servidor, eu posso ver a resposta e os contadores permanecem em zero

root@banana:~# dig @5.172.120.59 wpad.domain.name

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @5.172.120.59 wpad.domain.name
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 29891
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;wpad.domain.name.              IN      A

;; Query time: 136 msec
;; SERVER: 5.172.120.59#53(5.172.120.59)
;; WHEN: Thu Nov 26 22:55:30 2015
;; MSG SIZE  rcvd: 34

Você consegue identificar algum erro?

Obrigado

    
por Federi 26.11.2015 / 23:56

2 respostas

2

não faça isso

... pelo menos não para este pedido DNS específico. Por que não? Bem, em primeiro lugar, você não está realmente facilitando para você, sua CPU, e você está tornando isso muito pior para o cliente. Quase todos os navegadores em todas as plataformas, quando recebem um endereço DHCP, usam "detecção automática de proxy". Essa detecção automática funciona procurando uma entrada de DNS para um nome de host wpad.subdomain.subdomain.currentdomain.xx proceding down to wpad.currentdomain.xx . Em segundo lugar, o navegador solicita que o sistema operacional obtenha o DNS, e o sistema operacional (sujeito a vários parâmetros TCP / UDP) continuará a tentar a solicitação para o servidor DNS até obter uma resposta. Quando você bloqueia a entrada, você impede que seu servidor DNS responda, portanto o cliente tenta novamente e novamente, e novamente. E bloqueando isso, você não está de alguma forma "treinando" o cliente para parar de enviar as solicitações. Se não obtiver uma resposta, ela simplesmente pára de tentar usar um proxy e usa a conexão direta. Enquanto isso o usuário está apenas esperando para que o navegador tente a conexão direta. Ela pode estar esperando por 15 segundos antes que o navegador torne-se responsivo. Este mecanismo está agora incorporado em todos os dispositivos Android e iOS, por isso, todos os iPads, AppleTV e Samsung estão demorando muito para se conectar à Internet. Então, basicamente, você traz um idiota.

Como fazer isso (idealmente, corretamente)

Mas digamos que você irá bloquear uma consulta DNS baseada no QNAME. O QNAME compreende um conjunto de "rótulos". Enquanto nós vemos os rótulos em notação pontilhada, no pacote de consulta, cada rótulo é prefixado por seu comprimento em bytes, todos terminados por um NUL. 1

1 O OP já descobriu esta parte, mas fez parecer que tinha algo a ver com a string hexagonal.

A string hexadecimal, como eu confirmei olhando a fonte para o iptables 1.4.9 , já que nenhum manual que eu pudesse encontrar descreve adequadamente seu comportamento, é da forma (quase BNF)

HEXSTRING := SUBSTRING [ SUBSTRING ... ]

onde cada SUBSTRING é um dos

'\' CHAR
'|' HEXDIGIT HEXDIGIT [ SPACE ] '|'
CHAR

onde CHAR é praticamente qualquer coisa que a entrada pode manipular, e HEXDIGIT é o que isxdigit () diz que é, com a combinação convertida via sscanf(s,"%x",buf) . O caractere de escape garante que um pode ignorar o "modo hexadecimal" e corresponder à cadeia literal "|". Caso contrário, não faz nada de especial. O | à direita não é estritamente necessário se o SUBSTRING atual for o último em HEX-STRING.

Em seguida, otimizar a pesquisa: a seção Consulta não inicia antes do 13º byte da solicitação de DNS, o que significa iniciar a partir do byte 40 (20 (IP) + 8 (UDP) + 13 - 1). Se você puder testar se o pacote é uma consulta, o que você deve fazer, então você não precisa se preocupar com um limite para procurar - basta procurar até o final do pacote. Para testar se é uma consulta, teste os 5 bits altos do byte 31 no pacote. Você também pode querer levar em conta a pequena diferença do cabeçalho IP, que em condições raras é de 24 bytes em vez de 20, fazendo com que o byte teste 35 (ou 39).

Otimize ainda mais usando o algoritmo bm (Boyer-Moore). Não há nada de errado com o kmp , mas, em geral, o Boyer-Moore é mais rápido e usa menos recursos.

Juntando tudo, devemos ter algo como:

-A INPUT -s 5.172.121.170/32 -p udp -m udp --dport 53 \
-m u32 --u32 "28 & 0xF8 = 0" \
-m string --algo bm --from 40 \
--hex-string "|04|wpad|08|mydomain|03|isa|04|dick" 

A parte --u32 diz "pegue 4 bytes a partir do 28º (0-indexado) byte do pacote ... ou seja, bytes 28, 29, 30, 31 e mascare o valor de 32 bits com 0x000000F8 ... isso é só olhar para os cinco bits altos do byte 31 ... e se for 0, combine. " A parte --from , como mencionado, inicia a pesquisa por cadeia de caracteres na seção "pergunta" do pacote. Isso deve evitar falsos positivos.

Testado no RHEL 6.5 iptables 1.4.7.

Para ser pedante, crie outra regra que teste o byte 0 do campo de cabeçalho IP para o tamanho do cabeçalho e corresponda à consulta de DNS iniciada no byte 32.

    
por 27.11.2015 / 23:04
0

Encontrado por mim mesmo. a cadeia hexadecimal estava incorreta. Essa é a certa.

Além disso, no formato mais fácil --hex-string "|04|wpad|06|domanin|04|name|" , em que os valores numéricos significam o comprimento da palavra

-A INPUT -s 5.172.121.170/32 -p udp -m udp --dport 53 -m string \
--hex-string "|047770616406646f6d61696e046e616d65|" --algo kmp \
--to 65535 -m comment --comment "wpad.domain.name" -j DROP
    
por 27.11.2015 / 12:47

Tags