Arhn - архитектура программирования

DNS через TLS — сокет закрыт

Итак, моя ситуация заключается в том, что я проксирую все пользовательские DNS-запросы на устройстве Android и либо разрешаю их с помощью локальной базы данных, либо перенаправляю их на какой-либо вышестоящий DNS-сервер. С некоторым большим интересом к DNS по сравнению с TLS в последнее время я попытался реализовать его в соответствии с rfc.
Поскольку все это делается на мобильном устройстве, я не хочу устанавливать новое TLS-соединение для каждого прокси-запроса (в сумме это составит около 6,7 КБ), потому что пользователь может использовать мобильное соединение.< br> Короче говоря, в rfc говорится следующее:

[...] этот документ предусматривает, что успешное согласование TLS указывает на готовность обеих сторон оставить незанятые соединения DNS открытыми, независимо от тайм-аутов или других рекомендаций для DNS через TCP без TLS

Я использую следующий код для отправки тестовых запросов и оценки результата (урезан для удобства чтения):

private void tlsTest(){
    Socket s = establishConnection("1.1.1.1"); //Cloudflare in this example, reproducible for Quad9 as well
    DataInputStream in; //Created from the Socket
    DataOutputStream out; //Created from the Socket
    for (int i = 0; i < 20; i++) {
        byte[] data = dnsRequestTypeA("google.com");
        data = new DatagramPacket(data, 0, data.length, destination, 853).getData();
        out.writeShort(data.length);
        out.write(data);
        out.flush();
        int times = 0;
        while((message = readDNSMessage(in)) == null && ++times <= 10){
            Thread.sleep(200);
        }
        System.out.println("Response: " + message);
        Thread.sleep(2500);
    }
}

private DNSMessage readDNSMessage(DataInputStream in) throws IOException {
    byte[] lengthBytes = new byte[2];
    if(in.read(lengthBytes) < 0)return null;
    // Each DNS answer is preceded with an unsigned short giving the length of the packet
    int length = (lengthBytes[0]&0xFF) + ((lengthBytes[1] &0xFF) << 8);
    byte[] data = new byte[length];
    in.read(data);
    return new DNSMessage(data);
}

@NonNull
private Socket establishConnection(String host) throws IOException {
    Socket socket = getSocketFactory().createSocket(host, 853);
    socket.setKeepAlive(true);
    return socket;
}

Проблема здесь в том, что сервер вроде бы закрывает соединение (обозначается сломанной трубой, выброшенной при попытке отправить запрос [ssl=0x7ebb528840: I/O error during system call, Broken pipe]), когда запроса не было в течение короткого времени (около 1-2 секунд в моих тестах).
У кого-нибудь есть опыт? Я делаю что-то не так (может быть, это как-то связано с реализацией OpenSSL, которую Android использует для TLS)? Очевидно, что просто спамить сервер каждую секунду или около того фиктивными запросами будет работать, но это будет очень хакерский обходной путь.

20.04.2018

  • Вы ничего не можете сделать с соединением, которое уже было закрыто узлом. 09.03.2019
  • Да, я знаю, я сначала спросил, у кого-нибудь было то же самое или я сделал что-то не так. Но с тех пор я узнал, что серверы dns-over-tls не соответствуют RFC в отношении поддержания сеанса tls и просто завершают его после одного запроса. 09.03.2019

Ответы:


1

После некоторого времени отладки я не смог найти прямого решения. Я не использовал такие инструменты, как Wireshark, во время написания этой статьи, чтобы определить неисправную реализацию, но пока прибегнул к другому способу решения этой проблемы;

Я просто поддерживаю сокеты в рабочем состоянии как можно дольше ( если отправка пакета не удалась, он повторяется не более 5 раз, прежде чем выдается исключение). Кроме того, я кэшировал все запросы, но, поскольку это довольно сильно повлияло на производительность/использование ресурсов, я снова отказался от него.

23.04.2018
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..