我正在为大学的网络课程编写作业,我必须手动将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);
但是我遇到的问题是我需要解析Hex响应并检索上述信息。我整个上午都在寻找,但我似乎无法找到任何能够解析这些信息的库。
如果有人知道一个好的图书馆或我可以自己解析它的方式,我会非常感激。
干杯 科里
编辑:这是我的完整代码
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
答案 0 :(得分:1)
你看过if
(http://dnsjava.org/)了吗?它是一个高级DNS客户端,但您可以根据需要直接重用其内部部分进行数据包解析。
如果您的数据包来自UDP或TCP,则解析时几乎没有什么区别。
如果您查看dnsjava
,可能会使用各种Record.java
方法。另请参阅fromWire
目录和utils/
文件。
否则请返回规范:RFC1035第4部分为您提供有关如何格式化邮件的所有详细信息。它在两个方向上都是相同的结构。在您的具体情况下,您需要查看“答案”部分。确保不要忘记名称压缩,如§4.1.4所述。