2017-10-07 5 views
2

私はnettyを使用してカスタムDNSサーバーを作成しようとしています。私はDatagramDnsQueryDecoderを受信DNSQuery UDPパケットで解析するのに使用しましたが、ドメイン名を解決するために応答を送信する方法を理解できません。ハンドラからDatagramDnsQueryオブジェクトを受信しましたが、DatagramDnsResponseを初期化し、テストDNSレコードを追加してDatagramDnsResponseEncoderを通してクライアントに返信する方法を見つけることができません。ここで Nettyを使用するカスタムDNSサーバー

は私がこれまでにここに

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(); 
    } 

} 
} 

行わ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(); 
} 
} 

私はこれを実行すると、複数のDNS要求の出力を取得してシステムのDNSを設定ためのハンドラでてきたものです127.0.0.1 しかし、私は、要求されたドメインのIPアドレスが解決されるようにダミーDNS応答を送信する方法を見つけることができません。 (私はDatagramDnsResponseオブジェクトを初期化してユーザーに書き戻すべきだと思いますが、それは正しいですか?解決したIPとしてダミーのIPで初期化するにはどうすればいいですか) 間違ったパスにありますか?私を正しい経路に誘導してください。ありがとう。

+0

あなたが正しい方向にいるかどうかは言うまでもありません。あなたはあなたがしたことを示さなかった。 http://idownvotedbecau.se/nocode/ – blafasel

+0

これまで私が行ったことを加えて、さらに説明しました。ありがとう。 –

答えて

1

実際にはDatagramDnsResponseのインスタンスが必要で、addRecordメソッドを持つDNSレコードを追加するだけです。ここ

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); 

編集

名前は、この関数を使用し符号化するために(私は網状から抽出):

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); 
} 

する復号しますSRVレコードでこのスニペットを使用できます:

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

my.domain.tldをエンコードした例を挙げられますか? – rich

関連する問題