Как я могу обойти неразрешенную ошибку имени хоста или нераспознанного имени, используя HTTP (S) в Java или Python?

Я пытаюсь получить доступ к информации веб-сайта программным способом, но как на Java, так и на Python не удается разрешить имя хоста. Если я укажу IP-адрес, ошибка изменится на TLSV1_UNRECOGNIZED_NAME. Однако этот веб-сайт можно разрешить без каких-либо дополнительных действий через любой браузер.

Я просмотрел здесь множество потенциальных решений, но для Python написано, что эта проблема должна была быть решена в версии 2.7 или 2.8, но я использую 3.10 и все еще получаю эту ошибку. В Java утверждается, что это известная ошибка, но представленные решения, такие как удаление заголовка SNI с помощью параметра компиляции или передача пустого массива имен хостов в HTTPSURLConnection для отмены создания заголовка SNI, не решают проблему. Я также попробовал установить пользовательский агент на Mozilla, как предложено в ответе здесь, но это тоже ничего не изменило.

Я уверен, что на веб-сайте есть что-то необычное, но он не принадлежит мне, поэтому я не могу многое проверить о его конфигурации.

В частности, веб-сайт, который я пытаюсь увидеть:

URL -> https://epic7db.com/heroes
IP -> 157.230.84.20
DNS Lookup -> https://www.nslookup.io/domains/epic7db.com/webservers/

При локальном использовании nslookup я получаю следующее:

nslookup epic7db.com
Server:  UnKnown
Address:  10.0.0.1

Non-authoritative answer:
Name:    epic7db.com
Address:  157.230.84.20

Любая помощь будет оценена по достоинству, поскольку я, по сути, швыряю вещи в стену, чтобы посмотреть, что прилипнет к этому моменту.

Обновлено: Добавление примеров кода. Питон:

import requests

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} # This is chrome, you can set whatever browser you like
url = 'https://epic7db.com'
a = requests.get(url,headers)
print(a.content)

Котлин с использованием Java HttpsUrlConnection:

import http.SSLSocketFactoryWrapper
import java.net.URL
import javax.net.ssl.*


fun main() {

    HttpsURLConnection.setDefaultHostnameVerifier { hostName, session -> true }
    val url = URL("https://epic7db.com")
    val sslParameters = SSLParameters()
    val sniHostNames: MutableList<SNIHostName> = ArrayList<SNIHostName>(1)
//    sniHostNames.add(SNIHostName(url.getHost()))
    sslParameters.setServerNames(sniHostNames as List<SNIServerName>?)
    val wrappedSSLSocketFactory: SSLSocketFactory =
        SSLSocketFactoryWrapper(SSLContext.getDefault().socketFactory, sslParameters)
    HttpsURLConnection.setDefaultSSLSocketFactory(wrappedSSLSocketFactory)

    val conn = url.openConnection() as HttpsURLConnection
    conn.hostnameVerifier = HostnameVerifier { s: String?, sslSession: SSLSession? -> true }
    println(String(conn.inputStream.readAllBytes()))
}

Предлагаемый вспомогательный класс в Kotlin/Java:

package http;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class SSLSocketFactoryWrapper extends SSLSocketFactory {

    private final SSLSocketFactory wrappedFactory;
    private final SSLParameters sslParameters;

    public SSLSocketFactoryWrapper(SSLSocketFactory factory, SSLParameters sslParameters) {
        this.wrappedFactory = factory;
        this.sslParameters = sslParameters;
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
        setParameters(socket);
        return socket;
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
            throws IOException, UnknownHostException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port, localHost, localPort);
        setParameters(socket);
        return socket;
    }


    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
        setParameters(socket);
        return socket;
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(address, port, localAddress, localPort);
        setParameters(socket);
        return socket;

    }

    @Override
    public Socket createSocket() throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket();
        setParameters(socket);
        return socket;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return wrappedFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return wrappedFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(s, host, port, autoClose);
        setParameters(socket);
        return socket;
    }

    private void setParameters(SSLSocket socket) {
        socket.setSSLParameters(sslParameters);
    }

}

«невозможно разрешить имя хоста» — покажите код, выдающий эту ошибку.

Thorbjørn Ravn Andersen 04.08.2024 06:15

Добавлен пример ошибки имени хоста на Kotlin/Java и Python.

KM529 04.08.2024 06:20

Если код не может разрешить имя домена, но браузер на том же компьютере может это сделать, то браузер, скорее всего, использует либо прокси-сервер, который разрешает имя вместо браузера, либо другой DNS-сервер. Узнайте, что из этого сделано в вашем случае, проверив конфигурацию браузера, а затем сделайте то же самое в своем коде.

Steffen Ullrich 04.08.2024 06:30

«Java утверждает, что это известная ошибка» — Ссылка на авторитетный источник этого факта.

Basil Bourque 04.08.2024 06:36

Код Python работает у меня после установки модуля запросов. Что-то еще сломано.

Thorbjørn Ravn Andersen 04.08.2024 06:44

@ThorbjørnRavnAndersen работает с этим адресом и никаких дополнительных изменений?

KM529 04.08.2024 06:54

@BasilBourque Не могу найти вторую ссылку, но одна из них stackoverflow.com/questions/7615645/…

KM529 04.08.2024 06:55

@KM529 да. Точный код, который вы показали. Я предполагаю, что вы на работе, и конфигурация вашей сети не такая, как вы думаете.

Thorbjørn Ravn Andersen 04.08.2024 07:00
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
8
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как я могу обойти неразрешенную ошибку имени хоста или нераспознанного имени, используя HTTP (S) в Java или Python?

Скорее всего, это не проблема кода Java или Python1. Неспособность разрешить DNS-имя, скорее всего, вызвана:

  1. не обращается к правильному DNS-серверу(ам) или
  2. сбой на авторитетном сервере или
  3. изменение на авторитетном сервере, которое еще не распространилось.

(И 3. скорее всего, это будет проявляться в том, что DNS-имя разрешается в неправильный IP-адрес, а не в сбое разрешения. Прочтите о TTL-записях DNS.)

Так что... этого >в программе< не обойти. Вы можете обойти эту проблему, заглянув за пределы программы и выяснив, почему не удается разрешить DNS. Затем вы вносите изменения, чтобы это исправить.

Несколько причин, по которым браузер может работать, а приложение Java или Python — нет (или наоборот):

  1. Браузер может быть настроен на отправку всех HTTP/HTTPS-запросов через прокси. Прокси-сервер может иметь другой доступ к DNS для компьютера, на котором вы запускаете свой код.

  2. В случае с Java (по крайней мере, в Linux) у Java есть собственный способ настройки «локального» DNS-сервера. Обычно это не проблема, но иногда это может означать, что ваше приложение и браузер используют разные серверы.


Когда вы попытались использовать IP-адрес в URL-адресе, вы пропустили этап поиска DNS. Но тут вы столкнулись с проблемой, что сертификаты TLS не будут работать с IP-адресами. (Вы можете «взломать» это, но такие взломы могут иметь потенциально серьезные последствия для безопасности.)


1 - As others have pointed out, there is nothing wrong with the code you added to the question. Indeed, Thorbjørn attests that the code works for him exactly as written!

Другие вопросы по теме