Created
April 4, 2023 13:37
-
-
Save aravindhkumar23/2b6bd80952267debb9b32becf73a04c1 to your computer and use it in GitHub Desktop.
DNS resolver - test implemention - not prod ready
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func handlePacket(packetData: Data,syntheticIp: String) { | |
if(syntheticIp == "" || syntheticIp.isEmpty){ | |
os_log(.default, log: self.log, "*****No synthetic ip found") | |
return | |
} | |
let udpPayload : Data = packetData[28..<packetData.count] | |
do { | |
//to deserialize we used https://github.com/Bouke/DNS | |
let dnsQuery = try Message(deserialize: udpPayload) | |
os_log(.default, log: self.log, "________inside dnsQuery:===>>responseData=>> %{public}@",dnsQuery.debugDescription) | |
var dnsResponse = Message(id: dnsQuery.id, type: .response) | |
// Add the questions from the query to the response | |
dnsResponse.questions = dnsQuery.questions | |
// Add the answers to the response | |
let answer = HostRecord<IPv4>(name: dnsQuery.questions.first?.name ?? "", ttl: 3600, ip: IPv4(syntheticIp)!) | |
dnsResponse.answers.append(answer) | |
let responseData = try dnsResponse.serialize() | |
updateDnsDataPacket(packetData: packetData, syntheticIp: syntheticIp, queryResponseData: responseData) | |
} catch { | |
os_log(.default, log: self.log, "inside handlePacket:dnsQuery=error %{public}@",error as CVarArg) | |
} | |
} | |
func updateDnsDataPacket(packetData: Data,syntheticIp: String, queryResponseData: Data){ | |
// Get a mutable copy of the packet | |
let mutablePacket = NSMutableData(data: packetData) | |
//convert ipv4 ip address to UInt32 | |
let newDestinationIP = ipv4StringToUInt32(syntheticIp) | |
if(newDestinationIP == nil){ | |
os_log(.default, log: self.log, "syntheticIp to UInt32 failed") | |
return; | |
} | |
// Update the destination IP address | |
let newDestinationIPBytes = withUnsafeBytes(of: newDestinationIP!.bigEndian) { Data($0) } | |
newDestinationIPBytes.withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> Void in | |
mutablePacket.replaceBytes(in: NSRange(location: 16, length: 4), withBytes: pointer.baseAddress!) | |
} | |
let udpLength = queryResponseData.count + 8 //update the udp length [constructed response data length + 8(udp header default length)] | |
let udpLengthHexString = String(format: "%04X", udpLength) | |
let ipV4Length = udpLength+20 //update the ipv4 length [udp data length + 20(ipv4 header default length)] | |
let ipV4LengthHexString = String(format: "%04X", ipV4Length) | |
var updatedDataPacket = mutablePacket as Data | |
var updatedHexString = updatedDataPacket.hexEncodedString() | |
//update ipv4 length | |
let ipv4StartIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 4) //byte offset 2-3 is for ipv4 length | |
let ipv4EndIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 8) | |
updatedHexString.replaceSubrange(ipv4StartIndex..<ipv4EndIndex, with: ipV4LengthHexString) | |
//update udp length | |
let udpStartIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 48) //byte offset 24-25 is for udp length | |
let udpEndIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 52) | |
updatedHexString.replaceSubrange(udpStartIndex..<udpEndIndex, with: udpLengthHexString) | |
//update udp response | |
let udpResponseStartIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 56) //byte offset 28-END is for udp query data | |
let udpResponseEndIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: updatedHexString.count) | |
updatedHexString.replaceSubrange(udpResponseStartIndex..<udpResponseEndIndex, with: queryResponseData.hexEncodedString()) | |
os_log(.default, log: self.log, "updatedHexString: %{public}@",updatedHexString) | |
let rawDataPacket = Data(fromHexEncodedString: updatedHexString)! | |
let udpPacket : Data = rawDataPacket[20..<rawDataPacket.count]// your UDP packet as Data | |
os_log(.default, log: self.log, "updatedHexString: udpPacket : %{public}@",udpPacket.hexEncodedString()) | |
// let byteArray = [UInt8](udpPacket) | |
// let checksum = checksum(bytes: byteArray) | |
// os_log(.default, log: self.log, "updatedHexString checksum: %{public}@",checksum.description) | |
let ipv4CheckSum = calculateIPv4HeaderChecksum(packetData: rawDataPacket) | |
let ipV4CheckSumString = String(format: "%04X", ipv4CheckSum) | |
//update ipv4 checksum | |
let ipv4CheckSumStartIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 20) //byte offset 10-11 is for ipv4 checksum | |
let ipv4CheckSumEndIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 24) | |
updatedHexString.replaceSubrange(ipv4CheckSumStartIndex..<ipv4CheckSumEndIndex, with: ipV4CheckSumString) | |
//update udp checksum | |
let udpCheckSumStartIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 52) //byte offset 26-27 is for udp checksum | |
let udpCheckSumEndIndex = updatedHexString.index(updatedHexString.startIndex, offsetBy: 56) | |
updatedHexString.replaceSubrange(udpCheckSumStartIndex..<udpCheckSumEndIndex, with: "0000") | |
// let checksum = calculateUDPChecksum(packetData: rawDataPacket) | |
// os_log(.default, log: self.log, "updatedHexString checksum: %{public}@",checksum) | |
//finally update the mutable packet with the update hex string | |
updatedDataPacket = Data(fromHexEncodedString: updatedHexString)! | |
os_log(.default, log: self.log, "updatedHexString: befire sending %{public}@",updatedDataPacket.hexEncodedString()) | |
//write packet to server | |
let proto = protocolNumber(for: updatedDataPacket) | |
let success = self.packetFlow.writePackets([updatedDataPacket], withProtocols: [proto]) | |
os_log(.default, log: self.log, "packetFlow.writePackets: %{public}@",success.description) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Does it work? where is the method calculateIPv4HeaderChecksum