Библиотека Java для разбора DNS-ответа UDP-пакет? - PullRequest
0 голосов
/ 26 апреля 2018

Я пишу задание для сетевого курса в университете, где мне нужно вручную отправить DNS-запрос на DNS-сервер, а затем обработать ответ, чтобы получить почтовые серверы, адреса IPv4 и IPv6 и некоторые другие вещи.,В спецификации назначения написано, что мне разрешено использовать любые библиотеки, которые я хочу проанализировать в ответном пакете DNS, однако я не могу найти одну для Java.

Я отправляю свой запрос DNS и получаю ответ, подобный этому:

int port = 53;
    dnsIP = "8.8.8.8"; // TODO HARDCODED

    DatagramSocket socket;
    // DNS REQUEST
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);
    dos.writeShort(0x1234);

    // Write Query Flags
    dos.writeShort(0x0100);

    // Question Count: Specifies the number of questions in the Question section of the message.
    dos.writeShort(0x0001);

    // Answer Record Count: Specifies the number of resource records in the Answer section of the message.
    dos.writeShort(0x0000);

    // Authority Record Count: Specifies the number of resource records in the Authority section of 
    // the message. (“NS” stands for “name server”)
    dos.writeShort(0x0000);

    // Additional Record Count: Specifies the number of resource records in the Additional section of the message.
    dos.writeShort(0x0000);        

    String[] domainParts = hostName.split("\\.");
    System.out.println(hostName + " has " + domainParts.length + " parts");

    for (int i = 0; i<domainParts.length; i++) {
        System.out.println("Writing: " + domainParts[i]);
        byte[] domainBytes = domainParts[i].getBytes("UTF-8");
        dos.writeByte(domainBytes.length);
        dos.write(domainBytes);
    }

 // No more parts
    dos.writeByte(0x00);

    // Type 0x01 = A (Host Request)
    dos.writeShort(0xFF);

    // Class 0x01 = IN
    dos.writeShort(0x0001);

    byte[] dnsFrame = baos.toByteArray();

    System.out.println("Sending: " + dnsFrame.length + " bytes");
    for (int i =0; i< dnsFrame.length; i++) {
        System.out.print("0x" + String.format("%x", dnsFrame[i]) + " " );
    }
    socket = new DatagramSocket();
    DatagramPacket dnsRequestPacket = new DatagramPacket(dnsFrame, dnsFrame.length, InetAddress.getByName(dnsIP), port);
    socket.send(dnsRequestPacket);

    byte[] buffer = new byte[1024];
    DatagramPacket dnsResponsePacket = new DatagramPacket(buffer, buffer.length);
    socket.receive(dnsResponsePacket);

Однако у меня возникла проблема в том, что мне нужно проанализировать шестнадцатеричный ответ и получить вышеупомянутую информацию.Я искал все утро, но, похоже, не могу найти ни одной библиотеки, способной проанализировать эту информацию.

Если кто-нибудь знает о хорошей библиотеке или о том, как я могу ее проанализировать сам, я был бы очень признателен.

Приветствия Кори

РЕДАКТИРОВАТЬ: вот мой полный код

package coms3200A2;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.Font;

public class AppHome {

    private JFrame frame;
    private JTextField DNSServerInput;
    private JTextField hostDomainInput;
    JTabbedPane tabbedPane;
    SpringLayout sl_DNSSearch;
    SpringLayout s2_RDNSSearch;

    JPanel DNSSearch;
    JPanel RDNSSearch;
    JLabel DNSServerLabel;
    JLabel hostDomainLabel;
    JButton submitDNS;
    JLabel DNSErrorsLabel;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    AppHome window = new AppHome();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public AppHome() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(0, 0, 1400, 900);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        sl_DNSSearch = new SpringLayout();
        s2_RDNSSearch = new SpringLayout();

        DNSSearch = new JPanel(sl_DNSSearch);
        RDNSSearch = new JPanel(s2_RDNSSearch);

        // TODO TESTING
        DNSSearch.setBackground(Color.LIGHT_GRAY);
        RDNSSearch.setBackground(Color.GRAY);
        // DNS SEARCH

        tabbedPane.addTab("DNS Search", DNSSearch);

        DNSServerLabel = new JLabel("DNS Server: ");
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, DNSServerLabel, 10, SpringLayout.NORTH, DNSSearch);
        sl_DNSSearch.putConstraint(SpringLayout.WEST, DNSServerLabel, 10, SpringLayout.WEST, DNSSearch);
        DNSSearch.add(DNSServerLabel);

        hostDomainLabel = new JLabel("Host/Domain name: ");
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, hostDomainLabel, 21, SpringLayout.SOUTH, DNSServerLabel);
        sl_DNSSearch.putConstraint(SpringLayout.WEST, hostDomainLabel, 0, SpringLayout.WEST, DNSServerLabel);
        DNSSearch.add(hostDomainLabel);

        DNSServerInput = new JTextField();
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, DNSServerInput, -3, SpringLayout.NORTH, DNSServerLabel);
        sl_DNSSearch.putConstraint(SpringLayout.WEST, DNSServerInput, 115, SpringLayout.EAST, DNSServerLabel);
        DNSSearch.add(DNSServerInput);
        DNSServerInput.setColumns(30);

        hostDomainInput = new JTextField();
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, hostDomainInput, -3, SpringLayout.NORTH, hostDomainLabel);
        sl_DNSSearch.putConstraint(SpringLayout.WEST, hostDomainInput, 0, SpringLayout.WEST, DNSServerInput);
        DNSSearch.add(hostDomainInput);
        hostDomainInput.setColumns(30);

        submitDNS = new JButton("Submit");
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, submitDNS, 46, SpringLayout.SOUTH, hostDomainInput);
        sl_DNSSearch.putConstraint(SpringLayout.EAST, submitDNS, 0, SpringLayout.EAST, DNSServerInput);
        DNSSearch.add(submitDNS);

        DNSErrorsLabel = new JLabel("\"errors here\"");
        sl_DNSSearch.putConstraint(SpringLayout.NORTH, DNSErrorsLabel, 83, SpringLayout.SOUTH, hostDomainLabel);
        sl_DNSSearch.putConstraint(SpringLayout.WEST, DNSErrorsLabel, 0, SpringLayout.WEST, DNSServerLabel);
        DNSErrorsLabel.setFont(new Font("Arial", Font.PLAIN, 20));
        DNSErrorsLabel.setForeground(Color.RED);
        DNSSearch.add(DNSErrorsLabel);

        // REVERSE DNS SEARCH
        tabbedPane.addTab("Reverse DNS Search", RDNSSearch);

        frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
        submitDNS.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    processDNSSearch(DNSServerInput.getText(), hostDomainInput.getText());
                } catch (Exception e2) {
                    e2.printStackTrace();

                    DNSErrorsLabel.setText("Error: " + e2.getMessage());
                }

            }
        });
    }

    private void processDNSSearch(String dnsServer, String hostName) throws IOException {
        String dnsIP = dnsServer;
        int port = 53;
        dnsIP = "8.8.8.8"; // TODO HARDCODED

        DatagramSocket socket;
        // DNS REQUEST
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeShort(0x1234);

        // Write Query Flags
        dos.writeShort(0x0100);

        // Question Count: Specifies the number of questions in the Question section of the message.
        dos.writeShort(0x0001);

        // Answer Record Count: Specifies the number of resource records in the Answer section of the message.
        dos.writeShort(0x0000);

        // Authority Record Count: Specifies the number of resource records in the Authority section of 
        // the message. (“NS” stands for “name server”)
        dos.writeShort(0x0000);

        // Additional Record Count: Specifies the number of resource records in the Additional section of the message.
        dos.writeShort(0x0000);        

        String[] domainParts = hostName.split("\\.");
        System.out.println(hostName + " has " + domainParts.length + " parts");

        for (int i = 0; i<domainParts.length; i++) {
            System.out.println("Writing: " + domainParts[i]);
            byte[] domainBytes = domainParts[i].getBytes("UTF-8");
            dos.writeByte(domainBytes.length);
            dos.write(domainBytes);
        }

     // No more parts
        dos.writeByte(0x00);

        // Type 0x01 = A (Host Request)
        dos.writeShort(0xFF);

        // Class 0x01 = IN
        dos.writeShort(0x0001);

        byte[] dnsFrame = baos.toByteArray();

        System.out.println("Sending: " + dnsFrame.length + " bytes");
        for (int i =0; i< dnsFrame.length; i++) {
            System.out.print("0x" + String.format("%x", dnsFrame[i]) + " " );
        }
        socket = new DatagramSocket();
        DatagramPacket dnsRequestPacket = new DatagramPacket(dnsFrame, dnsFrame.length, InetAddress.getByName(dnsIP), port);
        socket.send(dnsRequestPacket);

        byte[] buffer = new byte[1024];
        DatagramPacket dnsResponsePacket = new DatagramPacket(buffer, buffer.length);
        socket.receive(dnsResponsePacket);

        System.out.println("\nReceived: " + dnsResponsePacket.getLength() + " bytes");
        for (int i = 0; i < dnsResponsePacket.getLength(); i++) {
            //System.out.print(" 0x" + buffer + " " );
            System.out.print(" 0x" + String.format("%x", buffer[i]) + " " );

        }
        System.out.println("\n");



        DataInputStream din = new DataInputStream(new ByteArrayInputStream(buffer));
        System.out.println("Transaction ID: 0x" + String.format("%x", din.readShort()));
        System.out.println("Flags: 0x" + String.format("%x", din.readShort()));
        System.out.println("Questions: 0x" + String.format("%x", din.readShort()));
        System.out.println("Answers RRs: 0x" + String.format("%x", din.readShort()));
        System.out.println("Authority RRs: 0x" + String.format("%x", din.readShort()));
        System.out.println("Additional RRs: 0x" + String.format("%x", din.readShort()));

        int recLen = 0;
        while ((recLen = din.readByte()) > 0) {
            byte[] record = new byte[recLen];

            for (int i = 0; i < recLen; i++) {
                record[i] = din.readByte();
            }

            System.out.println("Record: " + new String(record, "UTF-8"));
        }

        System.out.println("Record Type: 0x" + String.format("%x", din.readShort()));
        System.out.println("Class: 0x" + String.format("%x", din.readShort()));

        System.out.println("Field: 0x" + String.format("%x", din.readShort()));
        System.out.println("Type: 0x" + String.format("%x", din.readShort()));
        System.out.println("Class: 0x" + String.format("%x", din.readShort()));
        System.out.println("TTL: 0x" + String.format("%x", din.readInt()));

        short addrLen = din.readShort();
        System.out.println("Len: 0x" + String.format("%x", addrLen));

        System.out.print("Address: ");
        for (int i = 0; i < addrLen; i++ ) {
            System.out.print("" + String.format("%d", (din.readByte() & 0xFF)) + ".");
        }
    }

}

enter code here

1 Ответ

0 голосов
/ 22 мая 2018

Вы смотрели на dnsjava (http://dnsjava.org/)? Это высокоуровневый клиент DNS, но вы можете напрямую использовать его внутреннюю часть для простого анализа пакета в соответствии с вашими потребностями.

Этоне имеет большого значения при разборе, если ваш пакет пришел из UDP или TCP. Если вы посмотрите на Record.java, то могут быть полезны различные методы fromWire. См. также каталог utils/ и файл DNSInput.java.

В противном случае вернитесь к спецификации: RFC1035 В разделе 4 приведены все подробности о том, как форматируется сообщение. Это одинаковая структура в обоих направлениях. В вашем конкретном случае вам нужно будет ткнуть вЧасть «Ответ». Убедитесь, что не забыли о сжатии имен, как описано в §4.1.4.

...