diff --git a/.gitignore b/.gitignore index 6b468b62a9884e67ca19b673f8e14e1931d65036..ca7a69a70fd138e92a1833297d1d5dbf2f3cffa8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.class +.idea/ \ No newline at end of file diff --git a/ClassType.java b/ClassType.java new file mode 100644 index 0000000000000000000000000000000000000000..6b4e97b8cec4620f33ea5d2a14502602034c1df7 --- /dev/null +++ b/ClassType.java @@ -0,0 +1,6 @@ +public class ClassType { + public static final int IN = 1; + public static final int CS = 2; + public static final int CH = 3; + public static final int HS = 4; +} \ No newline at end of file diff --git a/QueryType.java b/QueryType.java new file mode 100644 index 0000000000000000000000000000000000000000..561e2d716b97aca83491a9e302e2a7a51e07805d --- /dev/null +++ b/QueryType.java @@ -0,0 +1,19 @@ +public class QueryType { + public static final int A = 1 ; + public static final int NS = 2 ; + public static final int MD = 3 ; + public static final int MF = 4 ; + public static final int CNAME = 5 ; + public static final int SOA = 6 ; + public static final int MB = 7 ; + public static final int MG = 8 ; + public static final int MR = 9 ; + public static final int NULL = 10; + public static final int WKS = 11; + public static final int PTR = 12; + public static final int HINFO = 13; + public static final int MINFO = 14; + public static final int MX = 15; + public static final int TXT = 16; +} + diff --git a/RecordMapper.java b/RecordMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..91ef1f9a8c7fc244a11b8279459f58d09f9cad86 --- /dev/null +++ b/RecordMapper.java @@ -0,0 +1,81 @@ +import java.io.*; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +public class RecordMapper { + private String qname; + private String mappedIP = "x"; + private DatagramPacket inPacket; + private HashMap inMap; + public RecordMapper(DatagramPacket inPacket, HashMap inMap) throws IOException { + this.qname = getQName(inPacket); + this.inMap = inMap; + this.inPacket = inPacket; + } + + public boolean isRecorded() throws IOException { + mappedIP = getIPAddr(); + if(mappedIP.equals("x")){ + return false; + } + else { + return true; + } + } + + public void sendResponse(DatagramSocket mSocket) throws IOException { + ResponseBuilder rb = new ResponseBuilder(inMap, inPacket, mappedIP); + byte[] payload = rb.buildA(); + SocketAddress remoteAddress = inPacket.getSocketAddress(); + DatagramPacket sendPacket = new DatagramPacket(payload, payload.length, remoteAddress); + mSocket.send(sendPacket); + } + + public String getIPAddr() throws IOException { + File f = new File("relay.txt"); + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f))); + String line = ""; + while((line = in.readLine()) != null){ + String fname = line.split(" ")[1]; +// System.out.println(fname.hashCode() + " - " + qname.hashCode()); +// System.out.println(fname + " - " + qname); +// System.out.println(fname.equals(qname)); +// System.out.println(Arrays.toString(new String(qname.getBytes()).getBytes())); +// System.out.println(Arrays.toString(fname.getBytes())); + if(line.split(" ")[1].equals(qname)){ + System.out.println(line.split(" ")[0] + " - " + line.split(" ")[1]); + return line.split(" ")[0]; + } + } + return "x"; + } + + public String getQName(DatagramPacket packet){ + byte[] data = packet.getData(); +// System.out.println(Arrays.toString(data)); + int i = 13, j = 0; + while(data[i] != 0){ + i++; + } + byte[] qnameByte = new byte[i-13]; + i = 13; + while(data[i] != 0){ + if(data[i] > 47) { + qnameByte[j] = data[i]; + j++; + } + else { + qnameByte[j] = '.'; + j++; + } + i++; + } +// System.out.println(Arrays.toString(qnameByte)); + return new String(qnameByte); + } +} diff --git a/ResponseBuilder.java b/ResponseBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..736d2e825c1cd8654d51ea556d4664ec8703c218 --- /dev/null +++ b/ResponseBuilder.java @@ -0,0 +1,102 @@ +import java.net.DatagramPacket; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; + +public class ResponseBuilder { + private HashMap inMap; + private DatagramPacket inPacket; + private String srcIP; + public ResponseBuilder(HashMap inMap, DatagramPacket inPacket, String srcIP){ + this.inMap = inMap; + this.inPacket = inPacket; + this.srcIP = srcIP; + } + + public byte[] buildA(){ + System.out.println(srcIP); + int flags; + byte[] data = new byte[1024]; + System.out.println("in packet: " + Arrays.toString(inPacket.getData())); + int i = 0; + for(i = 0; i < inPacket.getData().length; i++){ + data[i] = inPacket.getData()[i]; + } + for(i = 13; inPacket.getData()[i] != 0; i++){ + } + int length = i + 5; + if(srcIP.equals("0.0.0.0")){ + flags = 0x8183; + } + else { + flags = 0x8180; + } + data[2] = (byte) ((flags >> 8) & 0xFF); + data[3] = (byte) (flags & 0xFF); + data[7] = 0x1; + data[length] = (byte) 0xc0; + data[length+1] = (byte) 0x0c; + data[length+2] = (byte) 0x0; + data[length+3] = (byte) QueryType.A; + data[length+4] = (byte) 0x0; + data[length+5] = (byte) ClassType.IN; + data[length+6] = (byte) 0x0; + data[length+7] = (byte) 0x0; + data[length+8] = (byte) 0x0; + data[length+9] = (byte) 0xe0; + data[length+10] = (byte) 0x0; + data[length+11] = (byte) 0x4; + String[] ip = srcIP.split("[.]"); + System.out.println(Arrays.toString(ip)); + System.out.println("Response: " + Arrays.toString(data)); + data[length+12] = (byte) Integer.parseInt(ip[0]); + data[length+13] = (byte) Integer.parseInt(ip[1]); + data[length+14] = (byte) Integer.parseInt(ip[2]); + data[length+15] = (byte) Integer.parseInt(ip[3]); + return data; + } + + public static byte[] hexToByte(int hex, int byteLength){ + byte[] src = Integer.toBinaryString(hex).getBytes(StandardCharsets.UTF_8); + byte[] res = new byte[byteLength]; + for(int i = 0; i < byteLength; i++){ + if(i < byteLength - src.length){ + res[i] = 0; + } + else { + src[i - byteLength + src.length] -= 48; + res[i] = src[ i - byteLength + src.length]; + } + } + return res; + } + + public byte[] ipToBytes(String ip){ + byte[] res = new byte[32]; + writeBytesFromBytes(res, 0, hexToByte(Integer.parseInt(ip.split(".")[0]), 8)); + writeBytesFromBytes(res, 8, hexToByte(Integer.parseInt(ip.split(".")[1]), 8)); + writeBytesFromBytes(res, 16, hexToByte(Integer.parseInt(ip.split(".")[2]), 8)); + writeBytesFromBytes(res, 24, hexToByte(Integer.parseInt(ip.split(".")[3]), 8)); + return res; + } + + public static void writeBytesFromHex(byte[] target, int cursor, int hex){ + byte[] src = Integer.toBinaryString(hex).getBytes(StandardCharsets.UTF_8); + for(int i = 0; i < src.length; i++){ + target[i+cursor] = src[i]; + } + } + + public static void writeBytesFromBytes(byte[] target, int cursor, byte[] src){ + for(int i = 0; i < src.length; i++){ + target[i+cursor] = src[i]; + } + } + + public static void main(String[] args) { + byte[] data = ResponseBuilder.hexToByte(0xc00c, 16); + for(int i = 0; i < 16; i++){ + System.out.println(data[i]); + } + } +} diff --git a/Server.java b/Server.java index 102865b49fb68115480e96deda3b069a6ebab05f..0e10c86ec39b4f6de269a97eab6a9cd9326ba5f6 100644 --- a/Server.java +++ b/Server.java @@ -1,14 +1,10 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.*; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.SocketAddress; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.net.InetAddress; public class Server { private static DatagramSocket mSocket; @@ -139,12 +135,18 @@ public class Server { @Override public void run() { try { - // new DatagramPacket - byte[] sendData = buildRespData(); - if (sendData.length > 4) { - SocketAddress remoteAddress = mPacket.getSocketAddress(); - DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, remoteAddress); - mSocket.send(sendPacket); + RecordMapper rm = new RecordMapper(mPacket, dMap); + if(rm.isRecorded()){ + rm.sendResponse(mSocket); + } + else { + // new DatagramPacket + byte[] sendData = buildRespData(); + if (sendData.length > 4) { + SocketAddress remoteAddress = mPacket.getSocketAddress(); + DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, remoteAddress); + mSocket.send(sendPacket); + } } } catch (Exception e) { e.printStackTrace(); diff --git a/dns-server-java.iml b/dns-server-java.iml new file mode 100644 index 0000000000000000000000000000000000000000..b107a2dd81165eaaf682ad3da030668b937fbb6c --- /dev/null +++ b/dns-server-java.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/out/production/dns-server-java/.gitignore b/out/production/dns-server-java/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ca7a69a70fd138e92a1833297d1d5dbf2f3cffa8 --- /dev/null +++ b/out/production/dns-server-java/.gitignore @@ -0,0 +1,2 @@ +*.class +.idea/ \ No newline at end of file diff --git a/relay.txt b/relay.txt new file mode 100644 index 0000000000000000000000000000000000000000..4ff977071b88c6ad16e93c4fd2b97404e9c815ff --- /dev/null +++ b/relay.txt @@ -0,0 +1,4 @@ +10.3.8.216 www.baidu.com +0.0.0.0 www.sogou.com +0.0.0.0 www.sohu.com +39.156.66.18 www.google.com diff --git a/run.sh b/run.sh deleted file mode 100644 index 8bbe1423ff2abe2d71e39ccec1af8905da0258bc..0000000000000000000000000000000000000000 --- a/run.sh +++ /dev/null @@ -1,3 +0,0 @@ - -javac Server.java -java Server \ No newline at end of file