2017-10-07 4 views
2

J'ai essayé d'écrire un serveur DNS personnalisé en utilisant netty. J'ai utilisé le DatagramDnsQueryDecoder pour analyser les paquets UDP DNSQuery entrants mais je n'arrive pas à comprendre comment envoyer une réponse pour résoudre un nom de domaine. J'ai reçu l'objet DatagramDnsQuery du gestionnaire mais je ne trouve pas un moyen d'initialiser DatagramDnsResponse et d'ajouter un enregistrement DNS de test et de le renvoyer au client via DatagramDnsResponseEncoder.Serveur DNS personnalisé utilisant Netty

Voici ce que je l'ai fait jusqu'à présent

public class DNSListen { 
public static void main(String[] args) { 
    final NioEventLoopGroup group = new NioEventLoopGroup(); 

    try { 
     Bootstrap bootstrap = new Bootstrap(); 
     bootstrap.group(group) 
       .channel(NioDatagramChannel.class) 
       .handler(new ChannelInitializer<NioDatagramChannel>() { 
        @Override 
        protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception { 
         nioDatagramChannel.pipeline().addLast(new DatagramDnsQueryDecoder()); 
         nioDatagramChannel.pipeline().addLast(new DatagramDnsResponseEncoder()); 
         nioDatagramChannel.pipeline().addLast(new DNSMessageHandler()); 
        } 
       }) 
       .option(ChannelOption.SO_BROADCAST, true); 

     ChannelFuture future = bootstrap.bind(53).sync(); 
     future.channel().closeFuture().sync(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } finally { 
     group.shutdownGracefully(); 
    } 

} 
} 

ici est le gestionnaire pour DNSMessages

public class DNSMessageHandler extends SimpleChannelInboundHandler<DatagramDnsQuery> { 

@Override 
protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsQuery dnsMessage) throws Exception { 
    System.out.println(dnsMessage.content()); 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
    cause.printStackTrace(); 
} 
} 

Je reçois la sortie de plusieurs requêtes DNS lorsque je lance et a fixé le DNS Système 127.0.0.1 Mais je ne peux pas trouver un moyen d'envoyer une réponse DNS fictive afin que l'adresse IP est résolue pour le domaine demandé. (Je pense que je devrais initialiser un objet DatagramDnsResponse et le réécrire à l'utilisateur, mais est-ce correct?, Si oui, comment l'initialiser avec une IP fictive comme l'IP résolu) Suis-je dans le mauvais chemin, quelqu'un peut-il s'il vous plaît dirige-moi vers le bon chemin. Merci.

+0

Il est impossible de dire si vous êtes sur la bonne voie. Vous n'avez pas montré ce que vous avez fait. http://idownvotedbecau.se/nocode/ – blafasel

+0

J'ai ajouté ce que j'ai fait jusqu'ici, et expliqué de plus. Merci. –

Répondre

1

Il est assez facile actuellement, vous avez juste besoin d'une instance de DatagramDnsResponse et ajouter un enregistrement DNS avec la méthode addRecord c'est tout.

Voici un exemple pour une réponse SRV:

DatagramDnsResponse response = new DatagramDnsResponse(msg.recipient(), msg.sender(), msg.id()); 
ByteBuf buf = Unpooled.buffer(); 
buf.writeShort(0); // priority 
buf.writeShort(0); // weight 
buf.writeShort(993); // port 
encodeName("my.domain.tld", buf); // target (special encoding: https://tools.ietf.org/html/rfc1101) 
response.addRecord(DnsSection.ANSWER, new DefaultDnsRawRecord("_myprotocol._tcp.domain.tld." /* requested domain */, DnsRecordType.SRV, 30 /* ttl */ , buf)); 
ctx.writeAndFlush(response); 

Modifier

Pour encoder un nom utiliser cette fonction (j'extrait à partir Netty):

public void encodeName(String name, ByteBuf buf) throws Exception { 
    if(".".equals(name)) { 
     buf.writeByte(0); 
     return; 
    } 

    final String[] labels = name.split("\\."); 
    for (String label : labels) { 
     final int labelLen = label.length(); 
     if (labelLen == 0) 
      break; 

     buf.writeByte(labelLen); 
     ByteBufUtil.writeAscii(buf, label); 
    } 

    buf.writeByte(0); 
} 

Pour décoder un enregistrement SRV vous pouvez utiliser cet extrait:

DnsRawRecord record = msg.recordAt(DnsSection.ANSWER, 0); //msg is a DnsResponse 
if(record.type() == DnsRecordType.SRV) { 
    ByteBuf buf = record.content(); 
    System.out.println("\tPriority: " + buf.readUnsignedShort()); 
    System.out.println("\tWeight: " + buf.readUnsignedShort()); 
    System.out.println("\tPort: " + buf.readUnsignedShort()); 
    System.out.println("\tTarget:" + DefaultDnsRecordDecoder.decodeName(buf)); 
} 
+0

Pouvez-vous donner un exemple codant my.domain.tld? – rich