Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Netty的自定义DNS服务器_Java_Dns_Netty_Nameservers - Fatal编程技术网

Java 使用Netty的自定义DNS服务器

Java 使用Netty的自定义DNS服务器,java,dns,netty,nameservers,Java,Dns,Netty,Nameservers,我一直在尝试使用netty编写自定义DNS服务器。我已经使用了解析传入的DNSQuery UDP数据包,但我不知道如何发送响应来解析域名。我已从处理程序接收到对象,但找不到初始化和添加测试DNS记录的方法,并通过将其发送回客户端 以下是我迄今为止所做的工作 public class DNSListen { public static void main(String[] args) { final NioEventLoopGroup group = new NioEventLoopGro

我一直在尝试使用netty编写自定义DNS服务器。我已经使用了解析传入的DNSQuery UDP数据包,但我不知道如何发送响应来解析域名。我已从处理程序接收到对象,但找不到初始化和添加测试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();
    }

}
}
公共类DNSListen{
公共静态void main(字符串[]args){
final NioEventLoopGroup组=新的NioEventLoopGroup();
试一试{
Bootstrap Bootstrap=新的Bootstrap();
bootstrap.group(组)
.channel(NioDatagramChannel.class)
.handler(新的通道初始值设定项(){
@凌驾
受保护的void initChannel(NioDatagramChannel NioDatagramChannel)引发异常{
nioDatagramChannel.pipeline().addLast(新的DatagramdnsQueryCoder());
nioDatagramChannel.pipeline().addLast(新的datagramdnsrresponseencoder());
nioDatagramChannel.pipeline().addLast(新的DNSMessageHandler());
}
})
.option(ChannelOption.SO_广播,true);
ChannelFuture=bootstrap.bind(53.sync();
future.channel().closeFuture().sync();
}捕捉(中断异常e){
e、 printStackTrace();
}最后{
group.ShutdownGracely();
}
}
}
这是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();
}
}
公共类DNSMessageHandler扩展了SimpleChannelInboundHandler{
@凌驾
受保护的无效channelRead0(ChannelHandlerContext ctx、DatagramDnsQuery dnsMessage)引发异常{
System.out.println(dnsMessage.content());
}
@凌驾
public void exceptionCaught(ChannelHandlerContext ctx,可丢弃原因)引发异常{
cause.printStackTrace();
}
}
当我运行此命令并将系统DNS设置为127.0.0.1时,我获得了多个DNS请求的输出 但是我无法找到一种方法来发送虚拟DNS响应,以便解析请求域的IP地址。(我认为我应该初始化一个对象并将其写回用户,但这是正确的吗?如果是,我如何使用虚拟IP作为解析IP初始化它)
如果我走错了路,有人能告诉我正确的路吗。谢谢。

实际上非常简单,您只需要一个
Datagramdnsrresponse
的实例,然后使用
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);
编辑

要对名称进行编码,请使用此函数(我从netty中提取):

要解码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));
}

我补充了我迄今为止所做的工作,并作了进一步解释。谢谢。你能举一个例子来编码my.domain.tld吗?
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));
}