前言
這個也是 來自于一個朋友的需求?
最終的目的是實現一個 dns 代理服務器, 當然 這本質也是一個 dns 服務器?
并且 dns 代理服務器是依賴于 一個 dns 服務器的, 因此 順便給一個 dns 服務器的 demo?
這里 主要是 基于 udp 的一個 dns 請求, 響應數據的交互?
?
?
dns 服務器?
一個基礎的 dns 服務器 demo 如下?
為了方便測試, 可以將 端口改為 53, 然后使用 System.out.println 之類的進行調試?
package com.hx.test15;import org.xbill.DNS.*;import java.io.ByteArrayOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;/*** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2024-07-02 22:33*/
public class Test25SimpleDnsServer {public static void main(String[] args) throws Exception {DatagramSocket socket = new DatagramSocket(8053);System.out.println("DNS Server listening on port 8053...");while (true) {byte[] receiveData = new byte[512];DatagramPacket requestPacket = new DatagramPacket(receiveData, receiveData.length);socket.receive(requestPacket);byte[] data = requestPacket.getData();int offset = requestPacket.getOffset();int length = requestPacket.getLength();Message request = new Message(ByteBuffer.wrap(data, offset, length));Message response = handleRequest(request);ByteArrayOutputStream baos = new ByteArrayOutputStream();DNSOutput out = new DNSOutput();baos.write(out.toByteArray());baos.write(response.toWire());byte[] responseData = baos.toByteArray();DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length,requestPacket.getAddress(), requestPacket.getPort());socket.send(responsePacket);}}private static Message handleRequest(Message request) throws Exception {Message response = new Message(request.getHeader().getID());response.getHeader().setFlag(Flags.QR);response.getHeader().setOpcode(Opcode.QUERY);Record question = request.getQuestion();if (question.getName().toString().startsWith("www.abc.com") && question.getType() == Type.A) {ARecord answer = new ARecord(question.getName(), DClass.IN, 300, InetAddress.getByName("172.0.0.2"));response.addRecord(answer, Section.ANSWER);} else {// apply default}return response;}}
?
?
最終實現效果如下, dns 服務器中僅僅配置了 "www.abc.com" -> "172.0.0.2"?
因此 www.abc.com 能夠拿到查詢結果, www.baidu.com 拿不到查詢結果?
?
?
dns 代理服務器
主需求是實現一個 dns 的代理服務器??
實現如下, 無非就是 代理發送一次 dns 的請求 到目標 dns 服務器, 拿到響應之后 響應給客戶端?
package com.hx.test15;import org.xbill.DNS.Message;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;/*** Test25JavaDnsForwardServer** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2024-07-02 22:10*/
public class Test25JavaDnsForwardServer {public static void main(String[] args) throws IOException {DatagramSocket serverSocket = new DatagramSocket(53);System.out.println("DNS Proxy Server listening on port 53...");while (true) {byte[] receiveData = new byte[512];DatagramPacket requestPacket = new DatagramPacket(receiveData, receiveData.length);serverSocket.receive(requestPacket);Message request = readMessage(requestPacket);Message response = proxyRequest(request);ByteArrayOutputStream baos = new ByteArrayOutputStream();baos.write(response.toWire());byte[] responseData = baos.toByteArray();DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length,requestPacket.getAddress(), requestPacket.getPort());serverSocket.send(responsePacket);}}private static Message readMessage(DatagramPacket packet) throws IOException {byte[] data = packet.getData();int offset = packet.getOffset();int length = packet.getLength();return new Message(ByteBuffer.wrap(data, offset, length));}private static Message proxyRequest(Message request) throws IOException {DatagramSocket upstreamSocket = new DatagramSocket();InetAddress upstreamAddress = InetAddress.getByName("127.0.0.1");int upstreamPort = 8053;ByteArrayOutputStream baos = new ByteArrayOutputStream();baos.write(request.toWire());byte[] requestData = baos.toByteArray();DatagramPacket upstreamRequest = new DatagramPacket(requestData, requestData.length, upstreamAddress, upstreamPort);upstreamSocket.send(upstreamRequest);byte[] upstreamResponseData = new byte[512];DatagramPacket upstreamResponse = new DatagramPacket(upstreamResponseData, upstreamResponseData.length);upstreamSocket.receive(upstreamResponse);Message response = new Message(ByteBuffer.wrap(upstreamResponseData, upstreamResponse.getOffset(), upstreamResponse.getLength()));upstreamSocket.close();return response;}}
?
最終實現效果如下, dns 服務器中僅僅配置了 "www.abc.com" -> "172.0.0.2"?
因此 www.abc.com 能夠拿到查詢結果, www.baidu.com 拿不到查詢結果?
如果 關閉 目標dns服務, 代理服務器會阻塞住?
?
?
完?
?
?
?
?
?