Контрольная сумма пакета отрицательна после разрешения DNSAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Контрольная сумма пакета отрицательна после разрешения DNS

Сообщение Anonymous »

Я пытаюсь добавить DNS через HTTPS в приложение VPN. для справки по проекту VPN-Example. В этом проекте я пытаюсь добавить только DNS-запросы для передачи DNS через HTTPS (DoH) вместо простых DNS-запросов. Я могу сделать это и получить ответ для DoH. Проблема, с которой я в конечном итоге сталкиваюсь, заключается в том, что когда я обновляю пакет, я что-то упускаю или делаю что-то неправильно, что приводит к ошибкам расчета контрольной суммы. Я новичок в работе с сетями и не могу устранить эту проблему.
В методе VPN VPNRunnable Run я добавил следующий код, чтобы найти пакеты DNS-запросов, а затем разрешить DNS с помощью DoH.

Код: Выделить всё

private static class VPNRunnable implements Runnable {
//...
@Override
public void run() {
//...
if (packet.isDNSQuery()) {
String domain = packet.getDomainName();
Result resolvedResult = resolveDomainOverDoH(domain);
Log.i(TAG, "DNS Packet Before: " + packet.toString());
if (resolvedResult != null && !Objects.requireNonNull(resolvedResult.getAnswer()).isEmpty()) {
Packet dnsResponsePacket = buildDNSResponse(packet, resolvedResult);
if (dnsResponsePacket != null) {
Log.i(TAG, "DNS Packet After: " + dnsResponsePacket.toString());

networkToDeviceQueue.offer(dnsResponsePacket.toByteBuffer());
Log.i(TAG, "DNS response created for domain: " + domain);
} else {
Log.e(TAG, "Failed to create DNS response for domain: " + domain);
}
} else {
Log.e(TAG, "Failed to resolve DNS query for domain: " + domain);
}
} else if (packet.isUDP()) {
Log.i(TAG, "read udp" + readBytes); // Logs UDP read operation
deviceToNetworkUDPQueue.offer(packet); // Adds packet to UDP queue
} //...
В приведенном выше коде я могу получить правильный ответ DNS через HTTPS через

Код: Выделить всё

data class Result(
@SerializedName("Status") val status: Int,
@SerializedName("TC") val tc: Boolean?,
@SerializedName("RD") val rd: Boolean?,
@SerializedName("RA") val ra: Boolean?,
@SerializedName("AD") val ad: Boolean?,
@SerializedName("CD") val cd: Boolean?,
@SerializedName("Question") val question: List?,
@SerializedName("Answer") val answer: List?,
@SerializedName("Authority") val authority: List?,
@SerializedName("edns_client_subnet") val ednsClientSubnet: String?
)
data class Question(
@SerializedName("name") val name: String,
@SerializedName("type") val type: Int
)

data class Answer(
@SerializedName("name") val name: String,
@SerializedName("type") val type: Int,
@SerializedName("TTL") val ttl: Int,
@SerializedName("Expires") val expires: String,
@SerializedName("data") val data: String
)

data class Authority(
@SerializedName("name") val name: String,
@SerializedName("type") val type: Int,
@SerializedName("TTL") val ttl: Int,
@SerializedName("Expires") val expires: String,
@SerializedName("data") val data: String
)
и код поиска DNS через HTTPs:

Код: Выделить всё

// Perform a synchronous DNS lookup
fun lookup(domain: String, type: Int): Result? {
for (resolver in resolvers) {
val url = "${resolver.url}?name=$domain&type=$type"
val request = Request.Builder()
.url(url)
.apply {
if (resolver.method == Method.POST) post(RequestBody.create(null, ByteArray(0)))
}
.addHeader("Content-Type", "application/dns-json")
.build()

try {
val response = client.newCall(request).execute()
if (response.isSuccessful) {
response.body?.let { responseBody ->
return gson.fromJson(responseBody.string(), Result::class.java)
}
}
} catch (e: IOException) {
// Log or handle exception
e.printStackTrace()
}
}
return null
}
Проблема начинается после того, как я пытаюсь использовать этот код для обновления пакета и отправки его обратно на устройство. Код обновления моего пакета после того, как я передал его. Результат ответа DNS:

Код: Выделить всё

public static Packet buildDNSResponse(Packet queryPacket, Result responseInfo) {
try {
// Create a new response packet based on the query packet
ByteBuffer responseBuffer = ByteBuffer.allocate(1500); // Allocate a large enough buffer
responseBuffer.put(queryPacket.backingBuffer.array(), 0, queryPacket.backingBuffer.limit());
responseBuffer.clear();

Packet responsePacket = new Packet(responseBuffer);

// Swap source and destination IP addresses
byte[] tempIp = responsePacket.ip4Header.sourceAddress.getAddress();
responsePacket.ip4Header.sourceAddress = responsePacket.ip4Header.destinationAddress;
responsePacket.ip4Header.destinationAddress = InetAddress.getByAddress(tempIp);

// Swap source and destination ports
int tempPort = responsePacket.udpHeader.sourcePort;
responsePacket.udpHeader.sourcePort = responsePacket.udpHeader.destinationPort;
responsePacket.udpHeader.destinationPort = tempPort;

// Modify DNS header
int dnsStart = Packet.IP4_HEADER_SIZE + Packet.UDP_HEADER_SIZE;
responsePacket.backingBuffer.putShort(dnsStart + 2, (short) 0x8180); // DNS flags: Standard query response, No error
responsePacket.backingBuffer.putShort(dnsStart + 6, (short) responseInfo.getAnswer().size()); // Answer RRs

// Find the end of the question section
int questionEnd = findQuestionEnd(responsePacket.backingBuffer, dnsStart);

// Add answer section
int answerStart = questionEnd;
for (Answer answer : responseInfo.getAnswer()) {
answerStart = addAnswerRecord(responsePacket.backingBuffer, answerStart, answer);
}

// Update packet length
int totalLength = answerStart;
responsePacket.ip4Header.totalLength = totalLength;
responsePacket.backingBuffer.putShort(2, (short) totalLength);

// Update UDP length
int udpLength = totalLength - Packet.IP4_HEADER_SIZE;
responsePacket.udpHeader.length = udpLength;
responsePacket.backingBuffer.putShort(Packet.IP4_HEADER_SIZE + 4, (short) udpLength);

// Recalculate checksums
responsePacket.updateIP4Checksum();

// Adjust the limit of the backing buffer
responsePacket.backingBuffer.limit(totalLength);

return responsePacket;
} catch (Exception e) {
Log.e(TAG, "Error building DNS response", e);
return null;
}
}

private static int findQuestionEnd(ByteBuffer buffer, int dnsStart) {
int position = dnsStart + 12; // Start after DNS header
while (buffer.get(position) != 0) {
position += buffer.get(position) + 1;
}
return position + 5; // +1 for null byte, +4 for QTYPE and QCLASS
}

private static int addAnswerRecord(ByteBuffer buffer, int start, Answer answer) throws UnknownHostException {
buffer.putShort(start, (short) 0xC00C); // Pointer to question name
buffer.putShort(start + 2, (short) answer.getType());
buffer.putShort(start + 4, (short) 1); // CLASS IN
buffer.putInt(start + 6, answer.getTtl());

byte[] rdata = parseRDATA(answer.getType(), answer.getData());
buffer.putShort(start + 10, (short) rdata.length);
buffer.position(start + 12);
buffer.put(rdata);

return start + 12 + rdata.length;
}

private static byte[] parseRDATA(int type, String data) throws UnknownHostException {
switch (type) {
case 1: // A record
return InetAddress.getByName(data).getAddress();
case 28: // AAAA record
return InetAddress.getByName(data).getAddress();
case 5: // CNAME record
case 16: // TXT record
default:
return data.getBytes();
}
}
Поэтому полученный пакет от buildDNSResponse() неверен, и я не уверен, в чем заключается проблема.

Подробнее здесь: https://stackoverflow.com/questions/790 ... olving-dns
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»