Skip to content

Instantly share code, notes, and snippets.

@aravindhkumar23
Created April 4, 2023 13:37
Show Gist options
  • Save aravindhkumar23/2b6bd80952267debb9b32becf73a04c1 to your computer and use it in GitHub Desktop.
Save aravindhkumar23/2b6bd80952267debb9b32becf73a04c1 to your computer and use it in GitHub Desktop.
DNS resolver - test implemention - not prod ready
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)
}
@mike1023
Copy link

Does it work? where is the method calculateIPv4HeaderChecksum

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment